]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge tag 'reset-fixes-for-4.14' of git://git.pengutronix.de/git/pza/linux into fixes
authorOlof Johansson <olof@lixom.net>
Wed, 4 Oct 2017 01:10:12 +0000 (18:10 -0700)
committerOlof Johansson <olof@lixom.net>
Wed, 4 Oct 2017 01:10:12 +0000 (18:10 -0700)
Reset controller fixes for v4.14

- Remove misleading HSDK v1 suffix, as there is no v2 planned
- Add missing DT binding documentation for HSDK reset driver
- Fix HSDK reset driver dependencies

* tag 'reset-fixes-for-4.14' of git://git.pengutronix.de/git/pza/linux:
  reset: Restrict RESET_HSDK to ARC_SOC_HSDK or COMPILE_TEST
  ARC: reset: remove the misleading v1 suffix all over
  ARC: reset: add missing DT binding documentation for HSDKv1 reset driver
  ARC: reset: Only build on archs that have IOMEM

Signed-off-by: Olof Johansson <olof@lixom.net>
588 files changed:
Documentation/cpu-freq/index.txt
Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
Documentation/devicetree/bindings/leds/ams,as3645a.txt
Documentation/devicetree/bindings/security/tpm/tpm-i2c.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/driver-api/pm/devices.rst
Documentation/filesystems/cifs/AUTHORS
Documentation/filesystems/cifs/README
Documentation/filesystems/cifs/TODO
Documentation/filesystems/cifs/cifs.txt
Documentation/networking/filter.txt
Documentation/networking/ip-sysctl.txt
Documentation/networking/switchdev.txt
Documentation/sysctl/kernel.txt
Documentation/userspace-api/seccomp_filter.rst
MAINTAINERS
Makefile
arch/arc/include/asm/processor.h
arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
arch/arm/boot/dts/da850-evm.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/configs/gemini_defconfig
arch/arm/configs/pxa_defconfig
arch/arm/configs/viper_defconfig
arch/arm/configs/zeus_defconfig
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/uaccess.h
arch/arm/kernel/entry-common.S
arch/arm/kernel/signal.c
arch/arm/mach-at91/pm.c
arch/arm64/Makefile
arch/arm64/include/asm/linkage.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/head.S
arch/arm64/kernel/signal.c
arch/arm64/mm/fault.c
arch/c6x/include/asm/processor.h
arch/frv/include/asm/processor.h
arch/m32r/include/asm/processor.h
arch/metag/include/asm/processor.h
arch/microblaze/Kconfig
arch/microblaze/include/uapi/asm/Kbuild
arch/microblaze/kernel/dma.c
arch/mips/ath79/pci.c
arch/mips/include/asm/mipsregs.h
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/pci/fixup-capcella.c
arch/mips/pci/fixup-cobalt.c
arch/mips/pci/fixup-emma2rh.c
arch/mips/pci/fixup-fuloong2e.c
arch/mips/pci/fixup-ip32.c
arch/mips/pci/fixup-jmr3927.c
arch/mips/pci/fixup-lantiq.c
arch/mips/pci/fixup-lemote2f.c
arch/mips/pci/fixup-loongson3.c
arch/mips/pci/fixup-malta.c
arch/mips/pci/fixup-mpc30x.c
arch/mips/pci/fixup-pmcmsp.c
arch/mips/pci/fixup-rbtx4927.c
arch/mips/pci/fixup-rbtx4938.c
arch/mips/pci/fixup-sni.c
arch/mips/pci/fixup-tb0219.c
arch/mips/pci/fixup-tb0226.c
arch/mips/pci/fixup-tb0287.c
arch/mips/pci/pci-alchemy.c
arch/mips/pci/pci-bcm47xx.c
arch/mips/pci/pci-lasat.c
arch/mips/pci/pci-mt7620.c
arch/mips/pci/pci-octeon.c
arch/mips/pci/pci-rt2880.c
arch/mips/pci/pci-rt3883.c
arch/mips/pci/pci-tx4938.c
arch/mips/pci/pci-tx4939.c
arch/mips/pci/pci-xlp.c
arch/mips/pci/pci-xlr.c
arch/mips/pci/pcie-octeon.c
arch/mips/pmcs-msp71xx/msp_smp.c
arch/mips/txx9/generic/pci.c
arch/mn10300/kernel/process.c
arch/parisc/Kconfig
arch/parisc/Makefile
arch/parisc/boot/compressed/Makefile
arch/parisc/boot/compressed/misc.c
arch/parisc/include/asm/pdc.h
arch/parisc/include/asm/smp.h
arch/parisc/kernel/firmware.c
arch/parisc/kernel/pdt.c
arch/parisc/kernel/processor.c
arch/parisc/kernel/setup.c
arch/parisc/kernel/smp.c
arch/parisc/kernel/traps.c
arch/parisc/kernel/unwind.c
arch/parisc/mm/fault.c
arch/powerpc/configs/g5_defconfig
arch/powerpc/configs/gamecube_defconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/configs/pmac32_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/ppc64e_defconfig
arch/powerpc/configs/ppc6xx_defconfig
arch/powerpc/configs/wii_defconfig
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_dev.c
arch/powerpc/kernel/optprobes.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/traps.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/lib/sstep.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/platforms/powernv/idle.c
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/mobility.c
arch/s390/include/asm/pgtable.h
arch/s390/kernel/early.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/topology.c
arch/s390/mm/gup.c
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/processor_64.h
arch/tile/configs/tilegx_defconfig
arch/tile/configs/tilepro_defconfig
arch/tile/kernel/setup.c
arch/um/include/asm/processor-generic.h
arch/um/kernel/time.c
arch/x86/crypto/blowfish-x86_64-asm_64.S
arch/x86/crypto/camellia-x86_64-asm_64.S
arch/x86/crypto/cast5-avx-x86_64-asm_64.S
arch/x86/crypto/cast6-avx-x86_64-asm_64.S
arch/x86/crypto/des3_ede-asm_64.S
arch/x86/crypto/sha1_avx2_x86_64_asm.S
arch/x86/crypto/sha1_ssse3_asm.S
arch/x86/crypto/sha256-avx-asm.S
arch/x86/crypto/sha256-avx2-asm.S
arch/x86/crypto/sha256-ssse3-asm.S
arch/x86/crypto/sha512-avx2-asm.S
arch/x86/crypto/twofish-avx-x86_64-asm_64.S
arch/x86/events/intel/cstate.c
arch/x86/events/intel/rapl.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/events/msr.c
arch/x86/ia32/ia32_signal.c
arch/x86/include/asm/alternative.h
arch/x86/include/asm/asm.h
arch/x86/include/asm/fpu/internal.h
arch/x86/include/asm/fpu/types.h
arch/x86/include/asm/fpu/xstate.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/mshyperv.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/preempt.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/rwsem.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/trace/fpu.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/fpu/core.c
arch/x86/kernel/fpu/init.c
arch/x86/kernel/fpu/regset.c
arch/x86/kernel/fpu/signal.c
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/ksysfs.c
arch/x86/kernel/kvm.c
arch/x86/kernel/signal.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/traps.c
arch/x86/kvm/emulate.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/math-emu/fpu_entry.c
arch/x86/mm/extable.c
arch/x86/mm/fault.c
arch/x86/mm/mem_encrypt.c
arch/x86/mm/pkeys.c
arch/x86/mm/tlb.c
arch/x86/xen/mmu_pv.c
arch/xtensa/include/asm/processor.h
block/blk-core.c
block/bsg-lib.c
block/partition-generic.c
crypto/af_alg.c
crypto/drbg.c
drivers/acpi/acpi_watchdog.c
drivers/acpi/apei/ghes.c
drivers/acpi/property.c
drivers/base/dma-coherent.c
drivers/base/power/main.c
drivers/base/power/opp/core.c
drivers/base/power/qos.c
drivers/block/brd.c
drivers/block/loop.h
drivers/block/nbd.c
drivers/char/tpm/tpm-interface.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_crb.c
drivers/char/tpm/tpm_ibmvtpm.c
drivers/char/tpm/tpm_infineon.c
drivers/char/tpm/tpm_tis_core.c
drivers/clocksource/numachip.c
drivers/clocksource/timer-integrator-ap.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/ti-cpufreq.c
drivers/cpuidle/cpuidle-arm.c
drivers/crypto/caam/Kconfig
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/regs.h
drivers/crypto/inside-secure/safexcel_cipher.c
drivers/crypto/inside-secure/safexcel_hash.c
drivers/crypto/talitos.c
drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
drivers/gpu/drm/amd/amdkfd/kfd_events.c
drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
drivers/gpu/drm/etnaviv/etnaviv_gem.c
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
drivers/gpu/drm/exynos/exynos5433_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.h
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/i915/gvt/cfg_space.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/sun4i/Kconfig
drivers/gpu/drm/sun4i/sun4i_hdmi.h
drivers/gpu/drm/tegra/trace.h
drivers/infiniband/core/security.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/bnxt_re/bnxt_re.h
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/chip.h
drivers/infiniband/hw/hfi1/eprom.c
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/hfi1/pcie.c
drivers/infiniband/hw/hfi1/platform.c
drivers/infiniband/hw/i40iw/i40iw.h
drivers/infiniband/hw/i40iw/i40iw_cm.c
drivers/infiniband/hw/i40iw/i40iw_cm.h
drivers/infiniband/hw/i40iw/i40iw_main.c
drivers/infiniband/hw/i40iw/i40iw_utils.c
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mem.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/hw/ocrdma/ocrdma_hw.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_vlan.c
drivers/infiniband/ulp/iser/iser_memory.c
drivers/input/ff-core.c
drivers/input/misc/uinput.c
drivers/input/mouse/elan_i2c_i2c.c
drivers/iommu/Kconfig
drivers/iommu/amd_iommu_init.c
drivers/iommu/dmar.c
drivers/iommu/io-pgtable-arm-v7s.c
drivers/iommu/mtk_iommu.c
drivers/iommu/of_iommu.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic-v4.c
drivers/irqchip/irq-mips-gic.c
drivers/isdn/i4l/isdn_ppp.c
drivers/leds/leds-as3645a.c
drivers/md/dm-raid.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid5.c
drivers/mmc/core/queue.c
drivers/mmc/host/Kconfig
drivers/mmc/host/cavium-thunderx.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/tmio_mmc_core.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/atmel/pmecc.c
drivers/mtd/nand/lpc32xx_mlc.c
drivers/mtd/nand/nand_base.c
drivers/mtd/spi-nor/spi-nor.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/hisilicon/hns3/hnae3.c
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
drivers/net/ethernet/ibm/emac/mal.c
drivers/net/ethernet/qualcomm/emac/emac-ethtool.c
drivers/net/ethernet/qualcomm/emac/emac-mac.c
drivers/net/ethernet/qualcomm/emac/emac.c
drivers/net/ethernet/qualcomm/emac/emac.h
drivers/net/ethernet/realtek/8139too.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/phy/Kconfig
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/xilinx_gmii2rgmii.c
drivers/net/usb/lan78xx.c
drivers/nvdimm/namespace_devs.c
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/fc.c
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/target/core.c
drivers/nvme/target/fabrics-cmd.c
drivers/nvme/target/fc.c
drivers/nvme/target/fcloop.c
drivers/nvme/target/nvmet.h
drivers/pci/endpoint/functions/pci-epf-test.c
drivers/pci/pci-sysfs.c
drivers/perf/arm_pmu_acpi.c
drivers/platform/x86/fujitsu-laptop.c
drivers/s390/block/dasd.c
drivers/s390/block/scm_blk.c
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_fsm.c
drivers/s390/cio/io_sch.h
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/src.c
drivers/scsi/arm/acornscsi.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nvme.c
drivers/scsi/qla2xxx/qla_nvme.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/xen/xen-pciback/conf_space_header.c
drivers/xen/xenbus/xenbus_client.c
fs/btrfs/compression.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/send.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/cifs/cifs_debug.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/direct-io.c
fs/fcntl.c
fs/gfs2/glock.c
fs/iomap.c
fs/isofs/inode.c
fs/proc/array.c
fs/quota/dquot.c
fs/quota/quota_v2.c
fs/read_write.c
fs/xfs/libxfs/xfs_ag_resv.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_error.c
fs/xfs/xfs_file.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_iomap.h
fs/xfs/xfs_pnfs.c
fs/xfs/xfs_super.c
include/acpi/acpi_bus.h
include/linux/audit.h
include/linux/blkdev.h
include/linux/cpuhotplug.h
include/linux/device.h
include/linux/input.h
include/linux/iommu.h
include/linux/irq.h
include/linux/key.h
include/linux/nvme-fc-driver.h
include/linux/nvme.h
include/linux/of_platform.h
include/linux/pci.h
include/linux/sched.h
include/linux/seccomp.h
include/linux/syscalls.h
include/linux/timer.h
include/linux/trace_events.h
include/net/dst.h
include/net/route.h
include/net/sock.h
include/net/tcp.h
include/rdma/ib_verbs.h
include/trace/events/sched.h
include/uapi/linux/ethtool.h
include/uapi/linux/kfd_ioctl.h
include/uapi/linux/seccomp.h
include/uapi/rdma/ib_user_verbs.h
include/xen/arm/page.h
ipc/shm.c
kernel/bpf/devmap.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cpu.c
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/exit.c
kernel/extable.c
kernel/futex.c
kernel/irq/chip.c
kernel/irq/generic-chip.c
kernel/irq/irqdomain.c
kernel/irq/manage.c
kernel/locking/rwsem-xadd.c
kernel/rcu/tree.c
kernel/sched/core.c
kernel/sched/debug.c
kernel/seccomp.c
kernel/sysctl.c
kernel/trace/blktrace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_mmiotrace.c
kernel/trace/trace_output.c
kernel/trace/trace_sched_wakeup.c
kernel/trace/trace_stack.c
lib/Kconfig.debug
lib/iov_iter.c
lib/rhashtable.c
mm/filemap.c
net/bluetooth/Kconfig
net/bluetooth/hci_sock.c
net/ceph/osdmap.c
net/compat.c
net/core/dev.c
net/core/ethtool.c
net/core/filter.c
net/ipv4/inet_connection_sock.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/udp.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/nf_nat_core.c
net/packet/af_packet.c
net/sched/cls_flower.c
net/sched/cls_matchall.c
net/sched/sch_generic.c
net/sched/sch_hfsc.c
net/smc/af_smc.c
net/smc/smc.h
net/smc/smc_clc.c
net/smc/smc_clc.h
net/smc/smc_close.c
net/smc/smc_core.c
net/smc/smc_ib.c
net/smc/smc_pnet.c
net/smc/smc_rx.c
net/smc/smc_tx.c
net/smc/smc_wr.c
net/sunrpc/xprtrdma/frwr_ops.c
net/wireless/nl80211.c
scripts/Makefile.build
scripts/dtc/dtx_diff
scripts/mkversion [deleted file]
scripts/package/Makefile
scripts/package/builddeb
scripts/package/mkspec
security/apparmor/.gitignore
security/apparmor/Makefile
security/apparmor/apparmorfs.c
security/apparmor/domain.c
security/apparmor/file.c
security/apparmor/include/apparmor.h
security/apparmor/include/audit.h
security/apparmor/include/domain.h
security/apparmor/include/ipc.h
security/apparmor/include/label.h
security/apparmor/include/mount.h [new file with mode: 0644]
security/apparmor/include/net.h [new file with mode: 0644]
security/apparmor/include/perms.h
security/apparmor/include/policy.h
security/apparmor/include/sig_names.h [new file with mode: 0644]
security/apparmor/ipc.c
security/apparmor/label.c
security/apparmor/lib.c
security/apparmor/lsm.c
security/apparmor/mount.c [new file with mode: 0644]
security/apparmor/net.c [new file with mode: 0644]
security/apparmor/policy.c
security/apparmor/policy_ns.c
security/apparmor/policy_unpack.c
security/commoncap.c
security/keys/Kconfig
security/keys/big_key.c
security/keys/internal.h
security/keys/key.c
security/keys/keyctl.c
security/keys/keyring.c
security/keys/proc.c
security/keys/process_keys.c
security/keys/request_key_auth.c
tools/arch/s390/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/disabled-features.h
tools/include/asm-generic/hugetlb_encode.h [new file with mode: 0644]
tools/include/uapi/asm-generic/mman-common.h
tools/include/uapi/drm/drm.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/bpf.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/mman.h
tools/objtool/Documentation/stack-validation.txt
tools/objtool/arch/x86/decode.c
tools/objtool/check.c
tools/objtool/elf.c
tools/perf/MANIFEST
tools/perf/arch/s390/util/Build
tools/perf/arch/s390/util/sym-handling.c [deleted file]
tools/perf/util/callchain.c
tools/perf/util/evsel.c
tools/perf/util/symbol-elf.c
tools/perf/util/symbol.h
tools/perf/util/syscalltbl.c
tools/testing/nvdimm/test/nfit.c
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/bpf_util.h
tools/testing/selftests/breakpoints/Makefile
tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
tools/testing/selftests/futex/Makefile
tools/testing/selftests/intel_pstate/Makefile
tools/testing/selftests/intel_pstate/run.sh
tools/testing/selftests/lib.mk
tools/testing/selftests/memfd/run_tests.sh [changed mode: 0644->0755]
tools/testing/selftests/mqueue/Makefile
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/msg_zerocopy.c
tools/testing/selftests/net/netdevice.sh
tools/testing/selftests/net/reuseaddr_conflict.c [new file with mode: 0644]
tools/testing/selftests/seccomp/Makefile
tools/testing/selftests/seccomp/seccomp_benchmark.c [new file with mode: 0644]
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/sigaltstack/sas.c
tools/testing/selftests/sync/Makefile
tools/testing/selftests/timers/set-timer-lat.c
tools/testing/selftests/watchdog/Makefile
virt/kvm/eventfd.c

index 03a7cee6ac73a4f2dd48248196994538d81f6a4e..c15e75386a0523d5398290aa9a63cc1d9f40f45e 100644 (file)
@@ -32,8 +32,6 @@ cpufreq-stats.txt -   General description of sysfs cpufreq stats.
 
 index.txt      -       File index, Mailing list and Links (this document)
 
-intel-pstate.txt -     Intel pstate cpufreq driver specific file.
-
 pcc-cpufreq.txt -      PCC cpufreq driver specific file.
 
 
index a135504c7d57148b938285919130d8dfc8fa18d3..cac24ee10b72ebc3765d29708fa27c5ae6848950 100644 (file)
@@ -32,7 +32,7 @@ Example:
                compatible = "st,stm32h743-rcc", "st,stm32-rcc";
                reg = <0x58024400 0x400>;
                #reset-cells = <1>;
-               #clock-cells = <2>;
+               #clock-cells = <1>;
                clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>;
 
                st,syscfg = <&pwrcfg>;
index 12c5ef26ec73924566361aa2ad96710d1e12b210..fdc40e354a64dd582d86841afac520a73d6fa5f0 100644 (file)
@@ -15,11 +15,14 @@ Required properties
 
 compatible     : Must be "ams,as3645a".
 reg            : The I2C address of the device. Typically 0x30.
+#address-cells : 1
+#size-cells    : 0
 
 
-Required properties of the "flash" child node
-=============================================
+Required properties of the flash child node (0)
+===============================================
 
+reg: 0
 flash-timeout-us: Flash timeout in microseconds. The value must be in
                  the range [100000, 850000] and divisible by 50000.
 flash-max-microamp: Maximum flash current in microamperes. Has to be
@@ -33,20 +36,21 @@ ams,input-max-microamp: Maximum flash controller input current. The
                        and divisible by 50000.
 
 
-Optional properties of the "flash" child node
-=============================================
+Optional properties of the flash child node
+===========================================
 
 label          : The label of the flash LED.
 
 
-Required properties of the "indicator" child node
-=================================================
+Required properties of the indicator child node (1)
+===================================================
 
+reg: 1
 led-max-microamp: Maximum indicator current. The allowed values are
                  2500, 5000, 7500 and 10000.
 
-Optional properties of the "indicator" child node
-=================================================
+Optional properties of the indicator child node
+===============================================
 
 label          : The label of the indicator LED.
 
@@ -55,16 +59,20 @@ Example
 =======
 
        as3645a@30 {
+               #address-cells: 1
+               #size-cells: 0
                reg = <0x30>;
                compatible = "ams,as3645a";
-               flash {
+               flash@0 {
+                       reg = <0x0>;
                        flash-timeout-us = <150000>;
                        flash-max-microamp = <320000>;
                        led-max-microamp = <60000>;
                        ams,input-max-microamp = <1750000>;
                        label = "as3645a:flash";
                };
-               indicator {
+               indicator@1 {
+                       reg = <0x1>;
                        led-max-microamp = <10000>;
                        label = "as3645a:indicator";
                };
index 3eca6de6369d773ef70bba048345aaed1d2737df..a65d7b71e81a2a22bfc23ab79ede461a25d2de37 100644 (file)
@@ -8,6 +8,12 @@ Required properties:
                    the firmware event log
 - linux,sml-size : size of the memory allocated for the firmware event log
 
+Optional properties:
+
+- powered-while-suspended: present when the TPM is left powered on between
+                           suspend and resume (makes the suspend/resume
+                           callbacks do nothing).
+
 Example (for OpenPower Systems with Nuvoton TPM 2.0 on I2C)
 ----------------------------------------------------------
 
index 1ea1fd4232ab2ac9c0e736169ef98a02e05ccf8b..1afd298eddd73147ebf6a1dcbc56bf404559cff1 100644 (file)
@@ -3,8 +3,8 @@ Device tree binding vendor prefix registry.  Keep list in alphabetical order.
 This isn't an exhaustive list, but you should add new prefixes to it before
 using them to avoid name-space collisions.
 
-abcn   Abracon Corporation
 abilis Abilis Systems
+abracon        Abracon Corporation
 actions        Actions Semiconductor Co., Ltd.
 active-semi    Active-Semi International Inc
 ad     Avionic Design GmbH
index bedd32388dac51d8a603dd1389c3b4de24807d7a..a0dc2879a152c89dbb9d5f715ec07fbfe6a4cd8e 100644 (file)
@@ -675,7 +675,7 @@ sub-domain of the parent domain.
 
 Support for power domains is provided through the :c:member:`pm_domain` field of
 |struct device|.  This field is a pointer to an object of type
-|struct dev_pm_domain|, defined in :file:`include/linux/pm.h``, providing a set
+|struct dev_pm_domain|, defined in :file:`include/linux/pm.h`, providing a set
 of power management callbacks analogous to the subsystem-level and device driver
 callbacks that are executed for the given device during all power transitions,
 instead of the respective subsystem-level callbacks.  Specifically, if a
index c98800df677fef0e18103415af6a0333e8c6a10a..9f4f87e1624036349533adf9534bfd3c4b08535d 100644 (file)
@@ -41,6 +41,11 @@ Igor Mammedov (DFS support)
 Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
 Scott Lovenberg
 Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features)
+Aurelien Aptel (for DFS SMB3 work and some key bug fixes)
+Ronnie Sahlberg (for SMB3 xattr work and bug fixes)
+Shirish Pargaonkar (for many ACL patches over the years)
+Sachin Prabhu (many bug fixes, including for reconnect, copy offload and security)
+
 
 Test case and Bug Report contributors
 -------------------------------------
index a54788405429dce03af2dd950f6dd817df0d9a56..a9da51553ba3e15049c17aecbad840eb607ef056 100644 (file)
@@ -1,10 +1,14 @@
-The CIFS VFS support for Linux supports many advanced network filesystem 
-features such as hierarchical dfs like namespace, hardlinks, locking and more.  
+This module supports the SMB3 family of advanced network protocols (as well
+as older dialects, originally called "CIFS" or SMB1).
+
+The CIFS VFS module for Linux supports many advanced network filesystem
+features such as hierarchical DFS like namespace, hardlinks, locking and more.
 It was designed to comply with the SNIA CIFS Technical Reference (which 
 supersedes the 1992 X/Open SMB Standard) as well as to perform best practice 
 practical interoperability with Windows 2000, Windows XP, Samba and equivalent 
 servers.  This code was developed in participation with the Protocol Freedom
-Information Foundation.
+Information Foundation.  CIFS and now SMB3 has now become a defacto
+standard for interoperating between Macs and Windows and major NAS appliances.
 
 Please see
   http://protocolfreedom.org/ and
@@ -15,30 +19,11 @@ for more details.
 For questions or bug reports please contact:
     sfrench@samba.org (sfrench@us.ibm.com) 
 
+See the project page at: https://wiki.samba.org/index.php/LinuxCIFS_utils
+
 Build instructions:
 ==================
-For Linux 2.4:
-1) Get the kernel source (e.g.from http://www.kernel.org)
-and download the cifs vfs source (see the project page
-at http://us1.samba.org/samba/Linux_CIFS_client.html)
-and change directory into the top of the kernel directory
-then patch the kernel (e.g. "patch -p1 < cifs_24.patch") 
-to add the cifs vfs to your kernel configure options if
-it has not already been added (e.g. current SuSE and UL
-users do not need to apply the cifs_24.patch since the cifs vfs is
-already in the kernel configure menu) and then
-mkdir linux/fs/cifs and then copy the current cifs vfs files from
-the cifs download to your kernel build directory e.g.
-
-       cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
-       
-2) make menuconfig (or make xconfig)
-3) select cifs from within the network filesystem choices
-4) save and exit
-5) make dep
-6) make modules (or "make" if CIFS VFS not to be built as a module)
-
-For Linux 2.6:
+For Linux:
 1) Download the kernel (e.g. from http://www.kernel.org)
 and change directory into the top of the kernel directory tree
 (e.g. /usr/src/linux-2.5.73)
@@ -61,16 +46,13 @@ would simply type "make install").
 If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on 
 the CIFS VFS web site) copy it to the same directory in which mount.smbfs and 
 similar files reside (usually /sbin).  Although the helper software is not  
-required, mount.cifs is recommended.  Eventually the Samba 3.0 utility program 
-"net" may also be helpful since it may someday provide easier mount syntax for
-users who are used to Windows e.g.
-       net use <mount point> <UNC name or cifs URL>
+required, mount.cifs is recommended.  Most distros include a "cifs-utils"
+package that includes this utility so it is recommended to install this.
+
 Note that running the Winbind pam/nss module (logon service) on all of your
 Linux clients is useful in mapping Uids and Gids consistently across the
 domain to the proper network user.  The mount.cifs mount helper can be
-trivially built from Samba 3.0 or later source e.g. by executing:
-
-       gcc samba/source/client/mount.cifs.c -o mount.cifs
+found at cifs-utils.git on git.samba.org
 
 If cifs is built as a module, then the size and number of network buffers
 and maximum number of simultaneous requests to one server can be configured.
@@ -79,6 +61,18 @@ Changing these from their defaults is not recommended. By executing modinfo
 on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made
 at module initialization time (by running insmod cifs.ko) can be seen.
 
+Recommendations
+===============
+To improve security the SMB2.1 dialect or later (usually will get SMB3) is now
+the new default. To use old dialects (e.g. to mount Windows XP) use "vers=1.0"
+on mount (or vers=2.0 for Windows Vista).  Note that the CIFS (vers=1.0) is
+much older and less secure than the default dialect SMB3 which includes
+many advanced security features such as downgrade attack detection
+and encrypted shares and stronger signing and authentication algorithms.
+There are additional mount options that may be helpful for SMB3 to get
+improved POSIX behavior (NB: can use vers=3.0 to force only SMB3, never 2.1):
+     "mfsymlinks" and "cifsacl" and "idsfromsid"
+
 Allowing User Mounts
 ====================
 To permit users to mount and unmount over directories they own is possible
@@ -98,9 +92,7 @@ and execution of suid programs on the remote target would be enabled
 by default. This can be changed, as with nfs and other filesystems, 
 by simply specifying "nosuid" among the mount options. For user mounts 
 though to be able to pass the suid flag to mount requires rebuilding 
-mount.cifs with the following flag: 
-        gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
+mount.cifs with the following flag: CIFS_ALLOW_USR_SUID
 
 There is a corresponding manual page for cifs mounting in the Samba 3.0 and
 later source tree in docs/manpages/mount.cifs.8 
@@ -189,18 +181,18 @@ applications running on the same server as Samba.
 Use instructions:
 ================
 Once the CIFS VFS support is built into the kernel or installed as a module 
-(cifs.o), you can use mount syntax like the following to access Samba or Windows 
-servers: 
+(cifs.ko), you can use mount syntax like the following to access Samba or
+Mac or Windows servers:
 
-  mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
+  mount -t cifs //9.53.216.11/e$ /mnt -o username=myname,password=mypassword
 
 Before -o the option -v may be specified to make the mount.cifs
 mount helper display the mount steps more verbosely.  
 After -o the following commonly used cifs vfs specific options
 are supported:
 
-  user=<username>
-  pass=<password>
+  username=<username>
+  password=<password>
   domain=<domain name>
   
 Other cifs mount options are described below.  Use of TCP names (in addition to
@@ -246,13 +238,16 @@ the Server's registry.  Samba starting with version 3.10 will allow such
 filenames (ie those which contain valid Linux characters, which normally
 would be forbidden for Windows/CIFS semantics) as long as the server is
 configured for Unix Extensions (and the client has not disabled
-/proc/fs/cifs/LinuxExtensionsEnabled).
-  
+/proc/fs/cifs/LinuxExtensionsEnabled). In addition the mount option
+"mapposix" can be used on CIFS (vers=1.0) to force the mapping of
+illegal Windows/NTFS/SMB characters to a remap range (this mount parm
+is the default for SMB3). This remap ("mapposix") range is also
+compatible with Mac (and "Services for Mac" on some older Windows).
 
 CIFS VFS Mount Options
 ======================
 A partial list of the supported mount options follows:
-  user         The user name to use when trying to establish
+  username     The user name to use when trying to establish
                the CIFS session.
   password     The user password.  If the mount helper is
                installed, the user will be prompted for password
index 066ffddc3964917d75287198ffd178daacc1cac6..396ecfd6ff4a0da40f099dfef57ef6111ae8da71 100644 (file)
@@ -1,4 +1,4 @@
-Version 2.03 August 1, 2014
+Version 2.04 September 13, 2017
 
 A Partial List of Missing Features
 ==================================
@@ -8,73 +8,69 @@ for visible, important contributions to this module.  Here
 is a partial list of the known problems and missing features:
 
 a) SMB3 (and SMB3.02) missing optional features:
-   - RDMA
+   - RDMA (started)
    - multichannel (started)
    - directory leases (improved metadata caching)
    - T10 copy offload (copy chunk is only mechanism supported)
-   - encrypted shares
 
 b) improved sparse file support
 
 c) Directory entry caching relies on a 1 second timer, rather than
-using FindNotify or equivalent.  - (started)
+using Directory Leases
 
 d) quota support (needs minor kernel change since quota calls
 to make it to network filesystems or deviceless filesystems)
 
-e) improve support for very old servers (OS/2 and Win9x for example)
-Including support for changing the time remotely (utimes command).
+e) Better optimize open to reduce redundant opens (using reference
+counts more) and to improve use of compounding in SMB3 to reduce
+number of roundtrips.
 
-f) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
-extra copy in/out of the socket buffers in some cases.
-
-g) Better optimize open (and pathbased setfilesize) to reduce the
-oplock breaks coming from windows srv.  Piggyback identical file
-opens on top of each other by incrementing reference count rather
-than resending (helps reduce server resource utilization and avoid
-spurious oplock breaks).
-
-h) Add support for storing symlink info to Windows servers
-in the Extended Attribute format their SFU clients would recognize.
-
-i) Finish inotify support so kde and gnome file list windows
+f) Finish inotify support so kde and gnome file list windows
 will autorefresh (partially complete by Asser). Needs minor kernel
 vfs change to support removing D_NOTIFY on a file.   
 
-j) Add GUI tool to configure /proc/fs/cifs settings and for display of
+g) Add GUI tool to configure /proc/fs/cifs settings and for display of
 the CIFS statistics (started)
 
-k) implement support for security and trusted categories of xattrs
+h) implement support for security and trusted categories of xattrs
 (requires minor protocol extension) to enable better support for SELINUX
 
-l) Implement O_DIRECT flag on open (already supported on mount)
+i) Implement O_DIRECT flag on open (already supported on mount)
 
-m) Create UID mapping facility so server UIDs can be mapped on a per
+j) Create UID mapping facility so server UIDs can be mapped on a per
 mount or a per server basis to client UIDs or nobody if no mapping
-exists.  This is helpful when Unix extensions are negotiated to
-allow better permission checking when UIDs differ on the server
-and client.  Add new protocol request to the CIFS protocol 
-standard for asking the server for the corresponding name of a
-particular uid.
+exists. Also better integration with winbind for resolving SID owners
+
+k) Add tools to take advantage of more smb3 specific ioctls and features
+
+l) encrypted file support
+
+m) improved stats gathering, tools (perhaps integration with nfsometer?)
 
-n) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
+n) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed
+file attribute via chflags) and improve user space tools for managing and
+viewing them.
 
-o) mount check for unmatched uids
+o) mount helper GUI (to simplify the various configuration options on mount)
 
-p) Add support for new vfs entry point for fallocate
+p) autonegotiation of dialects (offering more than one dialect ie SMB3.02,
+SMB3, SMB2.1 not just SMB3).
 
-q) Add tools to take advantage of cifs/smb3 specific ioctls and features
-such as "CopyChunk" (fast server side file copy)
+q) Allow mount.cifs to be more verbose in reporting errors with dialect
+or unsupported feature errors.
 
-r) encrypted file support
+r) updating cifs documentation, and user guid.
 
-s) improved stats gathering, tools (perhaps integration with nfsometer?)
+s) Addressing bugs found by running a broader set of xfstests in standard
+file system xfstest suite.
 
-t) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed
-file attribute via chflags)
+t) split cifs and smb3 support into separate modules so legacy (and less
+secure) CIFS dialect can be disabled in environments that don't need it
+and simplify the code.
 
-u) mount helper GUI (to simplify the various configuration options on mount)
+u) Finish up SMB3.1.1 dialect support
 
+v) POSIX Extensions for SMB3.1.1
 
 KNOWN BUGS
 ====================================
index 2fac91ac96cf7484aae9e148e5841755feba5f70..67756607246e767a9105bc06c00a7b97730abbb1 100644 (file)
@@ -1,24 +1,28 @@
-  This is the client VFS module for the Common Internet File System
-  (CIFS) protocol which is the successor to the Server Message Block 
+  This is the client VFS module for the SMB3 NAS protocol as well
+  older dialects such as the Common Internet File System (CIFS)
+  protocol which was the successor to the Server Message Block
   (SMB) protocol, the native file sharing mechanism for most early
   PC operating systems. New and improved versions of CIFS are now
   called SMB2 and SMB3. These dialects are also supported by the
   CIFS VFS module. CIFS is fully supported by network
-  file servers such as Windows 2000, 2003, 2008 and 2012
+  file servers such as Windows 2000, 2003, 2008, 2012 and 2016
   as well by Samba (which provides excellent CIFS
-  server support for Linux and many other operating systems), so
+  server support for Linux and many other operating systems), Apple
+  systems, as well as most Network Attached Storage vendors, so
   this network filesystem client can mount to a wide variety of
   servers.
 
   The intent of this module is to provide the most advanced network
-  file system function for CIFS compliant servers, including better
-  POSIX compliance, secure per-user session establishment, high
-  performance safe distributed caching (oplock), optional packet
+  file system function for SMB3 compliant servers, including advanced
+  security features, excellent parallelized high performance i/o, better
+  POSIX compliance, secure per-user session establishment, encryption,
+  high performance safe distributed caching (leases/oplocks), optional packet
   signing, large files, Unicode support and other internationalization
   improvements. Since both Samba server and this filesystem client support
-  the CIFS Unix extensions, the combination can provide a reasonable 
-  alternative to NFSv4 for fileserving in some Linux to Linux environments,
-  not just in Linux to Windows environments.
+  the CIFS Unix extensions (and in the future SMB3 POSIX extensions),
+  the combination can provide a reasonable alternative to other network and
+  cluster file systems for fileserving in some Linux to Linux environments,
+  not just in Linux to Windows (or Linux to Mac) environments.
 
   This filesystem has an mount utility (mount.cifs) that can be obtained from
 
index 789b74dbe1d96af46fae8a3504a242eaa0b11c3c..87814859cfc21c5c6a64c1dfb83a1d6cff596731 100644 (file)
@@ -337,7 +337,7 @@ Examples for low-level BPF:
   jeq #14, good           /* __NR_rt_sigprocmask */
   jeq #13, good           /* __NR_rt_sigaction */
   jeq #35, good           /* __NR_nanosleep */
-  bad: ret #0             /* SECCOMP_RET_KILL */
+  bad: ret #0             /* SECCOMP_RET_KILL_THREAD */
   good: ret #0x7fff0000   /* SECCOMP_RET_ALLOW */
 
 The above example code can be placed into a file (here called "foo"), and
index b3345d0fe0a67e477a6754848e7fc7be144322d5..77f4de59dc9ceb3cdb36692d1ea41e1d861468b0 100644 (file)
@@ -1680,6 +1680,9 @@ accept_dad - INTEGER
        2: Enable DAD, and disable IPv6 operation if MAC-based duplicate
           link-local address has been found.
 
+       DAD operation and mode on a given interface will be selected according
+       to the maximum value of conf/{all,interface}/accept_dad.
+
 force_tllao - BOOLEAN
        Enable sending the target link-layer address option even when
        responding to a unicast neighbor solicitation.
@@ -1727,16 +1730,23 @@ suppress_frag_ndisc - INTEGER
 
 optimistic_dad - BOOLEAN
        Whether to perform Optimistic Duplicate Address Detection (RFC 4429).
-               0: disabled (default)
-               1: enabled
+       0: disabled (default)
+       1: enabled
+
+       Optimistic Duplicate Address Detection for the interface will be enabled
+       if at least one of conf/{all,interface}/optimistic_dad is set to 1,
+       it will be disabled otherwise.
 
 use_optimistic - BOOLEAN
        If enabled, do not classify optimistic addresses as deprecated during
        source address selection.  Preferred addresses will still be chosen
        before optimistic addresses, subject to other ranking in the source
        address selection algorithm.
-               0: disabled (default)
-               1: enabled
+       0: disabled (default)
+       1: enabled
+
+       This will be enabled if at least one of
+       conf/{all,interface}/use_optimistic is set to 1, disabled otherwise.
 
 stable_secret - IPv6 address
        This IPv6 address will be used as a secret to generate IPv6
index 5e40e1f68873b0f2b594c22a6e69ddb218ce56ec..82236a17b5e65198be004d2cdd6a7c5bd8a9b7d4 100644 (file)
@@ -13,42 +13,42 @@ an example setup using a data-center-class switch ASIC chip.  Other setups
 with SR-IOV or soft switches, such as OVS, are possible.
 
 
-                             User-space tools
-
-       user space                   |
-      +-------------------------------------------------------------------+
-       kernel                       | Netlink
-                                    |
-                     +--------------+-------------------------------+
-                     |         Network stack                        |
-                     |           (Linux)                            |
-                     |                                              |
-                     +----------------------------------------------+
+                             User-space tools
+
+       user space                   |
+      +-------------------------------------------------------------------+
+       kernel                       | Netlink
+                                    |
+                     +--------------+-------------------------------+
+                     |         Network stack                        |
+                     |           (Linux)                            |
+                     |                                              |
+                     +----------------------------------------------+
 
                            sw1p2     sw1p4     sw1p6
-                      sw1p1  +  sw1p3  +  sw1p5  +          eth1
-                        +    |    +    |    +    |            +
-                        |    |    |    |    |    |            |
-                     +--+----+----+----+-+--+----+---+  +-----+-----+
-                     |         Switch driver         |  |    mgmt   |
-                     |        (this document)        |  |   driver  |
-                     |                               |  |           |
-                     +--------------+----------------+  +-----------+
-                                    |
-       kernel                       | HW bus (eg PCI)
-      +-------------------------------------------------------------------+
-       hardware                     |
-                     +--------------+---+------------+
-                     |         Switch device (sw1)   |
-                     |  +----+                       +--------+
-                     |  |    v offloaded data path   | mgmt port
-                     |  |    |                       |
-                     +--|----|----+----+----+----+---+
-                        |    |    |    |    |    |
-                        +    +    +    +    +    +
-                       p1   p2   p3   p4   p5   p6
-
-                             front-panel ports
+                      sw1p1  +  sw1p3  +  sw1p5  +          eth1
+                        +    |    +    |    +    |            +
+                        |    |    |    |    |    |            |
+                     +--+----+----+----+----+----+---+  +-----+-----+
+                     |         Switch driver         |  |    mgmt   |
+                     |        (this document)        |  |   driver  |
+                     |                               |  |           |
+                     +--------------+----------------+  +-----------+
+                                    |
+       kernel                       | HW bus (eg PCI)
+      +-------------------------------------------------------------------+
+       hardware                     |
+                     +--------------+----------------+
+                     |         Switch device (sw1)   |
+                     |  +----+                       +--------+
+                     |  |    v offloaded data path   | mgmt port
+                     |  |    |                       |
+                     +--|----|----+----+----+----+---+
+                        |    |    |    |    |    |
+                        +    +    +    +    +    +
+                       p1   p2   p3   p4   p5   p6
+
+                             front-panel ports
 
 
                                     Fig 1.
index ce61d1fe08cacb5af99260241b058d139838029a..694968c7523cc28620c8ac51a28a33dc1b14336e 100644 (file)
@@ -75,6 +75,7 @@ show up in /proc/sys/kernel:
 - reboot-cmd                  [ SPARC only ]
 - rtsig-max
 - rtsig-nr
+- seccomp/                    ==> Documentation/userspace-api/seccomp_filter.rst
 - sem
 - sem_next_id                [ sysv ipc ]
 - sg-big-buff                 [ generic SCSI device (sg) ]
index f71eb5ef1f2df4154a0a31dd0307da00c5fde42f..099c412951d6b9dea515b08384e023e2c2d69025 100644 (file)
@@ -87,11 +87,16 @@ Return values
 A seccomp filter may return any of the following values. If multiple
 filters exist, the return value for the evaluation of a given system
 call will always use the highest precedent value. (For example,
-``SECCOMP_RET_KILL`` will always take precedence.)
+``SECCOMP_RET_KILL_PROCESS`` will always take precedence.)
 
 In precedence order, they are:
 
-``SECCOMP_RET_KILL``:
+``SECCOMP_RET_KILL_PROCESS``:
+       Results in the entire process exiting immediately without executing
+       the system call.  The exit status of the task (``status & 0x7f``)
+       will be ``SIGSYS``, not ``SIGKILL``.
+
+``SECCOMP_RET_KILL_THREAD``:
        Results in the task exiting immediately without executing the
        system call.  The exit status of the task (``status & 0x7f``) will
        be ``SIGSYS``, not ``SIGKILL``.
@@ -141,6 +146,15 @@ In precedence order, they are:
        allow use of ptrace, even of other sandboxed processes, without
        extreme care; ptracers can use this mechanism to escape.)
 
+``SECCOMP_RET_LOG``:
+       Results in the system call being executed after it is logged. This
+       should be used by application developers to learn which syscalls their
+       application needs without having to iterate through multiple test and
+       development cycles to build the list.
+
+       This action will only be logged if "log" is present in the
+       actions_logged sysctl string.
+
 ``SECCOMP_RET_ALLOW``:
        Results in the system call being executed.
 
@@ -169,7 +183,41 @@ The ``samples/seccomp/`` directory contains both an x86-specific example
 and a more generic example of a higher level macro interface for BPF
 program generation.
 
+Sysctls
+=======
 
+Seccomp's sysctl files can be found in the ``/proc/sys/kernel/seccomp/``
+directory. Here's a description of each file in that directory:
+
+``actions_avail``:
+       A read-only ordered list of seccomp return values (refer to the
+       ``SECCOMP_RET_*`` macros above) in string form. The ordering, from
+       left-to-right, is the least permissive return value to the most
+       permissive return value.
+
+       The list represents the set of seccomp return values supported
+       by the kernel. A userspace program may use this list to
+       determine if the actions found in the ``seccomp.h``, when the
+       program was built, differs from the set of actions actually
+       supported in the current running kernel.
+
+``actions_logged``:
+       A read-write ordered list of seccomp return values (refer to the
+       ``SECCOMP_RET_*`` macros above) that are allowed to be logged. Writes
+       to the file do not need to be in ordered form but reads from the file
+       will be ordered in the same way as the actions_avail sysctl.
+
+       It is important to note that the value of ``actions_logged`` does not
+       prevent certain actions from being logged when the audit subsystem is
+       configured to audit a task. If the action is not found in
+       ``actions_logged`` list, the final decision on whether to audit the
+       action for that task is ultimately left up to the audit subsystem to
+       decide for all seccomp return values other than ``SECCOMP_RET_ALLOW``.
+
+       The ``allow`` string is not accepted in the ``actions_logged`` sysctl
+       as it is not possible to log ``SECCOMP_RET_ALLOW`` actions. Attempting
+       to write ``allow`` to the sysctl will result in an EINVAL being
+       returned.
 
 Adding architecture support
 ===========================
index 3b9887b3644efd443c6e9d2dcc4bb0d624540a0f..60be46dc3fa853f37dedaebb6846a243d0683577 100644 (file)
@@ -352,6 +352,18 @@ L: linux-acpi@vger.kernel.org
 S:     Maintained
 F:     drivers/acpi/arm64
 
+ACPI PMIC DRIVERS
+M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
+M:     Len Brown <lenb@kernel.org>
+R:     Andy Shevchenko <andy@infradead.org>
+R:     Mika Westerberg <mika.westerberg@linux.intel.com>
+L:     linux-acpi@vger.kernel.org
+Q:     https://patchwork.kernel.org/project/linux-acpi/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
+B:     https://bugzilla.kernel.org
+S:     Supported
+F:     drivers/acpi/pmic/
+
 ACPI THERMAL DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
@@ -2853,7 +2865,6 @@ S:        Supported
 F:     drivers/scsi/bnx2i/
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-M:     Yuval Mintz <Yuval.Mintz@cavium.com>
 M:     Ariel Elior <ariel.elior@cavium.com>
 M:     everest-linux-l2@cavium.com
 L:     netdev@vger.kernel.org
@@ -6643,8 +6654,8 @@ M:        Alexander Aring <alex.aring@gmail.com>
 M:     Stefan Schmidt <stefan@osg.samsung.com>
 L:     linux-wpan@vger.kernel.org
 W:     http://wpan.cakelab.org/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sschmidt/wpan-next.git
 S:     Maintained
 F:     net/ieee802154/
 F:     net/mac802154/
@@ -8586,6 +8597,12 @@ M:       Sean Wang <sean.wang@mediatek.com>
 S:     Maintained
 F:     drivers/media/rc/mtk-cir.c
 
+MEDIATEK PMIC LED DRIVER
+M:     Sean Wang <sean.wang@mediatek.com>
+S:     Maintained
+F:     drivers/leds/leds-mt6323.c
+F:     Documentation/devicetree/bindings/leds/leds-mt6323.txt
+
 MEDIATEK ETHERNET DRIVER
 M:     Felix Fietkau <nbd@openwrt.org>
 M:     John Crispin <john@phrozen.org>
@@ -11047,7 +11064,6 @@ S:      Supported
 F:     drivers/scsi/qedi/
 
 QLOGIC QL4xxx ETHERNET DRIVER
-M:     Yuval Mintz <Yuval.Mintz@cavium.com>
 M:     Ariel Elior <Ariel.Elior@cavium.com>
 M:     everest-linux-l2@cavium.com
 L:     netdev@vger.kernel.org
index 64cbc66cebcaa7bbf8c0d10a09412ce6693437b9..cf007a31d575d6312f3f5a860e9591dc329a86a4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 14
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc3
 NAME = Fearless Coyote
 
 # *DOCUMENTATION*
@@ -1172,11 +1172,11 @@ headers_check: headers_install
 
 PHONY += kselftest
 kselftest:
-       $(Q)$(MAKE) -C tools/testing/selftests run_tests
+       $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests run_tests
 
 PHONY += kselftest-clean
 kselftest-clean:
-       $(Q)$(MAKE) -C tools/testing/selftests clean
+       $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests clean
 
 PHONY += kselftest-merge
 kselftest-merge:
index d400a2161935de5442c0ae1ddc7159ae16c003a4..8ee41e9881690b648bf1d4e5c385ddeef0a860c2 100644 (file)
@@ -78,9 +78,6 @@ struct task_struct;
 
 #endif
 
-#define copy_segments(tsk, mm)      do { } while (0)
-#define release_segments(mm)        do { } while (0)
-
 #define KSTK_EIP(tsk)   (task_pt_regs(tsk)->ret)
 #define KSTK_ESP(tsk)   (task_pt_regs(tsk)->sp)
 
index 9c9088c99cc4cdb36d963c61e648216ee7fc4c4c..60cb084a8d927e40303a377a40fd283d2eb29f45 100644 (file)
 
                usb1: ohci@00400000 {
                        num-ports = <3>;
-                       atmel,vbus-gpio = <&pioA PIN_PA10 GPIO_ACTIVE_HIGH>;
+                       atmel,vbus-gpio = <0 /* &pioA PIN_PD20 GPIO_ACTIVE_HIGH */
+                                          &pioA PIN_PA27 GPIO_ACTIVE_HIGH
+                                          0
+                                         >;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_usb_default>;
                        status = "okay";
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_mikrobus2_uart>;
                                atmel,use-dma-rx;
-                               atmel-use-dma-tx;
+                               atmel,use-dma-tx;
                                status = "okay";
                        };
 
                        uart4: serial@fc00c000 {
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
-                               pinctrl-name = "default";
+                               pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_mikrobus1_uart>;
                                status = "okay";
                        };
                                };
 
                                pinctrl_led_gpio_default: led_gpio_default {
-                                       pinmux = <PIN_PA27__GPIO>,
+                                       pinmux = <PIN_PA10__GPIO>,
                                                 <PIN_PB1__GPIO>,
                                                 <PIN_PA31__GPIO>;
                                        bias-pull-up;
                                };
 
                                pinctrl_usb_default: usb_default {
-                                       pinmux = <PIN_PA10__GPIO>,
+                                       pinmux = <PIN_PA27__GPIO>,
                                                 <PIN_PD19__GPIO>;
                                        bias-disable;
                                };
 
                red {
                        label = "red";
-                       gpios = <&pioA PIN_PA27 GPIO_ACTIVE_LOW>;
+                       gpios = <&pioA PIN_PA10 GPIO_ACTIVE_HIGH>;
                };
 
                green {
                        label = "green";
-                       gpios = <&pioA PIN_PB1 GPIO_ACTIVE_LOW>;
+                       gpios = <&pioA PIN_PB1 GPIO_ACTIVE_HIGH>;
                };
 
                blue {
                        label = "blue";
-                       gpios = <&pioA PIN_PA31 GPIO_ACTIVE_LOW>;
+                       gpios = <&pioA PIN_PA31 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
                };
        };
index 67e72bc72e805be995b0d44fa68f74e29161b140..c75507922f7d7998ee0e45bb875b8b6495b3d8d7 100644 (file)
        compatible = "ti,da850-evm", "ti,da850";
        model = "DA850/AM1808/OMAP-L138 EVM";
 
+       aliases {
+               serial0 = &serial0;
+               serial1 = &serial1;
+               serial2 = &serial2;
+               ethernet0 = &eth0;
+       };
+
        soc@1c00000 {
                pmx_core: pinmux@14120 {
                        status = "okay";
index cb47ae79a5f9e87ed1e9ce84b148b6829c9e2935..1b0bd72945f21337d1e89c3e1636bbfb5cabeecd 100644 (file)
        clock-frequency = <400000>;
 
        as3645a@30 {
+               #address-cells = <1>;
+               #size-cells = <0>;
                reg = <0x30>;
                compatible = "ams,as3645a";
-               flash {
+               flash@0 {
+                       reg = <0x0>;
                        flash-timeout-us = <150000>;
                        flash-max-microamp = <320000>;
                        led-max-microamp = <60000>;
-                       peak-current-limit = <1750000>;
+                       ams,input-max-microamp = <1750000>;
                };
-               indicator {
+               indicator@1 {
+                       reg = <0x1>;
                        led-max-microamp = <10000>;
                };
        };
index d2d75fa664a64338bc6bf0af3c3c65e3de0926f4..2a63fa10c813042bf2b98261964c7b6cd9f03790 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_ATA=y
+CONFIG_PATA_FTIDE010=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -55,8 +56,8 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_GEMINI=y
 CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
 # CONFIG_DNOTIFY is not set
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
index 64e3a2a8cedec353203694d6f9f74b4fa09f962f..d5e1370ec303d5440c4572262f6918d4a047a170 100644 (file)
@@ -471,7 +471,7 @@ CONFIG_LCD_PLATFORM=m
 CONFIG_LCD_TOSA=m
 CONFIG_BACKLIGHT_PWM=m
 CONFIG_BACKLIGHT_TOSA=m
-CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
index 44d4fa57ba0a346cde5f53d099a3be61b42d841a..070e5074f1ee5b118ed35612c9cd09d65f611255 100644 (file)
@@ -113,7 +113,7 @@ CONFIG_FB_PXA_PARAMETERS=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_PWM=m
 # CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
index 8d4c0c926c344d9f654a87d179488eb5bfff7096..09e7050d56532dabd512cc99e1038a6dae525d69 100644 (file)
@@ -112,7 +112,7 @@ CONFIG_FB_PXA=m
 CONFIG_FB_PXA_PARAMETERS=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
index 1d468b527b7b6928d2bb21c2152a3a282a7a366d..776757d1604ab3901996bb24bb02748e54c2aee7 100644 (file)
@@ -139,11 +139,10 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define TIF_NEED_RESCHED       1       /* rescheduling necessary */
 #define TIF_NOTIFY_RESUME      2       /* callback before returning to user */
 #define TIF_UPROBE             3       /* breakpointed or singlestepping */
-#define TIF_FSCHECK            4       /* Check FS is USER_DS on return */
-#define TIF_SYSCALL_TRACE      5       /* syscall trace active */
-#define TIF_SYSCALL_AUDIT      6       /* syscall auditing active */
-#define TIF_SYSCALL_TRACEPOINT 7       /* syscall tracepoint instrumentation */
-#define TIF_SECCOMP            8       /* seccomp syscall filtering active */
+#define TIF_SYSCALL_TRACE      4       /* syscall trace active */
+#define TIF_SYSCALL_AUDIT      5       /* syscall auditing active */
+#define TIF_SYSCALL_TRACEPOINT 6       /* syscall tracepoint instrumentation */
+#define TIF_SECCOMP            7       /* seccomp syscall filtering active */
 
 #define TIF_NOHZ               12      /* in adaptive nohz mode */
 #define TIF_USING_IWMMXT       17
@@ -154,7 +153,6 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_UPROBE            (1 << TIF_UPROBE)
-#define _TIF_FSCHECK           (1 << TIF_FSCHECK)
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_TRACEPOINT        (1 << TIF_SYSCALL_TRACEPOINT)
@@ -168,9 +166,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 /*
  * Change these and you break ASM code in entry-common.S
  */
-#define _TIF_WORK_MASK         (_TIF_NEED_RESCHED | _TIF_SIGPENDING |  \
-                                _TIF_NOTIFY_RESUME | _TIF_UPROBE |     \
-                                _TIF_FSCHECK)
+#define _TIF_WORK_MASK         (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
+                                _TIF_NOTIFY_RESUME | _TIF_UPROBE)
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_ARM_THREAD_INFO_H */
index 87936dd5d1510572993d4bcc9b4fa1222a4dd3b2..0bf2347495f13e4db7fdc1c560b0976ec1fbd619 100644 (file)
@@ -70,8 +70,6 @@ static inline void set_fs(mm_segment_t fs)
 {
        current_thread_info()->addr_limit = fs;
        modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
-       /* On user-mode return, check fs is correct */
-       set_thread_flag(TIF_FSCHECK);
 }
 
 #define segment_eq(a, b)       ((a) == (b))
index ca3614dc6938e1595f71a095f53456eb26701bec..99c908226065cf6331324309edeadfa618597874 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/unistd.h>
 #include <asm/ftrace.h>
 #include <asm/unwind.h>
+#include <asm/memory.h>
 #ifdef CONFIG_AEABI
 #include <asm/unistd-oabi.h>
 #endif
@@ -48,12 +49,14 @@ ret_fast_syscall:
  UNWIND(.fnstart       )
  UNWIND(.cantunwind    )
        disable_irq_notrace                     @ disable interrupts
+       ldr     r2, [tsk, #TI_ADDR_LIMIT]
+       cmp     r2, #TASK_SIZE
+       blne    addr_limit_check_failed
        ldr     r1, [tsk, #TI_FLAGS]            @ re-check for syscall tracing
-       tst     r1, #_TIF_SYSCALL_WORK
-       bne     fast_work_pending
-       tst     r1, #_TIF_WORK_MASK
+       tst     r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
        bne     fast_work_pending
 
+
        /* perform architecture specific actions before user return */
        arch_ret_to_user r1, lr
 
@@ -76,16 +79,16 @@ ret_fast_syscall:
  UNWIND(.cantunwind    )
        str     r0, [sp, #S_R0 + S_OFF]!        @ save returned r0
        disable_irq_notrace                     @ disable interrupts
+       ldr     r2, [tsk, #TI_ADDR_LIMIT]
+       cmp     r2, #TASK_SIZE
+       blne    addr_limit_check_failed
        ldr     r1, [tsk, #TI_FLAGS]            @ re-check for syscall tracing
-       tst     r1, #_TIF_SYSCALL_WORK
-       bne     fast_work_pending
-       tst     r1, #_TIF_WORK_MASK
+       tst     r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
        beq     no_work_pending
  UNWIND(.fnend         )
 ENDPROC(ret_fast_syscall)
 
        /* Slower path - fall through to work_pending */
-fast_work_pending:
 #endif
 
        tst     r1, #_TIF_SYSCALL_WORK
@@ -111,6 +114,9 @@ ENTRY(ret_to_user)
 ret_slow_syscall:
        disable_irq_notrace                     @ disable interrupts
 ENTRY(ret_to_user_from_irq)
+       ldr     r2, [tsk, #TI_ADDR_LIMIT]
+       cmp     r2, #TASK_SIZE
+       blne    addr_limit_check_failed
        ldr     r1, [tsk, #TI_FLAGS]
        tst     r1, #_TIF_WORK_MASK
        bne     slow_work_pending
index e2de50bf87425e4a55baa66ef68d1fe99e53e1f8..b67ae12503f30c3ba113f1d8c7a943d17e9db717 100644 (file)
@@ -614,10 +614,6 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
         * Update the trace code with the current status.
         */
        trace_hardirqs_off();
-
-       /* Check valid user FS if needed */
-       addr_limit_user_check();
-
        do {
                if (likely(thread_flags & _TIF_NEED_RESCHED)) {
                        schedule();
@@ -678,3 +674,9 @@ struct page *get_signal_page(void)
 
        return page;
 }
+
+/* Defer to generic check */
+asmlinkage void addr_limit_check_failed(void)
+{
+       addr_limit_user_check();
+}
index 5036f996e694a533d66f82743b901385ae048007..849014c01cf4d62a465ec6e54b829d4ff45f05a6 100644 (file)
@@ -533,8 +533,8 @@ static void __init at91_pm_backup_init(void)
        }
 
        pm_bu->suspended = 0;
-       pm_bu->canary = virt_to_phys(&canary);
-       pm_bu->resume = virt_to_phys(cpu_resume);
+       pm_bu->canary = __pa_symbol(&canary);
+       pm_bu->resume = __pa_symbol(cpu_resume);
 
        return;
 
index 9b41f1e3b1a039cd45fe842e10abff0181186fdf..939b310913cf38cd7ca3136128fb5440340d7d12 100644 (file)
@@ -50,17 +50,22 @@ KBUILD_CFLAGS       += -fno-asynchronous-unwind-tables
 KBUILD_CFLAGS  += $(call cc-option, -mpc-relative-literal-loads)
 KBUILD_AFLAGS  += $(lseinstr) $(brokengasinst)
 
+KBUILD_CFLAGS  += $(call cc-option,-mabi=lp64)
+KBUILD_AFLAGS  += $(call cc-option,-mabi=lp64)
+
 ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
 KBUILD_CPPFLAGS        += -mbig-endian
 CHECKFLAGS     += -D__AARCH64EB__
 AS             += -EB
 LD             += -EB
+LDFLAGS                += -maarch64linuxb
 UTS_MACHINE    := aarch64_be
 else
 KBUILD_CPPFLAGS        += -mlittle-endian
 CHECKFLAGS     += -D__AARCH64EL__
 AS             += -EL
 LD             += -EL
+LDFLAGS                += -maarch64linux
 UTS_MACHINE    := aarch64
 endif
 
index 636c1bced7d4a9dd60d3a6489997ebd82b83d96e..1b266292f0bee00ce1952005479053e820b5ca0e 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_LINKAGE_H
 #define __ASM_LINKAGE_H
 
-#define __ALIGN                .align 4
-#define __ALIGN_STR    ".align 4"
+#define __ALIGN                .align 2
+#define __ALIGN_STR    ".align 2"
 
 #endif
index bc4e92337d1690045b7b5c97efd11ad4fb8bb453..b46e54c2399b58b6451ea9dacc5c033115b05c64 100644 (file)
@@ -401,7 +401,7 @@ static inline phys_addr_t pmd_page_paddr(pmd_t pmd)
 /* Find an entry in the third-level page table. */
 #define pte_index(addr)                (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 
-#define pte_offset_phys(dir,addr)      (pmd_page_paddr(*(dir)) + pte_index(addr) * sizeof(pte_t))
+#define pte_offset_phys(dir,addr)      (pmd_page_paddr(READ_ONCE(*(dir))) + pte_index(addr) * sizeof(pte_t))
 #define pte_offset_kernel(dir,addr)    ((pte_t *)__va(pte_offset_phys((dir), (addr))))
 
 #define pte_offset_map(dir,addr)       pte_offset_kernel((dir), (addr))
index 3a68cf38a6b36712e1a5a6a8463a19d32bbdb4f5..f444f374bd7b3ccea1b097cc13d9229db5c8f2c3 100644 (file)
@@ -321,6 +321,8 @@ void kernel_neon_end(void)
 }
 EXPORT_SYMBOL(kernel_neon_end);
 
+#ifdef CONFIG_EFI
+
 static DEFINE_PER_CPU(struct fpsimd_state, efi_fpsimd_state);
 static DEFINE_PER_CPU(bool, efi_fpsimd_state_used);
 
@@ -370,6 +372,8 @@ void __efi_fpsimd_end(void)
                kernel_neon_end();
 }
 
+#endif /* CONFIG_EFI */
+
 #endif /* CONFIG_KERNEL_MODE_NEON */
 
 #ifdef CONFIG_CPU_PM
index 7434ec0c7a271632adce1a497bc097306199e580..0b243ecaf7ac87faa81fed0a09db996757d71f4e 100644 (file)
@@ -384,6 +384,7 @@ ENTRY(kimage_vaddr)
  * booted in EL1 or EL2 respectively.
  */
 ENTRY(el2_setup)
+       msr     SPsel, #1                       // We want to use SP_EL{1,2}
        mrs     x0, CurrentEL
        cmp     x0, #CurrentEL_EL2
        b.eq    1f
index c45214f8fb5497fdaed8665b8b066bbfc0118ed2..0bdc96c61bc0f2b14f627142a2778409c9c6a7d0 100644 (file)
@@ -751,10 +751,10 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
         */
        trace_hardirqs_off();
 
-       /* Check valid user FS if needed */
-       addr_limit_user_check();
-
        do {
+               /* Check valid user FS if needed */
+               addr_limit_user_check();
+
                if (thread_flags & _TIF_NEED_RESCHED) {
                        schedule();
                } else {
index 89993c4be1befe3d7629bf45174f10081027d2a2..2069e9bc0fca674ba1d6fe769be05e6f731ef93d 100644 (file)
@@ -651,7 +651,7 @@ static const struct fault_info fault_info[] = {
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 0 translation fault"     },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 1 translation fault"     },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 2 translation fault"     },
-       { do_page_fault,        SIGSEGV, SEGV_MAPERR,   "level 3 translation fault"     },
+       { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 3 translation fault"     },
        { do_bad,               SIGBUS,  0,             "unknown 8"                     },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 1 access flag fault"     },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 2 access flag fault"     },
index 7c87b5be53b5b74c76fbe03829034b1e96ac3c7c..8f7cce829f8e2630cb88e81cdb024a8375a59e4f 100644 (file)
@@ -92,9 +92,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-#define copy_segments(tsk, mm)         do { } while (0)
-#define release_segments(mm)           do { } while (0)
-
 /*
  * saved kernel SP and DP of a blocked thread.
  */
index e4d08d74ed9f8dc4f81140fcf60442378f02cf58..021cce78b4010d7b5c727d1e86812f85e81671bf 100644 (file)
@@ -92,10 +92,6 @@ static inline void release_thread(struct task_struct *dead_task)
 extern asmlinkage void save_user_regs(struct user_context *target);
 extern asmlinkage void *restore_user_regs(const struct user_context *target, ...);
 
-#define copy_segments(tsk, mm)         do { } while (0)
-#define release_segments(mm)           do { } while (0)
-#define forget_segments()              do { } while (0)
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define        KSTK_EIP(tsk)   ((tsk)->thread.frame0->pc)
index 657874eeeccc262c11268094e0f0ba530e05dd92..c70fa9ac71690d2529d97e1040a87ed01a8a35da 100644 (file)
@@ -118,14 +118,6 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/* Copy and release all segment info associated with a VM */
-extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
-extern void release_segments(struct mm_struct * mm);
-
-/* Copy and release all segment info associated with a VM */
-#define copy_segments(p, mm)  do { } while (0)
-#define release_segments(mm)  do { } while (0)
-
 unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  ((tsk)->thread.lr)
 #define KSTK_ESP(tsk)  ((tsk)->thread.sp)
index ec6a49076980fff90dc04ece4b389ea1782449b9..8ae92d6abfd2e24d9e6d767fab2fc83db8720fcf 100644 (file)
@@ -131,9 +131,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-#define copy_segments(tsk, mm)         do { } while (0)
-#define release_segments(mm)           do { } while (0)
-
 /*
  * Return saved PC of a blocked thread.
  */
index 9d26abdf0dc1c2349e5822b01416f0f0cd154b58..4f798aa671ddd2f481c35689f03be1ea73318ae8 100644 (file)
@@ -39,7 +39,7 @@ config MICROBLAZE
 # Endianness selection
 choice
        prompt "Endianness selection"
-       default CPU_BIG_ENDIAN
+       default CPU_LITTLE_ENDIAN
        help
          microblaze architectures can be configured for either little or
          big endian formats. Be sure to select the appropriate mode.
index e77a596f3f1efcfe94c4bc89b9b3cc860d589210..06609ca361150ab77529bf0999d8e258ad25d62c 100644 (file)
@@ -7,6 +7,7 @@ generic-y += fcntl.h
 generic-y += ioctl.h
 generic-y += ioctls.h
 generic-y += ipcbuf.h
+generic-y += kvm_para.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += param.h
index e45ada8fb00669a8889284db230908ed64f2dda1..94700c5270a91e69cb0acb7b32b20f272899a1a6 100644 (file)
@@ -165,7 +165,7 @@ int dma_direct_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
                             unsigned long attrs)
 {
 #ifdef CONFIG_MMU
-       unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       unsigned long user_count = vma_pages(vma);
        unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
        unsigned long off = vma->vm_pgoff;
        unsigned long pfn;
index 730c0b03060d0c941eaf29ee394f3c55be121954..b816cb4a25ff95eb7ca737f3296a71c5aea54830 100644 (file)
 #include "pci.h"
 
 static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
-static const struct ath79_pci_irq *ath79_pci_irq_map __initdata;
-static unsigned ath79_pci_nr_irqs __initdata;
+static const struct ath79_pci_irq *ath79_pci_irq_map;
+static unsigned ath79_pci_nr_irqs;
 
-static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
+static const struct ath79_pci_irq ar71xx_pci_irq_map[] = {
        {
                .slot   = 17,
                .pin    = 1,
@@ -41,7 +41,7 @@ static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
        }
 };
 
-static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
+static const struct ath79_pci_irq ar724x_pci_irq_map[] = {
        {
                .slot   = 0,
                .pin    = 1,
@@ -49,7 +49,7 @@ static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
        }
 };
 
-static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = {
+static const struct ath79_pci_irq qca955x_pci_irq_map[] = {
        {
                .bus    = 0,
                .slot   = 0,
@@ -64,7 +64,7 @@ static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = {
        },
 };
 
-int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
+int pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
 {
        int irq = -1;
        int i;
index e4ed1bc9a7345626d316bd1192dfdbf5bf1db8b0..a6810923b3f0214dfa36eab4a28320a65bba7790 100644 (file)
@@ -1377,29 +1377,32 @@ do {                                                                    \
 
 #define __write_64bit_c0_split(source, sel, val)                       \
 do {                                                                   \
+       unsigned long long __tmp;                                       \
        unsigned long __flags;                                          \
                                                                        \
        local_irq_save(__flags);                                        \
        if (sel == 0)                                                   \
                __asm__ __volatile__(                                   \
                        ".set\tmips64\n\t"                              \
-                       "dsll\t%L0, %L0, 32\n\t"                        \
+                       "dsll\t%L0, %L1, 32\n\t"                        \
                        "dsrl\t%L0, %L0, 32\n\t"                        \
-                       "dsll\t%M0, %M0, 32\n\t"                        \
+                       "dsll\t%M0, %M1, 32\n\t"                        \
                        "or\t%L0, %L0, %M0\n\t"                         \
                        "dmtc0\t%L0, " #source "\n\t"                   \
                        ".set\tmips0"                                   \
-                       : : "r" (val));                                 \
+                       : "=&r,r" (__tmp)                               \
+                       : "r,0" (val));                                 \
        else                                                            \
                __asm__ __volatile__(                                   \
                        ".set\tmips64\n\t"                              \
-                       "dsll\t%L0, %L0, 32\n\t"                        \
+                       "dsll\t%L0, %L1, 32\n\t"                        \
                        "dsrl\t%L0, %L0, 32\n\t"                        \
-                       "dsll\t%M0, %M0, 32\n\t"                        \
+                       "dsll\t%M0, %M1, 32\n\t"                        \
                        "or\t%L0, %L0, %M0\n\t"                         \
                        "dmtc0\t%L0, " #source ", " #sel "\n\t"         \
                        ".set\tmips0"                                   \
-                       : : "r" (val));                                 \
+                       : "=&r,r" (__tmp)                               \
+                       : "r,0" (val));                                 \
        local_irq_restore(__flags);                                     \
 } while (0)
 
index 9e6c74bf66c485cc3c1a23ee1d298c1b6f81dad5..6668f67a61c3a2bb09fc23d9e2172d7a738020e1 100644 (file)
@@ -618,8 +618,7 @@ static int mipspmu_event_init(struct perf_event *event)
                return -ENOENT;
        }
 
-       if ((unsigned int)event->cpu >= nr_cpumask_bits ||
-           (event->cpu >= 0 && !cpu_online(event->cpu)))
+       if (event->cpu >= 0 && !cpu_online(event->cpu))
                return -ENODEV;
 
        if (!atomic_inc_not_zero(&active_events)) {
index 1c02f5737367aa7e75569afeb98aebcd3ebb5327..b4c263f16b15eeb62c4fc93d70ff828cdfa7ac7f 100644 (file)
 #define INTC   PC104PLUS_INTC_IRQ
 #define INTD   PC104PLUS_INTD_IRQ
 
-static char irq_tab_capcella[][5] __initdata = {
+static char irq_tab_capcella[][5] = {
  [11] = { -1, INT1, INT1, INT1, INT1 },
  [12] = { -1, INT2, INT2, INT2, INT2 },
  [14] = { -1, INTA, INTB, INTC, INTD }
 };
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return irq_tab_capcella[slot][pin];
 }
index b3ab59318d91a7a2817e6615efba1ef3fc0a2c37..44be65c3e6bb3d211d8692211b732d5f41f2caa4 100644 (file)
@@ -147,7 +147,7 @@ static void qube_raq_via_board_id_fixup(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0,
         qube_raq_via_board_id_fixup);
 
-static char irq_tab_qube1[] __initdata = {
+static char irq_tab_qube1[] = {
   [COBALT_PCICONF_CPU]    = 0,
   [COBALT_PCICONF_ETH0]           = QUBE1_ETH0_IRQ,
   [COBALT_PCICONF_RAQSCSI] = SCSI_IRQ,
@@ -156,7 +156,7 @@ static char irq_tab_qube1[] __initdata = {
   [COBALT_PCICONF_ETH1]           = 0
 };
 
-static char irq_tab_cobalt[] __initdata = {
+static char irq_tab_cobalt[] = {
   [COBALT_PCICONF_CPU]    = 0,
   [COBALT_PCICONF_ETH0]           = ETH0_IRQ,
   [COBALT_PCICONF_RAQSCSI] = SCSI_IRQ,
@@ -165,7 +165,7 @@ static char irq_tab_cobalt[] __initdata = {
   [COBALT_PCICONF_ETH1]           = ETH1_IRQ
 };
 
-static char irq_tab_raq2[] __initdata = {
+static char irq_tab_raq2[] = {
   [COBALT_PCICONF_CPU]    = 0,
   [COBALT_PCICONF_ETH0]           = ETH0_IRQ,
   [COBALT_PCICONF_RAQSCSI] = RAQ2_SCSI_IRQ,
@@ -174,7 +174,7 @@ static char irq_tab_raq2[] __initdata = {
   [COBALT_PCICONF_ETH1]           = ETH1_IRQ
 };
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (cobalt_board_id <= COBALT_BRD_ID_QUBE1)
                return irq_tab_qube1[slot];
index 19caf775c20645ada7f1bbc86777c2bd45b23246..c31cb6af1cd07f8e9dd5ad715d30f93abd53a927 100644 (file)
@@ -43,7 +43,7 @@
  */
 
 #define MAX_SLOT_NUM 10
-static unsigned char irq_map[][5] __initdata = {
+static unsigned char irq_map[][5] = {
        [3] = {0, MARKEINS_PCI_IRQ_INTB, MARKEINS_PCI_IRQ_INTC,
               MARKEINS_PCI_IRQ_INTD, 0,},
        [4] = {0, MARKEINS_PCI_IRQ_INTA, 0, 0, 0,},
@@ -85,7 +85,7 @@ static void emma2rh_pci_host_fixup(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
                         emma2rh_pci_host_fixup);
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return irq_map[slot][pin];
 }
index 50da773faedee8fc5850480857ea5e36a78f24c0..b47c2771dc997663a7046dcb6166d1987957c89e 100644 (file)
@@ -19,7 +19,7 @@
 /* South bridge slot number is set by the pci probe process */
 static u8 sb_slot = 5;
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq = 0;
 
index 133685e215ee6a2f02a5a244e04e08464543273d..c6ec18a07e63ab2f88e53a5ff25cde90704f59a5 100644 (file)
@@ -21,7 +21,7 @@
 #define INTB   MACEPCI_SHARED0_IRQ
 #define INTC   MACEPCI_SHARED1_IRQ
 #define INTD   MACEPCI_SHARED2_IRQ
-static char irq_tab_mace[][5] __initdata = {
+static char irq_tab_mace[][5] = {
       /* Dummy INT#A  INT#B  INT#C  INT#D */
        {0,         0,     0,     0,     0}, /* This is placeholder row - never used */
        {0,     SCSI0, SCSI0, SCSI0, SCSI0},
@@ -39,7 +39,7 @@ static char irq_tab_mace[][5] __initdata = {
  * irqs.  I suppose a device without a pin A will thank us for doing it
  * right if there exists such a broken piece of crap.
  */
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return irq_tab_mace[slot][pin];
 }
index 0f1069527cbae435775c39d7acbaeb9369561d87..d3102eeea898983c655d7b8e6d7f923cdc56395a 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/txx9/pci.h>
 #include <asm/txx9/jmr3927.h>
 
-int __init jmr3927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int jmr3927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        unsigned char irq = pin;
 
index 2b5427d3f35c255bc566978b02ff1ac8e057f551..81530a13b34990a38d159ae248aa0a2d453bf332 100644 (file)
@@ -23,7 +23,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        return 0;
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return of_irq_parse_and_map_pci(dev, slot, pin);
 }
index 95ab9a1bd0107384a3faa8e45c9f2872f7c561df..20cdfdc0893875a7556cfbef91db0ab18b8099d2 100644 (file)
@@ -30,7 +30,7 @@
 #define PCID           7
 
 /* all the pci device has the PCIA pin, check the datasheet. */
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
        /*      INTA    INTB    INTC    INTD */
        {0, 0, 0, 0, 0},        /*  11: Unused */
        {0, 0, 0, 0, 0},        /*  12: Unused */
@@ -51,7 +51,7 @@ static char irq_tab[][5] __initdata = {
        {0, 0, 0, 0, 0},        /*  27: Unused */
 };
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int virq;
 
index 2b6d5e196f9990255eb5d35de3e6580a69f6003f..8a741c2c6685ded75b18975613f3e0a8b40867a1 100644 (file)
@@ -32,7 +32,7 @@ static void print_fixup_info(const struct pci_dev *pdev)
                        pdev->vendor, pdev->device, pdev->irq);
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        print_fixup_info(dev);
        return dev->irq;
index 40e920c653cc31762bcc10e4e6a235a4c53b78fa..3ec85331795ef561ce1bc624ae55cd009fc6a844 100644 (file)
@@ -12,7 +12,7 @@
 static char pci_irq[5] = {
 };
 
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
        /*      INTA    INTB    INTC    INTD */
        {0,     0,      0,      0,      0 },    /*  0: GT64120 PCI bridge */
        {0,     0,      0,      0,      0 },    /*  1: Unused */
@@ -38,7 +38,7 @@ static char irq_tab[][5] __initdata = {
        {0,     PCID,   PCIA,   PCIB,   PCIC }  /* 21: PCI Slot 4 */
 };
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int virq;
        virq = irq_tab[slot][pin];
index 8e4f8288eca2e2fcfc17bd615a26a5e0a6a152de..66eaf456bc89c31031abc74762874d09131a9ed0 100644 (file)
 
 #include <asm/vr41xx/mpc30x.h>
 
-static const int internal_func_irqs[] __initconst = {
+static const int internal_func_irqs[] = {
        VRC4173_CASCADE_IRQ,
        VRC4173_AC97_IRQ,
        VRC4173_USB_IRQ,
 };
 
-static const int irq_tab_mpc30x[] __initconst = {
+static const int irq_tab_mpc30x[] = {
  [12] = VRC4173_PCMCIA1_IRQ,
  [13] = VRC4173_PCMCIA2_IRQ,
  [29] = MQ200_IRQ,
 };
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (slot == 30)
                return internal_func_irqs[PCI_FUNC(dev->devfn)];
index fab405c21c2f76f856af004fab4e88e68f81cef2..4ad2ef02087bc0cf8bec3b19835ce88aec73b1f7 100644 (file)
@@ -47,7 +47,7 @@
 
 #if defined(CONFIG_PMC_MSP7120_GW)
 /* Garibaldi Board IRQ wiring to PCI slots */
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
        /* INTA    INTB    INTC    INTD */
        {0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
        {0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
@@ -86,7 +86,7 @@ static char irq_tab[][5] __initdata = {
 #elif defined(CONFIG_PMC_MSP7120_EVAL)
 
 /* MSP7120 Eval Board IRQ wiring to PCI slots */
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
        /* INTA    INTB    INTC    INTD */
        {0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
        {0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
@@ -125,7 +125,7 @@ static char irq_tab[][5] __initdata = {
 #else
 
 /* Unknown board -- don't assign any IRQs */
-static char irq_tab[][5] __initdata = {
+static char irq_tab[][5] = {
        /* INTA    INTB    INTC    INTD */
        {0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
        {0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
@@ -202,7 +202,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
  *  RETURNS:    IRQ number
  *
  ****************************************************************************/
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 #if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL)
        printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n");
index 321db265829c0c0e88cd83790edc028d2bec77d0..d6aaed1d6be9ed3f10d9843b068661b3dcc2e18d 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/txx9/pci.h>
 #include <asm/txx9/rbtx4927.h>
 
-int __init rbtx4927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int rbtx4927_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        unsigned char irq = pin;
 
index a80579af609bc7155f86836a3e4f0e8ed457e7d3..ff22a22db73ee618a30cb7af4e906ce060da7d92 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/txx9/pci.h>
 #include <asm/txx9/rbtx4938.h>
 
-int __init rbtx4938_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int rbtx4938_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq = tx4938_pcic1_map_irq(dev, slot);
 
index f67ebeeb42000bb5d4d73961d6bcc4d632375298..adb9a58641e8a1891e409b078e256d846ffa5d14 100644 (file)
@@ -40,7 +40,7 @@
  * seem to be a documentation error.  At least on my RM200C the Cirrus
  * Logic CL-GD5434 VGA is device 3.
  */
-static char irq_tab_rm200[8][5] __initdata = {
+static char irq_tab_rm200[8][5] = {
        /*       INTA  INTB  INTC  INTD */
        {     0,    0,    0,    0,    0 },      /* EISA bridge */
        {  SCSI, SCSI, SCSI, SCSI, SCSI },      /* SCSI */
@@ -57,7 +57,7 @@ static char irq_tab_rm200[8][5] __initdata = {
  *
  * The VGA card is optional for RM300 systems.
  */
-static char irq_tab_rm300d[8][5] __initdata = {
+static char irq_tab_rm300d[8][5] = {
        /*       INTA  INTB  INTC  INTD */
        {     0,    0,    0,    0,    0 },      /* EISA bridge */
        {  SCSI, SCSI, SCSI, SCSI, SCSI },      /* SCSI */
@@ -69,7 +69,7 @@ static char irq_tab_rm300d[8][5] __initdata = {
        {     0, INTD, INTA, INTB, INTC },      /* Slot 4 */
 };
 
-static char irq_tab_rm300e[5][5] __initdata = {
+static char irq_tab_rm300e[5][5] = {
        /*       INTA  INTB  INTC  INTD */
        {     0,    0,    0,    0,    0 },      /* HOST bridge */
        {  SCSI, SCSI, SCSI, SCSI, SCSI },      /* SCSI */
@@ -96,7 +96,7 @@ static char irq_tab_rm300e[5][5] __initdata = {
 #define INTC   PCIT_IRQ_INTC
 #define INTD   PCIT_IRQ_INTD
 
-static char irq_tab_pcit[13][5] __initdata = {
+static char irq_tab_pcit[13][5] = {
        /*       INTA  INTB  INTC  INTD */
        {     0,     0,     0,     0,     0 },  /* HOST bridge */
        { SCSI0, SCSI0, SCSI0, SCSI0, SCSI0 },  /* SCSI */
@@ -113,7 +113,7 @@ static char irq_tab_pcit[13][5] __initdata = {
        {     0,  INTA,  INTB,  INTC,  INTD },  /* Slot 5 */
 };
 
-static char irq_tab_pcit_cplus[13][5] __initdata = {
+static char irq_tab_pcit_cplus[13][5] = {
        /*       INTA  INTB  INTC  INTD */
        {     0,     0,     0,     0,     0 },  /* HOST bridge */
        {     0,  INTB,  INTC,  INTD,  INTA },  /* PCI Slot 9 */
@@ -130,7 +130,7 @@ static inline int is_rm300_revd(void)
        return (csmsr & 0xa0) == 0x20;
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        switch (sni_brd_type) {
        case SNI_BRD_PCI_TOWER_CPLUS:
index d0b0083fbd278a529209d41c7259e645d2c37f6c..cc581535f25772daf542445e1e4e59318e94a56f 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <asm/vr41xx/tb0219.h>
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq = -1;
 
index 4196ccf3ea3da5e6783de7acd913f68d2fc218bc..b827b5cad5fd80eb8e4fde0a0e66bfbed524751c 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/tb0226.h>
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq = -1;
 
index 8c5039ed75d74c40df1b739ad37edf177dfad5bf..98f26285f2e3a904c7bff305d5a1cc9d65389f26 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <asm/vr41xx/tb0287.h>
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        unsigned char bus;
        int irq = -1;
index e99ca7702d8ad81660ab011ae4c990c0fb954f96..f15ec98de2de5b5569f051705b74985693406ea5 100644 (file)
@@ -522,7 +522,7 @@ static int __init alchemy_pci_init(void)
 arch_initcall(alchemy_pci_init);
 
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct alchemy_pci_context *ctx = dev->sysdata;
        if (ctx && ctx->board_map_irq)
index 76f16eaed0ad3e9851d854d940e871c8c5f69aa9..230d7dd273e21af0668062c648ee2b6962383de1 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/bcma/bcma.h>
 #include <bcm47xx.h>
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return 0;
 }
index 40d2797d2bc43b255edd050cf17d270cdbc4325d..47f4ee6bbb3bf9bb9874d6d26510d7e1f13cf94e 100644 (file)
@@ -61,7 +61,7 @@ arch_initcall(lasat_pci_setup);
 #define LASAT_IRQ_PCIC  (LASAT_IRQ_BASE + 7)
 #define LASAT_IRQ_PCID  (LASAT_IRQ_BASE + 8)
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        switch (slot) {
        case 1:
index 4e633c1e7ff3e7834b93195ee2f1a829fbed3971..90fba9bf98da7104ee5ef74bd0f259653d279aa3 100644 (file)
@@ -361,7 +361,7 @@ static int mt7620_pci_probe(struct platform_device *pdev)
        return 0;
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        u16 cmd;
        u32 val;
index 9ee01936862ee1dfe11d8a21754bb16572230aac..3e92a06fa77288c2705e8435e9352b6bf8c5e368 100644 (file)
@@ -59,8 +59,7 @@ union octeon_pci_address {
        } s;
 };
 
-int __initconst (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
-                                        u8 slot, u8 pin);
+int (*octeon_pcibios_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
 enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
 
 /**
@@ -74,7 +73,7 @@ enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
  *              as it goes through each bridge.
  * Returns Interrupt number for the device
  */
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        if (octeon_pcibios_map_irq)
                return octeon_pcibios_map_irq(dev, slot, pin);
index d6360fe73d058c5733274fb1b163c393a3f0e14c..711cdccdf65ba7df9647f72bd11952432086e33b 100644 (file)
@@ -181,7 +181,7 @@ static inline void rt2880_pci_write_u32(unsigned long reg, u32 val)
        spin_unlock_irqrestore(&rt2880_pci_lock, flags);
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        u16 cmd;
        int irq = -1;
index 04f8ea953297ff96dfef3fedebc031075c31251d..958899ffe99c14b3e149a88e303fb4cd3d497d81 100644 (file)
@@ -564,7 +564,7 @@ err_put_intc_node:
        return err;
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return of_irq_parse_and_map_pci(dev, slot, pin);
 }
index 000c0e1f9ef869d884d8c9a0cbb286ba87bae97b..a6418460e3c4447e62028b63655e29233a166c42 100644 (file)
@@ -112,7 +112,7 @@ int __init tx4938_pciclk66_setup(void)
        return pciclk;
 }
 
-int __init tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
+int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
 {
        if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4938_pcic1ptr) {
                switch (slot) {
index 9d6acc00f3489ddbf4558aa1d67568899e7eea9f..09a65f7dbe7ca001d55780d0bf7c2008a9320cdf 100644 (file)
@@ -48,7 +48,7 @@ void __init tx4939_report_pci1clk(void)
                ((pciclk + 50000) / 100000) % 10);
 }
 
-int __init tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
+int tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
 {
        if (get_tx4927_pcicptr(dev->bus->sysdata) == tx4939_pcic1ptr) {
                switch (slot) {
@@ -68,7 +68,7 @@ int __init tx4939_pcic1_map_irq(const struct pci_dev *dev, u8 slot)
        return -1;
 }
 
-int __init tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int tx4939_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq = tx4939_pcic1_map_irq(dev, slot);
 
index 7babf01600cb0fd9cbb97d4bb40f079693b2e8ed..9eff9137f78e52dc60bd4c031e42f1db4001ab6e 100644 (file)
@@ -205,7 +205,7 @@ int xlp_socdev_to_node(const struct pci_dev *lnkdev)
                return PCI_SLOT(lnkdev->devfn) / 8;
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct pci_dev *lnkdev;
        int lnkfunc, node;
index 26d2dabef28152541b709b11d2257cb563fe0349..2a1c81a129ba31ae9a6757ef819f2cab3fe2f93a 100644 (file)
@@ -315,7 +315,7 @@ static void xls_pcie_ack_b(struct irq_data *d)
        }
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        return get_irq_vector(dev);
 }
index ad3584dbc9d72bc1d0b845a1089ce41cec494737..fd2887415bc8935acf86c79a864b78dbd5878a03 100644 (file)
@@ -1464,8 +1464,7 @@ static int cvmx_pcie_rc_initialize(int pcie_port)
  *              as it goes through each bridge.
  * Returns Interrupt number for the device
  */
-int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev,
-                                      u8 slot, u8 pin)
+int octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        /*
         * The EBH5600 board with the PCI to PCIe bridge mistakenly
index ffa0f7101a9773ec8e24813f37e3c270d912b5e2..2b08242ade628989e96aa3f24450b406ecdc7e7a 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 
+#include <asm/setup.h>
+
 #ifdef CONFIG_MIPS_MT_SMP
 #define MIPS_CPU_IPI_RESCHED_IRQ 0     /* SW int 0 for resched */
 #define MIPS_CPU_IPI_CALL_IRQ 1                /* SW int 1 for call */
index 0bd2a1e1ff9ab8e0f0d8c56e31872ac08404c7b6..fb998726bd5d58b31e520d8ac4f8290835db473a 100644 (file)
@@ -386,9 +386,10 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        return 0;
 }
 
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int (*txx9_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       return txx9_board_vec->pci_map_irq(dev, slot, pin);
+       return txx9_pci_map_irq(dev, slot, pin);
 }
 
 char * (*txx9_board_pcibios_setup)(char *str) __initdata;
@@ -424,5 +425,8 @@ char *__init txx9_pcibios_setup(char *str)
                        txx9_pci_err_action = TXX9_PCI_ERR_IGNORE;
                return NULL;
        }
+
+       txx9_pci_map_irq = txx9_board_vec->pci_map_irq;
+
        return str;
 }
index 89e8027e07fb327d39de0170c0da61af177c7160..7c475fd99c468396122e77c8f1dbe738ae368bc0 100644 (file)
@@ -59,10 +59,6 @@ void arch_cpu_idle(void)
 }
 #endif
 
-void release_segments(struct mm_struct *mm)
-{
-}
-
 void machine_restart(char *cmd)
 {
 #ifdef CONFIG_KERNEL_DEBUGGER
@@ -112,14 +108,6 @@ void release_thread(struct task_struct *dead_task)
 {
 }
 
-/*
- * we do not have to muck with descriptors here, that is
- * done in switch_mm() as needed.
- */
-void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
-{
-}
-
 /*
  * this gets called so that we can store lazy state into memory and copy the
  * current task into the new thread.
index ba7b7ddc38442dab7e9b0679bba03478bf20096c..a57dedbfc7b77802e09104ee115702a9fe6fee13 100644 (file)
@@ -257,6 +257,18 @@ config PARISC_PAGE_SIZE_64KB
 
 endchoice
 
+config PARISC_SELF_EXTRACT
+       bool "Build kernel as self-extracting executable"
+       default y
+       help
+         Say Y if you want to build the parisc kernel as a kind of
+         self-extracting executable.
+
+         If you say N here, the kernel will be compressed with gzip
+         which can be loaded by the palo bootloader directly too.
+
+         If you don't know what to do here, say Y.
+
 config SMP
        bool "Symmetric multi-processing support"
        ---help---
index 58fae5d2449daae762fbe09f54a52561e29832f9..01946ebaff72814435cf6128665bd778eb217fb1 100644 (file)
@@ -129,8 +129,13 @@ Image: vmlinux
 bzImage: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
+ifdef CONFIG_PARISC_SELF_EXTRACT
 vmlinuz: bzImage
        $(OBJCOPY) $(boot)/bzImage $@
+else
+vmlinuz: vmlinux
+       @gzip -cf -9 $< > $@
+endif
 
 install:
        $(CONFIG_SHELL) $(src)/arch/parisc/install.sh \
index 5450a11c9d108cf1bfeefef0af4f943e29551a41..7d7e594bda36f0403aef33577c9e75c1817011d4 100644 (file)
@@ -15,7 +15,7 @@ targets += misc.o piggy.o sizes.h head.o real2.o firmware.o
 KBUILD_CFLAGS := -D__KERNEL__ -O2 -DBOOTLOADER
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks
-KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs
+KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs -Os
 ifndef CONFIG_64BIT
 KBUILD_CFLAGS += -mfast-indirect-calls
 endif
index 13a4bf9ac4dae5eb626c5c9d01c7e6448a232df0..9345b44b86f036572e33721eb80e9bbbe4493aa4 100644 (file)
@@ -24,7 +24,8 @@
 /* Symbols defined by linker scripts */
 extern char input_data[];
 extern int input_len;
-extern __le32 output_len;      /* at unaligned address, little-endian */
+/* output_len is inserted by the linker possibly at an unaligned address */
+extern __le32 output_len __aligned(1);
 extern char _text, _end;
 extern char _bss, _ebss;
 extern char _startcode_end;
index 26b4455baa8370560bb572d7cb550cdbd17f1101..510341f62d979e0ced75108c4b771380e0866c57 100644 (file)
@@ -280,6 +280,7 @@ void setup_pdc(void);               /* in inventory.c */
 /* wrapper-functions from pdc.c */
 
 int pdc_add_valid(unsigned long address);
+int pdc_instr(unsigned int *instr);
 int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len);
 int pdc_chassis_disp(unsigned long disp);
 int pdc_chassis_warn(unsigned long *warn);
index a5dc9066c6d8d50cb35f2e4cf88509fa4621b84b..ad9c9c3b4136da6633e5d0c72fb117465376993e 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
+extern int init_per_cpu(int cpuid);
 
 #if defined(CONFIG_SMP)
 
index ab80e5c6f6517c4f165ab9ce8c3863b2d94e7c05..6d471c00c71af12f6a48c4deebb5d260071d5dd3 100644 (file)
@@ -232,6 +232,26 @@ int pdc_add_valid(unsigned long address)
 }
 EXPORT_SYMBOL(pdc_add_valid);
 
+/**
+ * pdc_instr - Get instruction that invokes PDCE_CHECK in HPMC handler.
+ * @instr: Pointer to variable which will get instruction opcode.
+ *
+ * The return value is PDC_OK (0) in case call succeeded.
+ */
+int __init pdc_instr(unsigned int *instr)
+{
+       int retval;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pdc_lock, flags);
+       retval = mem_pdc_call(PDC_INSTR, 0UL, __pa(pdc_result));
+       convert_to_wide(pdc_result);
+       *instr = pdc_result[0];
+       spin_unlock_irqrestore(&pdc_lock, flags);
+
+       return retval;
+}
+
 /**
  * pdc_chassis_info - Return chassis information.
  * @result: The return buffer.
index 05730a83895c7f5700760e880a460257e8c372ba..00aed082969b126719a988bbe7c63a210c10ed90 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/memblock.h>
 #include <linux/seq_file.h>
 #include <linux/kthread.h>
+#include <linux/initrd.h>
 
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
@@ -216,8 +217,16 @@ void __init pdc_pdt_init(void)
        }
 
        for (i = 0; i < pdt_status.pdt_entries; i++) {
+               unsigned long addr;
+
                report_mem_err(pdt_entry[i]);
 
+               addr = pdt_entry[i] & PDT_ADDR_PHYS_MASK;
+               if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) &&
+                       addr >= initrd_start && addr < initrd_end)
+                       pr_crit("CRITICAL: initrd possibly broken "
+                               "due to bad memory!\n");
+
                /* mark memory page bad */
                memblock_reserve(pdt_entry[i] & PAGE_MASK, PAGE_SIZE);
        }
index a778bd3c107c507e5a76d99e06813876aad64bd7..e120d63c1b285ad545c2281de0abbbcc2dde6e08 100644 (file)
@@ -317,7 +317,7 @@ void __init collect_boot_cpu_data(void)
  *
  * o Enable CPU profiling hooks.
  */
-int init_per_cpu(int cpunum)
+int __init init_per_cpu(int cpunum)
 {
        int ret;
        struct pdc_coproc_cfg coproc_cfg;
index dee6f9d6a153ce461ec816e6caeb5a38dd3bb9f2..f7d0c3b33d70a53b5350729f1e3d59b2e803749b 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/sched/clock.h>
+#include <linux/start_kernel.h>
 
 #include <asm/processor.h>
 #include <asm/sections.h>
@@ -48,6 +49,7 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/unwind.h>
+#include <asm/smp.h>
 
 static char __initdata command_line[COMMAND_LINE_SIZE];
 
@@ -115,7 +117,6 @@ void __init dma_ops_init(void)
 }
 #endif
 
-extern int init_per_cpu(int cpuid);
 extern void collect_boot_cpu_data(void);
 
 void __init setup_arch(char **cmdline_p)
@@ -398,9 +399,8 @@ static int __init parisc_init(void)
 }
 arch_initcall(parisc_init);
 
-void start_parisc(void)
+void __init start_parisc(void)
 {
-       extern void start_kernel(void);
        extern void early_trap_init(void);
 
        int ret, cpunum;
index 63365106ea1907589bbdee1688a1a9be54b1a74d..30c28ab145409b5966f7237ec2b6ca07121adc10 100644 (file)
@@ -255,12 +255,11 @@ void arch_send_call_function_single_ipi(int cpu)
 static void __init
 smp_cpu_init(int cpunum)
 {
-       extern int init_per_cpu(int);  /* arch/parisc/kernel/processor.c */
        extern void init_IRQ(void);    /* arch/parisc/kernel/irq.c */
        extern void start_cpu_itimer(void); /* arch/parisc/kernel/time.c */
 
        /* Set modes and Enable floating point coprocessor */
-       (void) init_per_cpu(cpunum);
+       init_per_cpu(cpunum);
 
        disable_sr_hashing();
 
index 991654c88eec8635056bef3ae9f536a6e8ff8862..230333157fe384c4171749e2b4eab43e3070a89d 100644 (file)
@@ -817,7 +817,7 @@ void __init initialize_ivt(const void *iva)
        u32 check = 0;
        u32 *ivap;
        u32 *hpmcp;
-       u32 length;
+       u32 length, instr;
 
        if (strcmp((const char *)iva, "cows can fly"))
                panic("IVT invalid");
@@ -827,6 +827,14 @@ void __init initialize_ivt(const void *iva)
        for (i = 0; i < 8; i++)
            *ivap++ = 0;
 
+       /*
+        * Use PDC_INSTR firmware function to get instruction that invokes
+        * PDCE_CHECK in HPMC handler.  See programming note at page 1-31 of
+        * the PA 1.1 Firmware Architecture document.
+        */
+       if (pdc_instr(&instr) == PDC_OK)
+               ivap[0] = instr;
+
        /* Compute Checksum for HPMC handler */
        length = os_hpmc_size;
        ivap[7] = length;
index 48dc7d4d20bba5e6fdb8669ae6d03b3ed3cb27c4..caab39dfa95d606564af62d3fd565eef6fc41757 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/kallsyms.h>
 #include <linux/sort.h>
+#include <linux/sched.h>
 
 #include <linux/uaccess.h>
 #include <asm/assembly.h>
@@ -279,6 +280,17 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
 
                        info->prev_sp = sp - 64;
                        info->prev_ip = 0;
+
+                       /* The stack is at the end inside the thread_union
+                        * struct. If we reach data, we have reached the
+                        * beginning of the stack and should stop unwinding. */
+                       if (info->prev_sp >= (unsigned long) task_thread_info(info->t) &&
+                           info->prev_sp < ((unsigned long) task_thread_info(info->t)
+                                               + THREAD_SZ_ALGN)) {
+                               info->prev_sp = 0;
+                               break;
+                       }
+
                        if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) 
                                break;
                        info->prev_ip = tmp;
index 5b101f6a5607dc1ef9e229b6f2421a78d35355ce..e247edbca68ecd2f56500e467776c9d2fa1f1c11 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/extable.h>
 #include <linux/uaccess.h>
+#include <linux/hugetlb.h>
 
 #include <asm/traps.h>
 
@@ -261,7 +262,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
        struct task_struct *tsk;
        struct mm_struct *mm;
        unsigned long acc_type;
-       int fault;
+       int fault = 0;
        unsigned int flags;
 
        if (faulthandler_disabled())
@@ -315,7 +316,8 @@ good_area:
                        goto out_of_memory;
                else if (fault & VM_FAULT_SIGSEGV)
                        goto bad_area;
-               else if (fault & VM_FAULT_SIGBUS)
+               else if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
+                                 VM_FAULT_HWPOISON_LARGE))
                        goto bad_area;
                BUG();
        }
@@ -352,8 +354,7 @@ bad_area:
 
        if (user_mode(regs)) {
                struct siginfo si;
-
-               show_signal_msg(regs, code, address, tsk, vma);
+               unsigned int lsb = 0;
 
                switch (code) {
                case 15:        /* Data TLB miss fault/Data page fault */
@@ -386,6 +387,30 @@ bad_area:
                        si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
                        break;
                }
+
+#ifdef CONFIG_MEMORY_FAILURE
+               if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
+                       printk(KERN_ERR
+       "MCE: Killing %s:%d due to hardware memory corruption fault at %08lx\n",
+                       tsk->comm, tsk->pid, address);
+                       si.si_signo = SIGBUS;
+                       si.si_code = BUS_MCEERR_AR;
+               }
+#endif
+
+               /*
+                * Either small page or large page may be poisoned.
+                * In other words, VM_FAULT_HWPOISON_LARGE and
+                * VM_FAULT_HWPOISON are mutually exclusive.
+                */
+               if (fault & VM_FAULT_HWPOISON_LARGE)
+                       lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
+               else if (fault & VM_FAULT_HWPOISON)
+                       lsb = PAGE_SHIFT;
+               else
+                       show_signal_msg(regs, code, address, tsk, vma);
+               si.si_addr_lsb = lsb;
+
                si.si_errno = 0;
                si.si_addr = (void __user *) address;
                force_sig_info(si.si_signo, &si, current);
index e084fa548d73d217b72ca96dbe0783dbf1b2105d..063817fee61cfeea164555a99139de3ffda3aedf 100644 (file)
@@ -138,10 +138,11 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQUENCER_OSS=m
 CONFIG_SND_POWERMAC=m
 CONFIG_SND_AOA=m
 CONFIG_SND_AOA_FABRIC_LAYOUT=m
index 79bbc8238b325aa5a637b7bc79913ebbc835b3be..805b0f87653c1939f2722929689db2ebb128930f 100644 (file)
@@ -64,11 +64,12 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_SOUND=y
 CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=y
index 8cf4a46bef86b00c0d2f5562d3f30262be4f5ecd..6daa56f8895cb22bcd37011328c68932abe50074 100644 (file)
@@ -115,9 +115,10 @@ CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER=y
 CONFIG_SND_SEQUENCER_OSS=y
 CONFIG_SND_USB_AUDIO=y
 CONFIG_SND_USB_USX2Y=y
index 8e798b1fbc9900eba3830878e77ea809a8b56b90..1aab9a62a681d4856aff8f7afaa0f9435832b4d9 100644 (file)
@@ -227,11 +227,12 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SEQUENCER_OSS=m
 CONFIG_SND_DUMMY=m
 CONFIG_SND_POWERMAC=m
 CONFIG_SND_AOA=m
index 791db775a09cac4e695fd199f9f9ed060337ea5c..6ddca80c52c3b4c1fef2e1442a5c1d2a31f24e2e 100644 (file)
@@ -222,11 +222,12 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SEQUENCER_OSS=m
 CONFIG_SND_POWERMAC=m
 CONFIG_SND_AOA=m
 CONFIG_SND_AOA_FABRIC_LAYOUT=m
index d0fe0f8f77c236f03470abb7fc039861e6587a12..41d85cb3c9a2fb65fae203654e0759dde8099080 100644 (file)
@@ -141,11 +141,12 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SEQUENCER_OSS=m
 CONFIG_HID_DRAGONRISE=y
 CONFIG_HID_GYRATION=y
 CONFIG_HID_TWINHAN=y
index ae6eba482d75da632b90be24bb83a89cb7140e78..da0e8d535eb8889efbd937a1d2ba62aac6236400 100644 (file)
@@ -789,17 +789,18 @@ CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_SOUND=m
 CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
 CONFIG_SND_DYNAMIC_MINORS=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
 CONFIG_SND_VERBOSE_PRINTK=y
 CONFIG_SND_DEBUG=y
 CONFIG_SND_DEBUG_VERBOSE=y
 CONFIG_SND_PCM_XRUN_DEBUG=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SEQUENCER_OSS=m
 CONFIG_SND_DUMMY=m
 CONFIG_SND_VIRMIDI=m
 CONFIG_SND_MTPAV=m
index aef41b17a8bc02d0445bd8f145904f0b9c9454b0..9c7400a19e9df2aca8b005bb658d802c48eb88af 100644 (file)
@@ -79,11 +79,12 @@ CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_SOUND=y
 CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_SEQUENCER_OSS=y
 CONFIG_HID_APPLE=m
 CONFIG_HID_WACOM=m
 CONFIG_MMC=y
index 9e816787c0d49fd31bc153debe1235e01281a5fa..116000b4553195f44adabf2894b002fcd5e6d6e1 100644 (file)
@@ -1019,6 +1019,10 @@ int eeh_init(void)
        } else if ((ret = eeh_ops->init()))
                return ret;
 
+       /* Initialize PHB PEs */
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+               eeh_dev_phb_init_dynamic(hose);
+
        /* Initialize EEH event */
        ret = eeh_event_init();
        if (ret)
index ad04ecd63c207def1a1dbb33172c4acc933a2a39..a34e6912c15e2a027c55b3ef1802d22792cac5f9 100644 (file)
@@ -78,21 +78,3 @@ void eeh_dev_phb_init_dynamic(struct pci_controller *phb)
        /* EEH PE for PHB */
        eeh_phb_pe_create(phb);
 }
-
-/**
- * eeh_dev_phb_init - Create EEH devices for devices included in existing PHBs
- *
- * Scan all the existing PHBs and create EEH devices for their OF
- * nodes and their children OF nodes
- */
-static int __init eeh_dev_phb_init(void)
-{
-       struct pci_controller *phb, *tmp;
-
-       list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
-               eeh_dev_phb_init_dynamic(phb);
-
-       return 0;
-}
-
-core_initcall(eeh_dev_phb_init);
index 6f8273f5e988b2cca6f320299ca6c67445ebca66..91e037ab20a197de398161c057d86bffabc3a68a 100644 (file)
@@ -104,8 +104,10 @@ static unsigned long can_optimize(struct kprobe *p)
         * and that can be emulated.
         */
        if (!is_conditional_branch(*p->ainsn.insn) &&
-                       analyse_instr(&op, &regs, *p->ainsn.insn))
+                       analyse_instr(&op, &regs, *p->ainsn.insn) == 1) {
+               emulate_update_regs(&regs, &op);
                nip = regs.nip;
+       }
 
        return nip;
 }
index 07cd22e354053597d990bf57457164bbb6f02b9c..f52ad5bb710960906b8ae61400688845e2811dd5 100644 (file)
@@ -131,7 +131,7 @@ static void flush_tmregs_to_thread(struct task_struct *tsk)
         * in the appropriate thread structures from live.
         */
 
-       if (tsk != current)
+       if ((!cpu_has_feature(CPU_FTR_TM)) || (tsk != current))
                return;
 
        if (MSR_TM_SUSPENDED(mfmsr())) {
index ec74e203ee04e5b8e7e307df28c133b6226cd487..13c9dcdcba6922e32d4c00267201f47e9498f805 100644 (file)
@@ -437,6 +437,7 @@ static inline int check_io_access(struct pt_regs *regs)
 int machine_check_e500mc(struct pt_regs *regs)
 {
        unsigned long mcsr = mfspr(SPRN_MCSR);
+       unsigned long pvr = mfspr(SPRN_PVR);
        unsigned long reason = mcsr;
        int recoverable = 1;
 
@@ -478,8 +479,15 @@ int machine_check_e500mc(struct pt_regs *regs)
                 * may still get logged and cause a machine check.  We should
                 * only treat the non-write shadow case as non-recoverable.
                 */
-               if (!(mfspr(SPRN_L1CSR2) & L1CSR2_DCWS))
-                       recoverable = 0;
+               /* On e6500 core, L1 DCWS (Data cache write shadow mode) bit
+                * is not implemented but L1 data cache always runs in write
+                * shadow mode. Hence on data cache parity errors HW will
+                * automatically invalidate the L1 Data Cache.
+                */
+               if (PVR_VER(pvr) != PVR_VER_E6500) {
+                       if (!(mfspr(SPRN_L1CSR2) & L1CSR2_DCWS))
+                               recoverable = 0;
+               }
        }
 
        if (reason & MCSR_L2MMU_MHIT) {
index 17936f82d3c787c38327f41186f634d043d843a9..ec69fa45d5a2f249322d32218a722f4d54390e97 100644 (file)
@@ -1121,6 +1121,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
 BEGIN_FTR_SECTION
        mtspr   SPRN_PPR, r0
 END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
+
+/* Move canary into DSISR to check for later */
+BEGIN_FTR_SECTION
+       li      r0, 0x7fff
+       mtspr   SPRN_HDSISR, r0
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
        ld      r0, VCPU_GPR(R0)(r4)
        ld      r4, VCPU_GPR(R4)(r4)
 
@@ -1956,9 +1963,14 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
 kvmppc_hdsi:
        ld      r3, VCPU_KVM(r9)
        lbz     r0, KVM_RADIX(r3)
-       cmpwi   r0, 0
        mfspr   r4, SPRN_HDAR
        mfspr   r6, SPRN_HDSISR
+BEGIN_FTR_SECTION
+       /* Look for DSISR canary. If we find it, retry instruction */
+       cmpdi   r6, 0x7fff
+       beq     6f
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+       cmpwi   r0, 0
        bne     .Lradix_hdsi            /* on radix, just save DAR/DSISR/ASDR */
        /* HPTE not found fault or protection fault? */
        andis.  r0, r6, (DSISR_NOHPTE | DSISR_PROTFAULT)@h
index fb9f58b868e76ef0692e45fe874b6546cf74de37..5e8418c28bd884bd854818755b61b06fcff776e6 100644 (file)
@@ -944,9 +944,9 @@ NOKPROBE_SYMBOL(emulate_dcbz);
                : "r" (addr), "i" (-EFAULT), "0" (err))
 
 static nokprobe_inline void set_cr0(const struct pt_regs *regs,
-                                   struct instruction_op *op, int rd)
+                                   struct instruction_op *op)
 {
-       long val = regs->gpr[rd];
+       long val = op->val;
 
        op->type |= SETCC;
        op->ccval = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000);
@@ -1326,7 +1326,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
        case 13:        /* addic. */
                imm = (short) instr;
                add_with_carry(regs, op, rd, regs->gpr[ra], imm, 0);
-               set_cr0(regs, op, rd);
+               set_cr0(regs, op);
                return 1;
 
        case 14:        /* addi */
@@ -1397,13 +1397,13 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
        case 28:        /* andi. */
                op->val = regs->gpr[rd] & (unsigned short) instr;
-               set_cr0(regs, op, ra);
+               set_cr0(regs, op);
                goto logical_done_nocc;
 
        case 29:        /* andis. */
                imm = (unsigned short) instr;
                op->val = regs->gpr[rd] & (imm << 16);
-               set_cr0(regs, op, ra);
+               set_cr0(regs, op);
                goto logical_done_nocc;
 
 #ifdef __powerpc64__
@@ -1513,10 +1513,10 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        op->type = COMPUTE + SETCC;
                        imm = 0xf0000000UL;
                        val = regs->gpr[rd];
-                       op->val = regs->ccr;
+                       op->ccval = regs->ccr;
                        for (sh = 0; sh < 8; ++sh) {
                                if (instr & (0x80000 >> sh))
-                                       op->val = (op->val & ~imm) |
+                                       op->ccval = (op->ccval & ~imm) |
                                                (val & imm);
                                imm >>= 4;
                        }
@@ -1651,8 +1651,9 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
                        goto arith_done;
 
                case 235:       /* mullw */
-                       op->val = (unsigned int) regs->gpr[ra] *
-                               (unsigned int) regs->gpr[rb];
+                       op->val = (long)(int) regs->gpr[ra] *
+                               (int) regs->gpr[rb];
+
                        goto arith_done;
 
                case 266:       /* add */
@@ -2526,7 +2527,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
  logical_done:
        if (instr & 1)
-               set_cr0(regs, op, ra);
+               set_cr0(regs, op);
  logical_done_nocc:
        op->reg = ra;
        op->type |= SETREG;
@@ -2534,7 +2535,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
 
  arith_done:
        if (instr & 1)
-               set_cr0(regs, op, rd);
+               set_cr0(regs, op);
  compute_done:
        op->reg = rd;
        op->type |= SETREG;
index 2e3eb7431571603fc9cd2452df25a32c6cd4c6da..9e3da168d54cdcd36e3911ff040ff2ad187c92b7 100644 (file)
@@ -793,6 +793,11 @@ void perf_event_print_debug(void)
        u32 pmcs[MAX_HWEVENTS];
        int i;
 
+       if (!ppmu) {
+               pr_info("Performance monitor hardware not registered.\n");
+               return;
+       }
+
        if (!ppmu->n_counter)
                return;
 
index 9f59041a172bbfdea270ccb4139e66948bc3354f..443d5ca719958e5170374edbcaaf7d2cc52b8104 100644 (file)
@@ -393,7 +393,13 @@ static void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val)
        u64 pir = get_hard_smp_processor_id(cpu);
 
        mtspr(SPRN_LPCR, lpcr_val);
-       opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val);
+
+       /*
+        * Program the LPCR via stop-api only if the deepest stop state
+        * can lose hypervisor context.
+        */
+       if (supported_cpuidle_states & OPAL_PM_LOSE_FULL_CONTEXT)
+               opal_slw_set_reg(pir, SPRN_LPCR, lpcr_val);
 }
 
 /*
index 783f3636469093034ae26a23856fef6aaf1922a6..e45b5f10645ae54b6610298a0a03c07f7e5d0966 100644 (file)
@@ -266,7 +266,6 @@ int dlpar_attach_node(struct device_node *dn, struct device_node *parent)
                return rc;
        }
 
-       of_node_put(dn->parent);
        return 0;
 }
 
index fc0d8f97c03a2f243a51c9ba27c7043626bd95cc..fadb95efbb9e1856ed8a7182cf870dcf3a5f5331 100644 (file)
@@ -462,15 +462,19 @@ static ssize_t dlpar_cpu_add(u32 drc_index)
        }
 
        dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
-       of_node_put(parent);
        if (!dn) {
                pr_warn("Failed call to configure-connector, drc index: %x\n",
                        drc_index);
                dlpar_release_drc(drc_index);
+               of_node_put(parent);
                return -EINVAL;
        }
 
        rc = dlpar_attach_node(dn, parent);
+
+       /* Regardless we are done with parent now */
+       of_node_put(parent);
+
        if (rc) {
                saved_rc = rc;
                pr_warn("Failed to attach node %s, rc: %d, drc index: %x\n",
index 210ce632d63e1e47c2796acd767e3bf610da7439..f7042ad492bafba5ac21e3db9ce24977fd527169 100644 (file)
@@ -226,8 +226,10 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
                return -ENOENT;
 
        dn = dlpar_configure_connector(drc_index, parent_dn);
-       if (!dn)
+       if (!dn) {
+               of_node_put(parent_dn);
                return -ENOENT;
+       }
 
        rc = dlpar_attach_node(dn, parent_dn);
        if (rc)
index dce708e061eac79a56b655eb71bb6bb63f3ce978..20e75a2ca93a283f6413ca6a8ee40ff280e3c74d 100644 (file)
@@ -1507,7 +1507,9 @@ static inline pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma,
 static inline void pmdp_invalidate(struct vm_area_struct *vma,
                                   unsigned long addr, pmd_t *pmdp)
 {
-       pmdp_xchg_direct(vma->vm_mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY));
+       pmd_t pmd = __pmd(pmd_val(*pmdp) | _SEGMENT_ENTRY_INVALID);
+
+       pmdp_xchg_direct(vma->vm_mm, addr, pmdp, pmd);
 }
 
 #define __HAVE_ARCH_PMDP_SET_WRPROTECT
index ca8cd80e8feb7c6f01be173a76471420020e2bb6..60181caf8e8ad332029212e82b07c561cb44395a 100644 (file)
@@ -404,18 +404,6 @@ static inline void save_vector_registers(void)
 #endif
 }
 
-static int __init topology_setup(char *str)
-{
-       bool enabled;
-       int rc;
-
-       rc = kstrtobool(str, &enabled);
-       if (!rc && !enabled)
-               S390_lowcore.machine_flags &= ~MACHINE_FLAG_TOPOLOGY;
-       return rc;
-}
-early_param("topology", topology_setup);
-
 static int __init disable_vector_extension(char *str)
 {
        S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX;
index c1bf75ffb8756549b1c6a5c97908ff49dd2e79aa..7e1e40323b78e1bb7a3910e1191dfbe40027b748 100644 (file)
@@ -823,9 +823,12 @@ static int cpumsf_pmu_event_init(struct perf_event *event)
        }
 
        /* Check online status of the CPU to which the event is pinned */
-       if ((unsigned int)event->cpu >= nr_cpumask_bits ||
-           (event->cpu >= 0 && !cpu_online(event->cpu)))
-               return -ENODEV;
+       if (event->cpu >= 0) {
+               if ((unsigned int)event->cpu >= nr_cpumask_bits)
+                       return -ENODEV;
+               if (!cpu_online(event->cpu))
+                       return -ENODEV;
+       }
 
        /* Force reset of idle/hv excludes regardless of what the
         * user requested.
index bb47c92476f0d852ded0b9b50f9756e46480e9b9..ed0bdd220e1a643788655fbefaef328dd38c7951 100644 (file)
@@ -8,6 +8,8 @@
 
 #include <linux/workqueue.h>
 #include <linux/bootmem.h>
+#include <linux/uaccess.h>
+#include <linux/sysctl.h>
 #include <linux/cpuset.h>
 #include <linux/device.h>
 #include <linux/export.h>
 #define PTF_VERTICAL   (1UL)
 #define PTF_CHECK      (2UL)
 
+enum {
+       TOPOLOGY_MODE_HW,
+       TOPOLOGY_MODE_SINGLE,
+       TOPOLOGY_MODE_PACKAGE,
+       TOPOLOGY_MODE_UNINITIALIZED
+};
+
 struct mask_info {
        struct mask_info *next;
        unsigned char id;
        cpumask_t mask;
 };
 
+static int topology_mode = TOPOLOGY_MODE_UNINITIALIZED;
 static void set_topology_timer(void);
 static void topology_work_fn(struct work_struct *work);
 static struct sysinfo_15_1_x *tl_info;
@@ -59,11 +69,26 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
        cpumask_t mask;
 
        cpumask_copy(&mask, cpumask_of(cpu));
-       if (!MACHINE_HAS_TOPOLOGY)
-               return mask;
-       for (; info; info = info->next) {
-               if (cpumask_test_cpu(cpu, &info->mask))
-                       return info->mask;
+       switch (topology_mode) {
+       case TOPOLOGY_MODE_HW:
+               while (info) {
+                       if (cpumask_test_cpu(cpu, &info->mask)) {
+                               mask = info->mask;
+                               break;
+                       }
+                       info = info->next;
+               }
+               if (cpumask_empty(&mask))
+                       cpumask_copy(&mask, cpumask_of(cpu));
+               break;
+       case TOPOLOGY_MODE_PACKAGE:
+               cpumask_copy(&mask, cpu_present_mask);
+               break;
+       default:
+               /* fallthrough */
+       case TOPOLOGY_MODE_SINGLE:
+               cpumask_copy(&mask, cpumask_of(cpu));
+               break;
        }
        return mask;
 }
@@ -74,7 +99,7 @@ static cpumask_t cpu_thread_map(unsigned int cpu)
        int i;
 
        cpumask_copy(&mask, cpumask_of(cpu));
-       if (!MACHINE_HAS_TOPOLOGY)
+       if (topology_mode != TOPOLOGY_MODE_HW)
                return mask;
        cpu -= cpu % (smp_cpu_mtid + 1);
        for (i = 0; i <= smp_cpu_mtid; i++)
@@ -184,10 +209,8 @@ static void topology_update_polarization_simple(void)
 {
        int cpu;
 
-       mutex_lock(&smp_cpu_state_mutex);
        for_each_possible_cpu(cpu)
                smp_cpu_set_polarization(cpu, POLARIZATION_HRZ);
-       mutex_unlock(&smp_cpu_state_mutex);
 }
 
 static int ptf(unsigned long fc)
@@ -223,7 +246,7 @@ int topology_set_cpu_management(int fc)
 static void update_cpu_masks(void)
 {
        struct cpu_topology_s390 *topo;
-       int cpu;
+       int cpu, id;
 
        for_each_possible_cpu(cpu) {
                topo = &cpu_topology[cpu];
@@ -231,12 +254,13 @@ static void update_cpu_masks(void)
                topo->core_mask = cpu_group_map(&socket_info, cpu);
                topo->book_mask = cpu_group_map(&book_info, cpu);
                topo->drawer_mask = cpu_group_map(&drawer_info, cpu);
-               if (!MACHINE_HAS_TOPOLOGY) {
+               if (topology_mode != TOPOLOGY_MODE_HW) {
+                       id = topology_mode == TOPOLOGY_MODE_PACKAGE ? 0 : cpu;
                        topo->thread_id = cpu;
                        topo->core_id = cpu;
-                       topo->socket_id = cpu;
-                       topo->book_id = cpu;
-                       topo->drawer_id = cpu;
+                       topo->socket_id = id;
+                       topo->book_id = id;
+                       topo->drawer_id = id;
                        if (cpu_present(cpu))
                                cpumask_set_cpu(cpu, &cpus_with_topology);
                }
@@ -254,6 +278,7 @@ static int __arch_update_cpu_topology(void)
        struct sysinfo_15_1_x *info = tl_info;
        int rc = 0;
 
+       mutex_lock(&smp_cpu_state_mutex);
        cpumask_clear(&cpus_with_topology);
        if (MACHINE_HAS_TOPOLOGY) {
                rc = 1;
@@ -263,6 +288,7 @@ static int __arch_update_cpu_topology(void)
        update_cpu_masks();
        if (!MACHINE_HAS_TOPOLOGY)
                topology_update_polarization_simple();
+       mutex_unlock(&smp_cpu_state_mutex);
        return rc;
 }
 
@@ -289,6 +315,11 @@ void topology_schedule_update(void)
        schedule_work(&topology_work);
 }
 
+static void topology_flush_work(void)
+{
+       flush_work(&topology_work);
+}
+
 static void topology_timer_fn(unsigned long ignored)
 {
        if (ptf(PTF_CHECK))
@@ -459,6 +490,12 @@ void __init topology_init_early(void)
        struct sysinfo_15_1_x *info;
 
        set_sched_topology(s390_topology);
+       if (topology_mode == TOPOLOGY_MODE_UNINITIALIZED) {
+               if (MACHINE_HAS_TOPOLOGY)
+                       topology_mode = TOPOLOGY_MODE_HW;
+               else
+                       topology_mode = TOPOLOGY_MODE_SINGLE;
+       }
        if (!MACHINE_HAS_TOPOLOGY)
                goto out;
        tl_info = memblock_virt_alloc(PAGE_SIZE, PAGE_SIZE);
@@ -474,12 +511,97 @@ out:
        __arch_update_cpu_topology();
 }
 
+static inline int topology_get_mode(int enabled)
+{
+       if (!enabled)
+               return TOPOLOGY_MODE_SINGLE;
+       return MACHINE_HAS_TOPOLOGY ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE;
+}
+
+static inline int topology_is_enabled(void)
+{
+       return topology_mode != TOPOLOGY_MODE_SINGLE;
+}
+
+static int __init topology_setup(char *str)
+{
+       bool enabled;
+       int rc;
+
+       rc = kstrtobool(str, &enabled);
+       if (rc)
+               return rc;
+       topology_mode = topology_get_mode(enabled);
+       return 0;
+}
+early_param("topology", topology_setup);
+
+static int topology_ctl_handler(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       unsigned int len;
+       int new_mode;
+       char buf[2];
+
+       if (!*lenp || *ppos) {
+               *lenp = 0;
+               return 0;
+       }
+       if (!write) {
+               strncpy(buf, topology_is_enabled() ? "1\n" : "0\n",
+                       ARRAY_SIZE(buf));
+               len = strnlen(buf, ARRAY_SIZE(buf));
+               if (len > *lenp)
+                       len = *lenp;
+               if (copy_to_user(buffer, buf, len))
+                       return -EFAULT;
+               goto out;
+       }
+       len = *lenp;
+       if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))
+               return -EFAULT;
+       if (buf[0] != '0' && buf[0] != '1')
+               return -EINVAL;
+       mutex_lock(&smp_cpu_state_mutex);
+       new_mode = topology_get_mode(buf[0] == '1');
+       if (topology_mode != new_mode) {
+               topology_mode = new_mode;
+               topology_schedule_update();
+       }
+       mutex_unlock(&smp_cpu_state_mutex);
+       topology_flush_work();
+out:
+       *lenp = len;
+       *ppos += len;
+       return 0;
+}
+
+static struct ctl_table topology_ctl_table[] = {
+       {
+               .procname       = "topology",
+               .mode           = 0644,
+               .proc_handler   = topology_ctl_handler,
+       },
+       { },
+};
+
+static struct ctl_table topology_dir_table[] = {
+       {
+               .procname       = "s390",
+               .maxlen         = 0,
+               .mode           = 0555,
+               .child          = topology_ctl_table,
+       },
+       { },
+};
+
 static int __init topology_init(void)
 {
        if (MACHINE_HAS_TOPOLOGY)
                set_topology_timer();
        else
                topology_update_polarization_simple();
+       register_sysctl_table(topology_dir_table);
        return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
 }
 device_initcall(topology_init);
index 8ecc25e760fa6dfba0f082cfd8dff38b8c33d9e9..98ffe3ee9411ad23798c7ef896783ebd4d6edcfc 100644 (file)
@@ -56,13 +56,12 @@ static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
 static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
                unsigned long end, int write, struct page **pages, int *nr)
 {
-       unsigned long mask, result;
        struct page *head, *page;
+       unsigned long mask;
        int refs;
 
-       result = write ? 0 : _SEGMENT_ENTRY_PROTECT;
-       mask = result | _SEGMENT_ENTRY_INVALID;
-       if ((pmd_val(pmd) & mask) != result)
+       mask = (write ? _SEGMENT_ENTRY_PROTECT : 0) | _SEGMENT_ENTRY_INVALID;
+       if ((pmd_val(pmd) & mask) != 0)
                return 0;
        VM_BUG_ON(!pfn_valid(pmd_val(pmd) >> PAGE_SHIFT));
 
index 18e0377f72bbb9ad8f559b00fc2452532d0ad312..88ce1e22237b2b9a22f100e753d00456699ece47 100644 (file)
@@ -136,10 +136,6 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned lo
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/* Copy and release all segment info associated with a VM */
-#define copy_segments(p, mm)   do { } while(0)
-#define release_segments(mm)   do { } while(0)
-
 /*
  * FPU lazy state save handling.
  */
index eedd4f625d07650e1f392a37b45e22d765e51602..777a16318aff1fd41df535ccc91453d7d91d318f 100644 (file)
@@ -170,10 +170,6 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/* Copy and release all segment info associated with a VM */
-#define copy_segments(p, mm)   do { } while (0)
-#define release_segments(mm)   do { } while (0)
-#define forget_segments()      do { } while (0)
 /*
  * FPU lazy state save handling.
  */
index 0d925fa0f0c1f270c7bb6ffcacd8f548ede225ec..9f94435cc44f455597fad4afda30fca3e5238675 100644 (file)
@@ -409,5 +409,4 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
index 149d8e8eacb83c223d186f86d342de9db21f6063..1c5bd4f8ffca34110fe68fd3ffd96e98743aef2f 100644 (file)
@@ -189,7 +189,6 @@ CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
@@ -521,7 +520,6 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
 CONFIG_CRC_CCITT=m
 CONFIG_CRC7=m
index 6becb96c60a03c5515cb443b5cdc7c683e259433..ad83c1e66dbd23c5ba46e20c8e5deefdf6f3655e 100644 (file)
@@ -140,7 +140,7 @@ static int __init setup_maxnodemem(char *str)
 {
        char *endp;
        unsigned long long maxnodemem;
-       long node;
+       unsigned long node;
 
        node = str ? simple_strtoul(str, &endp, 0) : INT_MAX;
        if (node >= MAX_NUMNODES || *endp != ':')
index f6d1a3f747a9b58b3f33ce0ee25c3bf889985c0b..86942a492454c296bcc5cfc7f5fdd23544a46dc9 100644 (file)
@@ -58,11 +58,6 @@ static inline void release_thread(struct task_struct *task)
 {
 }
 
-static inline void mm_copy_segments(struct mm_struct *from_mm,
-                                   struct mm_struct *new_mm)
-{
-}
-
 #define init_stack     (init_thread_union.stack)
 
 /*
index 0b034ebbda2a1c2dd0125a6d4c2135dd886eb440..7f69d17de3540ca8491270408946a00654493cd2 100644 (file)
@@ -98,7 +98,7 @@ static struct clocksource timer_clocksource = {
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static void __init timer_setup(void)
+static void __init um_timer_setup(void)
 {
        int err;
 
@@ -132,5 +132,5 @@ void read_persistent_clock(struct timespec *ts)
 void __init time_init(void)
 {
        timer_set_signal_handler();
-       late_time_init = timer_setup;
+       late_time_init = um_timer_setup;
 }
index 246c67006ed06ad84516b3a56ceac06e05734a1c..8c1fcb6bad21f91604f0b61357db834f560b7fdb 100644 (file)
@@ -33,7 +33,7 @@
 #define s3     ((16 + 2 + (3 * 256)) * 4)
 
 /* register macros */
-#define CTX %rdi
+#define CTX %r12
 #define RIO %rsi
 
 #define RX0 %rax
 #define RX2bh %ch
 #define RX3bh %dh
 
-#define RT0 %rbp
+#define RT0 %rdi
 #define RT1 %rsi
 #define RT2 %r8
 #define RT3 %r9
 
-#define RT0d %ebp
+#define RT0d %edi
 #define RT1d %esi
 #define RT2d %r8d
 #define RT3d %r9d
 
 ENTRY(__blowfish_enc_blk)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         *      %rcx: bool, if true: xor output
         */
-       movq %rbp, %r11;
+       movq %r12, %r11;
 
+       movq %rdi, CTX;
        movq %rsi, %r10;
        movq %rdx, RIO;
 
@@ -142,7 +143,7 @@ ENTRY(__blowfish_enc_blk)
        round_enc(14);
        add_roundkey_enc(16);
 
-       movq %r11, %rbp;
+       movq %r11, %r12;
 
        movq %r10, RIO;
        test %cl, %cl;
@@ -157,12 +158,13 @@ ENDPROC(__blowfish_enc_blk)
 
 ENTRY(blowfish_dec_blk)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         */
-       movq %rbp, %r11;
+       movq %r12, %r11;
 
+       movq %rdi, CTX;
        movq %rsi, %r10;
        movq %rdx, RIO;
 
@@ -181,7 +183,7 @@ ENTRY(blowfish_dec_blk)
        movq %r10, RIO;
        write_block();
 
-       movq %r11, %rbp;
+       movq %r11, %r12;
 
        ret;
 ENDPROC(blowfish_dec_blk)
@@ -298,20 +300,21 @@ ENDPROC(blowfish_dec_blk)
 
 ENTRY(__blowfish_enc_blk_4way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         *      %rcx: bool, if true: xor output
         */
-       pushq %rbp;
+       pushq %r12;
        pushq %rbx;
        pushq %rcx;
 
-       preload_roundkey_enc(0);
-
+       movq %rdi, CTX
        movq %rsi, %r11;
        movq %rdx, RIO;
 
+       preload_roundkey_enc(0);
+
        read_block4();
 
        round_enc4(0);
@@ -324,39 +327,40 @@ ENTRY(__blowfish_enc_blk_4way)
        round_enc4(14);
        add_preloaded_roundkey4();
 
-       popq %rbp;
+       popq %r12;
        movq %r11, RIO;
 
-       test %bpl, %bpl;
+       test %r12b, %r12b;
        jnz .L__enc_xor4;
 
        write_block4();
 
        popq %rbx;
-       popq %rbp;
+       popq %r12;
        ret;
 
 .L__enc_xor4:
        xor_block4();
 
        popq %rbx;
-       popq %rbp;
+       popq %r12;
        ret;
 ENDPROC(__blowfish_enc_blk_4way)
 
 ENTRY(blowfish_dec_blk_4way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         */
-       pushq %rbp;
+       pushq %r12;
        pushq %rbx;
-       preload_roundkey_dec(17);
 
-       movq %rsi, %r11;
+       movq %rdi, CTX;
+       movq %rsi, %r11
        movq %rdx, RIO;
 
+       preload_roundkey_dec(17);
        read_block4();
 
        round_dec4(17);
@@ -373,7 +377,7 @@ ENTRY(blowfish_dec_blk_4way)
        write_block4();
 
        popq %rbx;
-       popq %rbp;
+       popq %r12;
 
        ret;
 ENDPROC(blowfish_dec_blk_4way)
index 310319c601ede2884b2d031ca4603593f304e4b3..95ba6956a7f6a1fc0b01e2938f94cee0ff6a2ac3 100644 (file)
 #define RCD1bh %dh
 
 #define RT0 %rsi
-#define RT1 %rbp
+#define RT1 %r12
 #define RT2 %r8
 
 #define RT0d %esi
-#define RT1d %ebp
+#define RT1d %r12d
 #define RT2d %r8d
 
 #define RT2bl %r8b
 
 #define RXOR %r9
-#define RRBP %r10
+#define RR12 %r10
 #define RDST %r11
 
 #define RXORd %r9d
@@ -197,7 +197,7 @@ ENTRY(__camellia_enc_blk)
         *      %rdx: src
         *      %rcx: bool xor
         */
-       movq %rbp, RRBP;
+       movq %r12, RR12;
 
        movq %rcx, RXOR;
        movq %rsi, RDST;
@@ -227,13 +227,13 @@ ENTRY(__camellia_enc_blk)
 
        enc_outunpack(mov, RT1);
 
-       movq RRBP, %rbp;
+       movq RR12, %r12;
        ret;
 
 .L__enc_xor:
        enc_outunpack(xor, RT1);
 
-       movq RRBP, %rbp;
+       movq RR12, %r12;
        ret;
 ENDPROC(__camellia_enc_blk)
 
@@ -248,7 +248,7 @@ ENTRY(camellia_dec_blk)
        movl $24, RXORd;
        cmovel RXORd, RT2d; /* max */
 
-       movq %rbp, RRBP;
+       movq %r12, RR12;
        movq %rsi, RDST;
        movq %rdx, RIO;
 
@@ -271,7 +271,7 @@ ENTRY(camellia_dec_blk)
 
        dec_outunpack();
 
-       movq RRBP, %rbp;
+       movq RR12, %r12;
        ret;
 ENDPROC(camellia_dec_blk)
 
@@ -433,7 +433,7 @@ ENTRY(__camellia_enc_blk_2way)
         */
        pushq %rbx;
 
-       movq %rbp, RRBP;
+       movq %r12, RR12;
        movq %rcx, RXOR;
        movq %rsi, RDST;
        movq %rdx, RIO;
@@ -461,14 +461,14 @@ ENTRY(__camellia_enc_blk_2way)
 
        enc_outunpack2(mov, RT2);
 
-       movq RRBP, %rbp;
+       movq RR12, %r12;
        popq %rbx;
        ret;
 
 .L__enc2_xor:
        enc_outunpack2(xor, RT2);
 
-       movq RRBP, %rbp;
+       movq RR12, %r12;
        popq %rbx;
        ret;
 ENDPROC(__camellia_enc_blk_2way)
@@ -485,7 +485,7 @@ ENTRY(camellia_dec_blk_2way)
        cmovel RXORd, RT2d; /* max */
 
        movq %rbx, RXOR;
-       movq %rbp, RRBP;
+       movq %r12, RR12;
        movq %rsi, RDST;
        movq %rdx, RIO;
 
@@ -508,7 +508,7 @@ ENTRY(camellia_dec_blk_2way)
 
        dec_outunpack2();
 
-       movq RRBP, %rbp;
+       movq RR12, %r12;
        movq RXOR, %rbx;
        ret;
 ENDPROC(camellia_dec_blk_2way)
index b4a8806234ea1c5f61f46898900a84035af72763..86107c961bb4627f08f6c7eac252589218c6c7e3 100644 (file)
@@ -47,7 +47,7 @@
 /**********************************************************************
   16-way AVX cast5
  **********************************************************************/
-#define CTX %rdi
+#define CTX %r15
 
 #define RL1 %xmm0
 #define RR1 %xmm1
@@ -70,8 +70,8 @@
 
 #define RTMP %xmm15
 
-#define RID1  %rbp
-#define RID1d %ebp
+#define RID1  %rdi
+#define RID1d %edi
 #define RID2  %rsi
 #define RID2d %esi
 
 .align 16
 __cast5_enc_blk16:
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      RL1: blocks 1 and 2
         *      RR1: blocks 3 and 4
         *      RL2: blocks 5 and 6
@@ -246,9 +246,11 @@ __cast5_enc_blk16:
         *      RR4: encrypted blocks 15 and 16
         */
 
-       pushq %rbp;
+       pushq %r15;
        pushq %rbx;
 
+       movq %rdi, CTX;
+
        vmovdqa .Lbswap_mask, RKM;
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
@@ -283,7 +285,7 @@ __cast5_enc_blk16:
 
 .L__skip_enc:
        popq %rbx;
-       popq %rbp;
+       popq %r15;
 
        vmovdqa .Lbswap_mask, RKM;
 
@@ -298,7 +300,7 @@ ENDPROC(__cast5_enc_blk16)
 .align 16
 __cast5_dec_blk16:
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      RL1: encrypted blocks 1 and 2
         *      RR1: encrypted blocks 3 and 4
         *      RL2: encrypted blocks 5 and 6
@@ -318,9 +320,11 @@ __cast5_dec_blk16:
         *      RR4: decrypted blocks 15 and 16
         */
 
-       pushq %rbp;
+       pushq %r15;
        pushq %rbx;
 
+       movq %rdi, CTX;
+
        vmovdqa .Lbswap_mask, RKM;
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
@@ -356,7 +360,7 @@ __cast5_dec_blk16:
 
        vmovdqa .Lbswap_mask, RKM;
        popq %rbx;
-       popq %rbp;
+       popq %r15;
 
        outunpack_blocks(RR1, RL1, RTMP, RX, RKM);
        outunpack_blocks(RR2, RL2, RTMP, RX, RKM);
@@ -372,12 +376,14 @@ ENDPROC(__cast5_dec_blk16)
 
 ENTRY(cast5_ecb_enc_16way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         */
        FRAME_BEGIN
+       pushq %r15;
 
+       movq %rdi, CTX;
        movq %rsi, %r11;
 
        vmovdqu (0*4*4)(%rdx), RL1;
@@ -400,18 +406,22 @@ ENTRY(cast5_ecb_enc_16way)
        vmovdqu RR4, (6*4*4)(%r11);
        vmovdqu RL4, (7*4*4)(%r11);
 
+       popq %r15;
        FRAME_END
        ret;
 ENDPROC(cast5_ecb_enc_16way)
 
 ENTRY(cast5_ecb_dec_16way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         */
 
        FRAME_BEGIN
+       pushq %r15;
+
+       movq %rdi, CTX;
        movq %rsi, %r11;
 
        vmovdqu (0*4*4)(%rdx), RL1;
@@ -434,20 +444,22 @@ ENTRY(cast5_ecb_dec_16way)
        vmovdqu RR4, (6*4*4)(%r11);
        vmovdqu RL4, (7*4*4)(%r11);
 
+       popq %r15;
        FRAME_END
        ret;
 ENDPROC(cast5_ecb_dec_16way)
 
 ENTRY(cast5_cbc_dec_16way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         */
        FRAME_BEGIN
-
        pushq %r12;
+       pushq %r15;
 
+       movq %rdi, CTX;
        movq %rsi, %r11;
        movq %rdx, %r12;
 
@@ -483,23 +495,24 @@ ENTRY(cast5_cbc_dec_16way)
        vmovdqu RR4, (6*16)(%r11);
        vmovdqu RL4, (7*16)(%r11);
 
+       popq %r15;
        popq %r12;
-
        FRAME_END
        ret;
 ENDPROC(cast5_cbc_dec_16way)
 
 ENTRY(cast5_ctr_16way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         *      %rcx: iv (big endian, 64bit)
         */
        FRAME_BEGIN
-
        pushq %r12;
+       pushq %r15;
 
+       movq %rdi, CTX;
        movq %rsi, %r11;
        movq %rdx, %r12;
 
@@ -558,8 +571,8 @@ ENTRY(cast5_ctr_16way)
        vmovdqu RR4, (6*16)(%r11);
        vmovdqu RL4, (7*16)(%r11);
 
+       popq %r15;
        popq %r12;
-
        FRAME_END
        ret;
 ENDPROC(cast5_ctr_16way)
index 952d3156a93312ff8c5a5c2c193132a89f7413da..7f30b6f0d72c15f402a69d621ecde1c283780266 100644 (file)
@@ -47,7 +47,7 @@
 /**********************************************************************
   8-way AVX cast6
  **********************************************************************/
-#define CTX %rdi
+#define CTX %r15
 
 #define RA1 %xmm0
 #define RB1 %xmm1
@@ -70,8 +70,8 @@
 
 #define RTMP %xmm15
 
-#define RID1  %rbp
-#define RID1d %ebp
+#define RID1  %rdi
+#define RID1d %edi
 #define RID2  %rsi
 #define RID2d %esi
 
 .align 8
 __cast6_enc_blk8:
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: blocks
         * output:
         *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
         */
 
-       pushq %rbp;
+       pushq %r15;
        pushq %rbx;
 
+       movq %rdi, CTX;
+
        vmovdqa .Lbswap_mask, RKM;
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
@@ -297,7 +299,7 @@ __cast6_enc_blk8:
        QBAR(11);
 
        popq %rbx;
-       popq %rbp;
+       popq %r15;
 
        vmovdqa .Lbswap_mask, RKM;
 
@@ -310,15 +312,17 @@ ENDPROC(__cast6_enc_blk8)
 .align 8
 __cast6_dec_blk8:
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: encrypted blocks
         * output:
         *      RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2: decrypted blocks
         */
 
-       pushq %rbp;
+       pushq %r15;
        pushq %rbx;
 
+       movq %rdi, CTX;
+
        vmovdqa .Lbswap_mask, RKM;
        vmovd .Lfirst_mask, R1ST;
        vmovd .L32_mask, R32;
@@ -343,7 +347,7 @@ __cast6_dec_blk8:
        QBAR(0);
 
        popq %rbx;
-       popq %rbp;
+       popq %r15;
 
        vmovdqa .Lbswap_mask, RKM;
        outunpack_blocks(RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
@@ -354,12 +358,14 @@ ENDPROC(__cast6_dec_blk8)
 
 ENTRY(cast6_ecb_enc_8way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         */
        FRAME_BEGIN
+       pushq %r15;
 
+       movq %rdi, CTX;
        movq %rsi, %r11;
 
        load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
@@ -368,18 +374,21 @@ ENTRY(cast6_ecb_enc_8way)
 
        store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+       popq %r15;
        FRAME_END
        ret;
 ENDPROC(cast6_ecb_enc_8way)
 
 ENTRY(cast6_ecb_dec_8way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         */
        FRAME_BEGIN
+       pushq %r15;
 
+       movq %rdi, CTX;
        movq %rsi, %r11;
 
        load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
@@ -388,20 +397,22 @@ ENTRY(cast6_ecb_dec_8way)
 
        store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+       popq %r15;
        FRAME_END
        ret;
 ENDPROC(cast6_ecb_dec_8way)
 
 ENTRY(cast6_cbc_dec_8way)
        /* input:
-        *      %rdi: ctx, CTX
+        *      %rdi: ctx
         *      %rsi: dst
         *      %rdx: src
         */
        FRAME_BEGIN
-
        pushq %r12;
+       pushq %r15;
 
+       movq %rdi, CTX;
        movq %rsi, %r11;
        movq %rdx, %r12;
 
@@ -411,8 +422,8 @@ ENTRY(cast6_cbc_dec_8way)
 
        store_cbc_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+       popq %r15;
        popq %r12;
-
        FRAME_END
        ret;
 ENDPROC(cast6_cbc_dec_8way)
@@ -425,9 +436,10 @@ ENTRY(cast6_ctr_8way)
         *      %rcx: iv (little endian, 128bit)
         */
        FRAME_BEGIN
-
        pushq %r12;
+       pushq %r15
 
+       movq %rdi, CTX;
        movq %rsi, %r11;
        movq %rdx, %r12;
 
@@ -438,8 +450,8 @@ ENTRY(cast6_ctr_8way)
 
        store_ctr_8way(%r12, %r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+       popq %r15;
        popq %r12;
-
        FRAME_END
        ret;
 ENDPROC(cast6_ctr_8way)
@@ -452,7 +464,9 @@ ENTRY(cast6_xts_enc_8way)
         *      %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
         */
        FRAME_BEGIN
+       pushq %r15;
 
+       movq %rdi, CTX
        movq %rsi, %r11;
 
        /* regs <= src, dst <= IVs, regs <= regs xor IVs */
@@ -464,6 +478,7 @@ ENTRY(cast6_xts_enc_8way)
        /* dst <= regs xor IVs(in dst) */
        store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+       popq %r15;
        FRAME_END
        ret;
 ENDPROC(cast6_xts_enc_8way)
@@ -476,7 +491,9 @@ ENTRY(cast6_xts_dec_8way)
         *      %rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
         */
        FRAME_BEGIN
+       pushq %r15;
 
+       movq %rdi, CTX
        movq %rsi, %r11;
 
        /* regs <= src, dst <= IVs, regs <= regs xor IVs */
@@ -488,6 +505,7 @@ ENTRY(cast6_xts_dec_8way)
        /* dst <= regs xor IVs(in dst) */
        store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+       popq %r15;
        FRAME_END
        ret;
 ENDPROC(cast6_xts_dec_8way)
index f3e91647ca274a4b20d4b18f0d7232a3c8ca4567..8e49ce1174947ea612fca65a6d143cdc2386534e 100644 (file)
 #define RW2bh %ch
 
 #define RT0 %r15
-#define RT1 %rbp
+#define RT1 %rsi
 #define RT2 %r14
 #define RT3 %rdx
 
 #define RT0d %r15d
-#define RT1d %ebp
+#define RT1d %esi
 #define RT2d %r14d
 #define RT3d %edx
 
@@ -177,13 +177,14 @@ ENTRY(des3_ede_x86_64_crypt_blk)
         *      %rsi: dst
         *      %rdx: src
         */
-       pushq %rbp;
        pushq %rbx;
        pushq %r12;
        pushq %r13;
        pushq %r14;
        pushq %r15;
 
+       pushq %rsi; /* dst */
+
        read_block(%rdx, RL0, RR0);
        initial_permutation(RL0, RR0);
 
@@ -241,6 +242,8 @@ ENTRY(des3_ede_x86_64_crypt_blk)
        round1(32+15, RL0, RR0, dummy2);
 
        final_permutation(RR0, RL0);
+
+       popq %rsi /* dst */
        write_block(%rsi, RR0, RL0);
 
        popq %r15;
@@ -248,7 +251,6 @@ ENTRY(des3_ede_x86_64_crypt_blk)
        popq %r13;
        popq %r12;
        popq %rbx;
-       popq %rbp;
 
        ret;
 ENDPROC(des3_ede_x86_64_crypt_blk)
@@ -432,13 +434,14 @@ ENTRY(des3_ede_x86_64_crypt_blk_3way)
         *      %rdx: src (3 blocks)
         */
 
-       pushq %rbp;
        pushq %rbx;
        pushq %r12;
        pushq %r13;
        pushq %r14;
        pushq %r15;
 
+       pushq %rsi /* dst */
+
        /* load input */
        movl 0 * 4(%rdx), RL0d;
        movl 1 * 4(%rdx), RR0d;
@@ -520,6 +523,7 @@ ENTRY(des3_ede_x86_64_crypt_blk_3way)
        bswapl RR2d;
        bswapl RL2d;
 
+       popq %rsi /* dst */
        movl RR0d, 0 * 4(%rsi);
        movl RL0d, 1 * 4(%rsi);
        movl RR1d, 2 * 4(%rsi);
@@ -532,7 +536,6 @@ ENTRY(des3_ede_x86_64_crypt_blk_3way)
        popq %r13;
        popq %r12;
        popq %rbx;
-       popq %rbp;
 
        ret;
 ENDPROC(des3_ede_x86_64_crypt_blk_3way)
index 1eab79c9ac484172a63d9cc0c4a409b7fffe7e8b..9f712a7dfd797cc499e1ef52ba7999078530494a 100644 (file)
@@ -89,7 +89,7 @@
 #define        REG_RE  %rdx
 #define        REG_RTA %r12
 #define        REG_RTB %rbx
-#define        REG_T1  %ebp
+#define        REG_T1  %r11d
 #define        xmm_mov vmovups
 #define        avx2_zeroupper  vzeroupper
 #define        RND_F1  1
@@ -637,7 +637,6 @@ _loop3:
        ENTRY(\name)
 
        push    %rbx
-       push    %rbp
        push    %r12
        push    %r13
        push    %r14
@@ -673,7 +672,6 @@ _loop3:
        pop     %r14
        pop     %r13
        pop     %r12
-       pop     %rbp
        pop     %rbx
 
        ret
index a4109506a5e8884ba54562aed09bc36e5e800d12..6204bd53528c65c0d4a70f05e76a60bcc476499e 100644 (file)
@@ -37,7 +37,7 @@
 #define REG_A  %ecx
 #define REG_B  %esi
 #define REG_C  %edi
-#define REG_D  %ebp
+#define REG_D  %r12d
 #define REG_E  %edx
 
 #define REG_T1 %eax
        ENTRY(\name)
 
        push    %rbx
-       push    %rbp
        push    %r12
+       push    %rbp
+       mov     %rsp, %rbp
 
-       mov     %rsp, %r12
        sub     $64, %rsp               # allocate workspace
        and     $~15, %rsp              # align stack
 
        xor     %rax, %rax
        rep stosq
 
-       mov     %r12, %rsp              # deallocate workspace
-
-       pop     %r12
+       mov     %rbp, %rsp              # deallocate workspace
        pop     %rbp
+       pop     %r12
        pop     %rbx
        ret
 
index e08888a1a5f2cf5f8a6809d86d497664cece52a1..001bbcf93c79ba08628abcf30dd49ad77158420d 100644 (file)
@@ -103,7 +103,7 @@ SRND = %rsi       # clobbers INP
 c = %ecx
 d = %r8d
 e = %edx
-TBL = %rbp
+TBL = %r12
 a = %eax
 b = %ebx
 
@@ -350,13 +350,13 @@ a = TMP_
 ENTRY(sha256_transform_avx)
 .align 32
        pushq   %rbx
-       pushq   %rbp
+       pushq   %r12
        pushq   %r13
        pushq   %r14
        pushq   %r15
-       pushq   %r12
+       pushq   %rbp
+       movq    %rsp, %rbp
 
-       mov     %rsp, %r12
        subq    $STACK_SIZE, %rsp       # allocate stack space
        and     $~15, %rsp              # align stack pointer
 
@@ -452,13 +452,12 @@ loop2:
 
 done_hash:
 
-       mov     %r12, %rsp
-
-       popq    %r12
+       mov     %rbp, %rsp
+       popq    %rbp
        popq    %r15
        popq    %r14
        popq    %r13
-       popq    %rbp
+       popq    %r12
        popq    %rbx
        ret
 ENDPROC(sha256_transform_avx)
index 89c8f09787d20552c12230ded345282bb2f2bf42..1420db15dcddc8505b57faad5e6e6701f972b517 100644 (file)
@@ -98,8 +98,6 @@ d     = %r8d
 e       = %edx # clobbers NUM_BLKS
 y3     = %esi  # clobbers INP
 
-
-TBL    = %rbp
 SRND   = CTX   # SRND is same register as CTX
 
 a = %eax
@@ -531,7 +529,6 @@ STACK_SIZE  = _RSP      + _RSP_SIZE
 ENTRY(sha256_transform_rorx)
 .align 32
        pushq   %rbx
-       pushq   %rbp
        pushq   %r12
        pushq   %r13
        pushq   %r14
@@ -568,8 +565,6 @@ ENTRY(sha256_transform_rorx)
        mov     CTX, _CTX(%rsp)
 
 loop0:
-       lea     K256(%rip), TBL
-
        ## Load first 16 dwords from two blocks
        VMOVDQ  0*32(INP),XTMP0
        VMOVDQ  1*32(INP),XTMP1
@@ -597,19 +592,19 @@ last_block_enter:
 
 .align 16
 loop1:
-       vpaddd  0*32(TBL, SRND), X0, XFER
+       vpaddd  K256+0*32(SRND), X0, XFER
        vmovdqa XFER, 0*32+_XFER(%rsp, SRND)
        FOUR_ROUNDS_AND_SCHED   _XFER + 0*32
 
-       vpaddd  1*32(TBL, SRND), X0, XFER
+       vpaddd  K256+1*32(SRND), X0, XFER
        vmovdqa XFER, 1*32+_XFER(%rsp, SRND)
        FOUR_ROUNDS_AND_SCHED   _XFER + 1*32
 
-       vpaddd  2*32(TBL, SRND), X0, XFER
+       vpaddd  K256+2*32(SRND), X0, XFER
        vmovdqa XFER, 2*32+_XFER(%rsp, SRND)
        FOUR_ROUNDS_AND_SCHED   _XFER + 2*32
 
-       vpaddd  3*32(TBL, SRND), X0, XFER
+       vpaddd  K256+3*32(SRND), X0, XFER
        vmovdqa XFER, 3*32+_XFER(%rsp, SRND)
        FOUR_ROUNDS_AND_SCHED   _XFER + 3*32
 
@@ -619,10 +614,11 @@ loop1:
 
 loop2:
        ## Do last 16 rounds with no scheduling
-       vpaddd  0*32(TBL, SRND), X0, XFER
+       vpaddd  K256+0*32(SRND), X0, XFER
        vmovdqa XFER, 0*32+_XFER(%rsp, SRND)
        DO_4ROUNDS      _XFER + 0*32
-       vpaddd  1*32(TBL, SRND), X1, XFER
+
+       vpaddd  K256+1*32(SRND), X1, XFER
        vmovdqa XFER, 1*32+_XFER(%rsp, SRND)
        DO_4ROUNDS      _XFER + 1*32
        add     $2*32, SRND
@@ -676,9 +672,6 @@ loop3:
        ja      done_hash
 
 do_last_block:
-       #### do last block
-       lea     K256(%rip), TBL
-
        VMOVDQ  0*16(INP),XWORD0
        VMOVDQ  1*16(INP),XWORD1
        VMOVDQ  2*16(INP),XWORD2
@@ -718,7 +711,6 @@ done_hash:
        popq    %r14
        popq    %r13
        popq    %r12
-       popq    %rbp
        popq    %rbx
        ret
 ENDPROC(sha256_transform_rorx)
index 39b83c93e7fd6cdbc658a35ef4698756cccef612..c6c05ed2c16a593390ddf7617070f45e58a40ad4 100644 (file)
@@ -95,7 +95,7 @@ SRND = %rsi       # clobbers INP
 c = %ecx
 d = %r8d
 e = %edx
-TBL = %rbp
+TBL = %r12
 a = %eax
 b = %ebx
 
@@ -356,13 +356,13 @@ a = TMP_
 ENTRY(sha256_transform_ssse3)
 .align 32
        pushq   %rbx
-       pushq   %rbp
+       pushq   %r12
        pushq   %r13
        pushq   %r14
        pushq   %r15
-       pushq   %r12
+       pushq   %rbp
+       mov     %rsp, %rbp
 
-       mov     %rsp, %r12
        subq    $STACK_SIZE, %rsp
        and     $~15, %rsp
 
@@ -462,13 +462,12 @@ loop2:
 
 done_hash:
 
-       mov     %r12, %rsp
-
-       popq    %r12
+       mov     %rbp, %rsp
+       popq    %rbp
        popq    %r15
        popq    %r14
        popq    %r13
-       popq    %rbp
+       popq    %r12
        popq    %rbx
 
        ret
index 7f5f6c6ec72e9cb0a47c2b5babbbedff487fbbf3..b16d560051629a1c6d518321b93be2672b861c9e 100644 (file)
@@ -69,8 +69,9 @@ XFER  = YTMP0
 
 BYTE_FLIP_MASK  = %ymm9
 
-# 1st arg
-CTX         = %rdi
+# 1st arg is %rdi, which is saved to the stack and accessed later via %r12
+CTX1        = %rdi
+CTX2        = %r12
 # 2nd arg
 INP         = %rsi
 # 3rd arg
@@ -81,7 +82,7 @@ d           = %r8
 e           = %rdx
 y3          = %rsi
 
-TBL   = %rbp
+TBL   = %rdi # clobbers CTX1
 
 a     = %rax
 b     = %rbx
@@ -91,26 +92,26 @@ g     = %r10
 h     = %r11
 old_h = %r11
 
-T1    = %r12
+T1    = %r12 # clobbers CTX2
 y0    = %r13
 y1    = %r14
 y2    = %r15
 
-y4    = %r12
-
 # Local variables (stack frame)
 XFER_SIZE = 4*8
 SRND_SIZE = 1*8
 INP_SIZE = 1*8
 INPEND_SIZE = 1*8
+CTX_SIZE = 1*8
 RSPSAVE_SIZE = 1*8
-GPRSAVE_SIZE = 6*8
+GPRSAVE_SIZE = 5*8
 
 frame_XFER = 0
 frame_SRND = frame_XFER + XFER_SIZE
 frame_INP = frame_SRND + SRND_SIZE
 frame_INPEND = frame_INP + INP_SIZE
-frame_RSPSAVE = frame_INPEND + INPEND_SIZE
+frame_CTX = frame_INPEND + INPEND_SIZE
+frame_RSPSAVE = frame_CTX + CTX_SIZE
 frame_GPRSAVE = frame_RSPSAVE + RSPSAVE_SIZE
 frame_size = frame_GPRSAVE + GPRSAVE_SIZE
 
@@ -576,12 +577,11 @@ ENTRY(sha512_transform_rorx)
        mov     %rax, frame_RSPSAVE(%rsp)
 
        # Save GPRs
-       mov     %rbp, frame_GPRSAVE(%rsp)
-       mov     %rbx, 8*1+frame_GPRSAVE(%rsp)
-       mov     %r12, 8*2+frame_GPRSAVE(%rsp)
-       mov     %r13, 8*3+frame_GPRSAVE(%rsp)
-       mov     %r14, 8*4+frame_GPRSAVE(%rsp)
-       mov     %r15, 8*5+frame_GPRSAVE(%rsp)
+       mov     %rbx, 8*0+frame_GPRSAVE(%rsp)
+       mov     %r12, 8*1+frame_GPRSAVE(%rsp)
+       mov     %r13, 8*2+frame_GPRSAVE(%rsp)
+       mov     %r14, 8*3+frame_GPRSAVE(%rsp)
+       mov     %r15, 8*4+frame_GPRSAVE(%rsp)
 
        shl     $7, NUM_BLKS    # convert to bytes
        jz      done_hash
@@ -589,14 +589,17 @@ ENTRY(sha512_transform_rorx)
        mov     NUM_BLKS, frame_INPEND(%rsp)
 
        ## load initial digest
-       mov     8*0(CTX),a
-       mov     8*1(CTX),b
-       mov     8*2(CTX),c
-       mov     8*3(CTX),d
-       mov     8*4(CTX),e
-       mov     8*5(CTX),f
-       mov     8*6(CTX),g
-       mov     8*7(CTX),h
+       mov     8*0(CTX1), a
+       mov     8*1(CTX1), b
+       mov     8*2(CTX1), c
+       mov     8*3(CTX1), d
+       mov     8*4(CTX1), e
+       mov     8*5(CTX1), f
+       mov     8*6(CTX1), g
+       mov     8*7(CTX1), h
+
+       # save %rdi (CTX) before it gets clobbered
+       mov     %rdi, frame_CTX(%rsp)
 
        vmovdqa PSHUFFLE_BYTE_FLIP_MASK(%rip), BYTE_FLIP_MASK
 
@@ -652,14 +655,15 @@ loop2:
        subq    $1, frame_SRND(%rsp)
        jne     loop2
 
-       addm    8*0(CTX),a
-       addm    8*1(CTX),b
-       addm    8*2(CTX),c
-       addm    8*3(CTX),d
-       addm    8*4(CTX),e
-       addm    8*5(CTX),f
-       addm    8*6(CTX),g
-       addm    8*7(CTX),h
+       mov     frame_CTX(%rsp), CTX2
+       addm    8*0(CTX2), a
+       addm    8*1(CTX2), b
+       addm    8*2(CTX2), c
+       addm    8*3(CTX2), d
+       addm    8*4(CTX2), e
+       addm    8*5(CTX2), f
+       addm    8*6(CTX2), g
+       addm    8*7(CTX2), h
 
        mov     frame_INP(%rsp), INP
        add     $128, INP
@@ -669,12 +673,11 @@ loop2:
 done_hash:
 
 # Restore GPRs
-       mov     frame_GPRSAVE(%rsp)     ,%rbp
-       mov     8*1+frame_GPRSAVE(%rsp) ,%rbx
-       mov     8*2+frame_GPRSAVE(%rsp) ,%r12
-       mov     8*3+frame_GPRSAVE(%rsp) ,%r13
-       mov     8*4+frame_GPRSAVE(%rsp) ,%r14
-       mov     8*5+frame_GPRSAVE(%rsp) ,%r15
+       mov     8*0+frame_GPRSAVE(%rsp), %rbx
+       mov     8*1+frame_GPRSAVE(%rsp), %r12
+       mov     8*2+frame_GPRSAVE(%rsp), %r13
+       mov     8*3+frame_GPRSAVE(%rsp), %r14
+       mov     8*4+frame_GPRSAVE(%rsp), %r15
 
        # Restore Stack Pointer
        mov     frame_RSPSAVE(%rsp), %rsp
index b3f49d2863480334e8b2d12828e4ca20045b8be9..73b471da36226386112a23c0036b7f5da14b3266 100644 (file)
@@ -76,8 +76,8 @@
 #define RT %xmm14
 #define RR %xmm15
 
-#define RID1  %rbp
-#define RID1d %ebp
+#define RID1  %r13
+#define RID1d %r13d
 #define RID2  %rsi
 #define RID2d %esi
 
@@ -259,7 +259,7 @@ __twofish_enc_blk8:
 
        vmovdqu w(CTX), RK1;
 
-       pushq %rbp;
+       pushq %r13;
        pushq %rbx;
        pushq %rcx;
 
@@ -282,7 +282,7 @@ __twofish_enc_blk8:
 
        popq %rcx;
        popq %rbx;
-       popq %rbp;
+       popq %r13;
 
        outunpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
        outunpack_blocks(RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
@@ -301,7 +301,7 @@ __twofish_dec_blk8:
 
        vmovdqu (w+4*4)(CTX), RK1;
 
-       pushq %rbp;
+       pushq %r13;
        pushq %rbx;
 
        inpack_blocks(RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
@@ -322,7 +322,7 @@ __twofish_dec_blk8:
        vmovdqu (w)(CTX), RK1;
 
        popq %rbx;
-       popq %rbp;
+       popq %r13;
 
        outunpack_blocks(RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
        outunpack_blocks(RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
index 4cf100ff2a3746f440049dd5c27c254e4dcc1776..72db0664a53dfd6fe64512ebda83caaa97db1abd 100644 (file)
@@ -552,6 +552,7 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
 
        X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_MOBILE,  snb_cstates),
        X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_DESKTOP, snb_cstates),
+       X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_X, snb_cstates),
 
        X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE_MOBILE,  snb_cstates),
        X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE_DESKTOP, snb_cstates),
@@ -560,6 +561,9 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
        X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNM, knl_cstates),
 
        X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT, glm_cstates),
+       X86_CSTATES_MODEL(INTEL_FAM6_ATOM_DENVERTON, glm_cstates),
+
+       X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GEMINI_LAKE, glm_cstates),
        { },
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
index 8e2457cb6b4a416e1c84d9baa990ea512ec74ba0..005908ee9333f0e87cdd4db7ca14a278d52fa773 100644 (file)
@@ -775,6 +775,9 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE_DESKTOP, skl_rapl_init),
 
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT, hsw_rapl_init),
+       X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_DENVERTON, hsw_rapl_init),
+
+       X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GEMINI_LAKE, hsw_rapl_init),
        {},
 };
 
index db1fe377e6dd9ddfcfbc006a7346879f263d408a..a7196818416a57381b513254628206a9660ed578 100644 (file)
@@ -3462,7 +3462,7 @@ static struct intel_uncore_ops skx_uncore_iio_ops = {
 static struct intel_uncore_type skx_uncore_iio = {
        .name                   = "iio",
        .num_counters           = 4,
-       .num_boxes              = 5,
+       .num_boxes              = 6,
        .perf_ctr_bits          = 48,
        .event_ctl              = SKX_IIO0_MSR_PMON_CTL0,
        .perf_ctr               = SKX_IIO0_MSR_PMON_CTR0,
@@ -3492,7 +3492,7 @@ static const struct attribute_group skx_uncore_format_group = {
 static struct intel_uncore_type skx_uncore_irp = {
        .name                   = "irp",
        .num_counters           = 2,
-       .num_boxes              = 5,
+       .num_boxes              = 6,
        .perf_ctr_bits          = 48,
        .event_ctl              = SKX_IRP0_MSR_PMON_CTL0,
        .perf_ctr               = SKX_IRP0_MSR_PMON_CTR0,
index 4bb3ec69e8ea10537c25ef2d792be94f1d7a4127..06723671ae4e91d53b7327b44fe96b588826d838 100644 (file)
@@ -63,6 +63,14 @@ static bool test_intel(int idx)
        case INTEL_FAM6_ATOM_SILVERMONT1:
        case INTEL_FAM6_ATOM_SILVERMONT2:
        case INTEL_FAM6_ATOM_AIRMONT:
+
+       case INTEL_FAM6_ATOM_GOLDMONT:
+       case INTEL_FAM6_ATOM_DENVERTON:
+
+       case INTEL_FAM6_ATOM_GEMINI_LAKE:
+
+       case INTEL_FAM6_XEON_PHI_KNL:
+       case INTEL_FAM6_XEON_PHI_KNM:
                if (idx == PERF_MSR_SMI)
                        return true;
                break;
index e0bb46c0285752e73c8eb55420e29f97d88a818e..0e2a5edbce00111f6a41f1b3070610b5316d1e71 100644 (file)
@@ -231,7 +231,7 @@ static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
                 ksig->ka.sa.sa_restorer)
                sp = (unsigned long) ksig->ka.sa.sa_restorer;
 
-       if (fpu->fpstate_active) {
+       if (fpu->initialized) {
                unsigned long fx_aligned, math_size;
 
                sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size);
index 1b020381ab38965ae2a80d2d86df32c66c92e2e8..c096624137ae831fa4d0f9cebf528453598fdefb 100644 (file)
@@ -218,10 +218,9 @@ static inline int alternatives_text_reserved(void *start, void *end)
 #define alternative_call_2(oldfunc, newfunc1, feature1, newfunc2, feature2,   \
                           output, input...)                                  \
 {                                                                            \
-       register void *__sp asm(_ASM_SP);                                     \
        asm volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", feature1,\
                "call %P[new2]", feature2)                                    \
-               : output, "+r" (__sp)                                         \
+               : output, ASM_CALL_CONSTRAINT                                 \
                : [old] "i" (oldfunc), [new1] "i" (newfunc1),                 \
                  [new2] "i" (newfunc2), ## input);                           \
 }
index 676ee5807d864d94538bf16d2ed7535655045128..b0dc91f4bedc680ac69d7ecc481a71c863bade77 100644 (file)
 # define __ASM_FORM_COMMA(x) " " #x ","
 #endif
 
-#ifdef CONFIG_X86_32
+#ifndef __x86_64__
+/* 32 bit */
 # define __ASM_SEL(a,b) __ASM_FORM(a)
 # define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(a)
 #else
+/* 64 bit */
 # define __ASM_SEL(a,b) __ASM_FORM(b)
 # define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
 #endif
 /* For C file, we already have NOKPROBE_SYMBOL macro */
 #endif
 
+#ifndef __ASSEMBLY__
+/*
+ * This output constraint should be used for any inline asm which has a "call"
+ * instruction.  Otherwise the asm may be inserted before the frame pointer
+ * gets set up by the containing function.  If you forget to do this, objtool
+ * may print a "call without frame pointer save/setup" warning.
+ */
+register unsigned long current_stack_pointer asm(_ASM_SP);
+#define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer)
+#endif
+
 #endif /* _ASM_X86_ASM_H */
index 554cdb205d17586887e6b599c991b2fc090ba38a..e3221ffa304e301858db746a03d6cf8600790004 100644 (file)
 /*
  * High level FPU state handling functions:
  */
-extern void fpu__activate_curr(struct fpu *fpu);
-extern void fpu__activate_fpstate_read(struct fpu *fpu);
-extern void fpu__activate_fpstate_write(struct fpu *fpu);
-extern void fpu__current_fpstate_write_begin(void);
-extern void fpu__current_fpstate_write_end(void);
+extern void fpu__initialize(struct fpu *fpu);
+extern void fpu__prepare_read(struct fpu *fpu);
+extern void fpu__prepare_write(struct fpu *fpu);
 extern void fpu__save(struct fpu *fpu);
 extern void fpu__restore(struct fpu *fpu);
 extern int  fpu__restore_sig(void __user *buf, int ia32_frame);
@@ -120,20 +118,11 @@ extern void fpstate_sanitize_xstate(struct fpu *fpu);
        err;                                                            \
 })
 
-#define check_insn(insn, output, input...)                             \
-({                                                                     \
-       int err;                                                        \
+#define kernel_insn(insn, output, input...)                            \
        asm volatile("1:" #insn "\n\t"                                  \
                     "2:\n"                                             \
-                    ".section .fixup,\"ax\"\n"                         \
-                    "3:  movl $-1,%[err]\n"                            \
-                    "    jmp  2b\n"                                    \
-                    ".previous\n"                                      \
-                    _ASM_EXTABLE(1b, 3b)                               \
-                    : [err] "=r" (err), output                         \
-                    : "0"(0), input);                                  \
-       err;                                                            \
-})
+                    _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_fprestore)  \
+                    : output : input)
 
 static inline int copy_fregs_to_user(struct fregs_state __user *fx)
 {
@@ -153,20 +142,16 @@ static inline int copy_fxregs_to_user(struct fxregs_state __user *fx)
 
 static inline void copy_kernel_to_fxregs(struct fxregs_state *fx)
 {
-       int err;
-
        if (IS_ENABLED(CONFIG_X86_32)) {
-               err = check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
+               kernel_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
        } else {
                if (IS_ENABLED(CONFIG_AS_FXSAVEQ)) {
-                       err = check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
+                       kernel_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
                } else {
                        /* See comment in copy_fxregs_to_kernel() below. */
-                       err = check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), "m" (*fx));
+                       kernel_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), "m" (*fx));
                }
        }
-       /* Copying from a kernel buffer to FPU registers should never fail: */
-       WARN_ON_FPU(err);
 }
 
 static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
@@ -183,9 +168,7 @@ static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
 
 static inline void copy_kernel_to_fregs(struct fregs_state *fx)
 {
-       int err = check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
-
-       WARN_ON_FPU(err);
+       kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
 }
 
 static inline int copy_user_to_fregs(struct fregs_state __user *fx)
@@ -281,18 +264,13 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu)
  * Use XRSTORS to restore context if it is enabled. XRSTORS supports compact
  * XSAVE area format.
  */
-#define XSTATE_XRESTORE(st, lmask, hmask, err)                         \
+#define XSTATE_XRESTORE(st, lmask, hmask)                              \
        asm volatile(ALTERNATIVE(XRSTOR,                                \
                                 XRSTORS, X86_FEATURE_XSAVES)           \
                     "\n"                                               \
-                    "xor %[err], %[err]\n"                             \
                     "3:\n"                                             \
-                    ".pushsection .fixup,\"ax\"\n"                     \
-                    "4: movl $-2, %[err]\n"                            \
-                    "jmp 3b\n"                                         \
-                    ".popsection\n"                                    \
-                    _ASM_EXTABLE(661b, 4b)                             \
-                    : [err] "=r" (err)                                 \
+                    _ASM_EXTABLE_HANDLE(661b, 3b, ex_handler_fprestore)\
+                    :                                                  \
                     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)    \
                     : "memory")
 
@@ -336,7 +314,10 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)
        else
                XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
 
-       /* We should never fault when copying from a kernel buffer: */
+       /*
+        * We should never fault when copying from a kernel buffer, and the FPU
+        * state we set at boot time should be valid.
+        */
        WARN_ON_FPU(err);
 }
 
@@ -350,7 +331,7 @@ static inline void copy_xregs_to_kernel(struct xregs_state *xstate)
        u32 hmask = mask >> 32;
        int err;
 
-       WARN_ON(!alternatives_patched);
+       WARN_ON_FPU(!alternatives_patched);
 
        XSTATE_XSAVE(xstate, lmask, hmask, err);
 
@@ -365,12 +346,8 @@ static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask)
 {
        u32 lmask = mask;
        u32 hmask = mask >> 32;
-       int err;
-
-       XSTATE_XRESTORE(xstate, lmask, hmask, err);
 
-       /* We should never fault when copying from a kernel buffer: */
-       WARN_ON_FPU(err);
+       XSTATE_XRESTORE(xstate, lmask, hmask);
 }
 
 /*
@@ -526,37 +503,16 @@ static inline int fpregs_state_valid(struct fpu *fpu, unsigned int cpu)
  */
 static inline void fpregs_deactivate(struct fpu *fpu)
 {
-       WARN_ON_FPU(!fpu->fpregs_active);
-
-       fpu->fpregs_active = 0;
        this_cpu_write(fpu_fpregs_owner_ctx, NULL);
        trace_x86_fpu_regs_deactivated(fpu);
 }
 
 static inline void fpregs_activate(struct fpu *fpu)
 {
-       WARN_ON_FPU(fpu->fpregs_active);
-
-       fpu->fpregs_active = 1;
        this_cpu_write(fpu_fpregs_owner_ctx, fpu);
        trace_x86_fpu_regs_activated(fpu);
 }
 
-/*
- * The question "does this thread have fpu access?"
- * is slightly racy, since preemption could come in
- * and revoke it immediately after the test.
- *
- * However, even in that very unlikely scenario,
- * we can just assume we have FPU access - typically
- * to save the FP state - we'll just take a #NM
- * fault and get the FPU access back.
- */
-static inline int fpregs_active(void)
-{
-       return current->thread.fpu.fpregs_active;
-}
-
 /*
  * FPU state switching for scheduling.
  *
@@ -571,14 +527,13 @@ static inline int fpregs_active(void)
 static inline void
 switch_fpu_prepare(struct fpu *old_fpu, int cpu)
 {
-       if (old_fpu->fpregs_active) {
+       if (old_fpu->initialized) {
                if (!copy_fpregs_to_fpstate(old_fpu))
                        old_fpu->last_cpu = -1;
                else
                        old_fpu->last_cpu = cpu;
 
                /* But leave fpu_fpregs_owner_ctx! */
-               old_fpu->fpregs_active = 0;
                trace_x86_fpu_regs_deactivated(old_fpu);
        } else
                old_fpu->last_cpu = -1;
@@ -595,7 +550,7 @@ switch_fpu_prepare(struct fpu *old_fpu, int cpu)
 static inline void switch_fpu_finish(struct fpu *new_fpu, int cpu)
 {
        bool preload = static_cpu_has(X86_FEATURE_FPU) &&
-                      new_fpu->fpstate_active;
+                      new_fpu->initialized;
 
        if (preload) {
                if (!fpregs_state_valid(new_fpu, cpu))
@@ -617,8 +572,7 @@ static inline void user_fpu_begin(void)
        struct fpu *fpu = &current->thread.fpu;
 
        preempt_disable();
-       if (!fpregs_active())
-               fpregs_activate(fpu);
+       fpregs_activate(fpu);
        preempt_enable();
 }
 
index 3c80f5b9c09d8cf5407378a39ba27cfa380bafbf..a1520575d86b81fd2521d7e4013856b7e70d4db2 100644 (file)
@@ -68,6 +68,9 @@ struct fxregs_state {
 /* Default value for fxregs_state.mxcsr: */
 #define MXCSR_DEFAULT          0x1f80
 
+/* Copy both mxcsr & mxcsr_flags with a single u64 memcpy: */
+#define MXCSR_AND_FLAGS_SIZE sizeof(u64)
+
 /*
  * Software based FPU emulation state. This is arbitrary really,
  * it matches the x87 format to make it easier to understand:
@@ -290,36 +293,13 @@ struct fpu {
        unsigned int                    last_cpu;
 
        /*
-        * @fpstate_active:
+        * @initialized:
         *
-        * This flag indicates whether this context is active: if the task
+        * This flag indicates whether this context is initialized: if the task
         * is not running then we can restore from this context, if the task
         * is running then we should save into this context.
         */
-       unsigned char                   fpstate_active;
-
-       /*
-        * @fpregs_active:
-        *
-        * This flag determines whether a given context is actively
-        * loaded into the FPU's registers and that those registers
-        * represent the task's current FPU state.
-        *
-        * Note the interaction with fpstate_active:
-        *
-        *   # task does not use the FPU:
-        *   fpstate_active == 0
-        *
-        *   # task uses the FPU and regs are active:
-        *   fpstate_active == 1 && fpregs_active == 1
-        *
-        *   # the regs are inactive but still match fpstate:
-        *   fpstate_active == 1 && fpregs_active == 0 && fpregs_owner == fpu
-        *
-        * The third state is what we use for the lazy restore optimization
-        * on lazy-switching CPUs.
-        */
-       unsigned char                   fpregs_active;
+       unsigned char                   initialized;
 
        /*
         * @state:
index 1b2799e0699a4d47a3ef191f6177f0a4abc13ceb..83fee2469eb76079771c668545db95e929d1446c 100644 (file)
@@ -48,8 +48,12 @@ void fpu__xstate_clear_all_cpu_caps(void);
 void *get_xsave_addr(struct xregs_state *xsave, int xstate);
 const void *get_xsave_field_ptr(int xstate_field);
 int using_compacted_format(void);
-int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,
-                       void __user *ubuf, struct xregs_state *xsave);
-int copyin_to_xsaves(const void *kbuf, const void __user *ubuf,
-                    struct xregs_state *xsave);
+int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
+int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset, unsigned int size);
+int copy_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf);
+int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf);
+
+/* Validate an xstate header supplied by userspace (ptrace or sigreturn) */
+extern int validate_xstate_header(const struct xstate_header *hdr);
+
 #endif
index 7ae318c340d9b5d0fca2697dbb7e977b0bda3892..c120b5db178aa415e1bbb97957dd7d73687575d3 100644 (file)
@@ -286,6 +286,32 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
        return __pkru_allows_pkey(vma_pkey(vma), write);
 }
 
+/*
+ * If PCID is on, ASID-aware code paths put the ASID+1 into the PCID
+ * bits.  This serves two purposes.  It prevents a nasty situation in
+ * which PCID-unaware code saves CR3, loads some other value (with PCID
+ * == 0), and then restores CR3, thus corrupting the TLB for ASID 0 if
+ * the saved ASID was nonzero.  It also means that any bugs involving
+ * loading a PCID-enabled CR3 with CR4.PCIDE off will trigger
+ * deterministically.
+ */
+
+static inline unsigned long build_cr3(struct mm_struct *mm, u16 asid)
+{
+       if (static_cpu_has(X86_FEATURE_PCID)) {
+               VM_WARN_ON_ONCE(asid > 4094);
+               return __sme_pa(mm->pgd) | (asid + 1);
+       } else {
+               VM_WARN_ON_ONCE(asid != 0);
+               return __sme_pa(mm->pgd);
+       }
+}
+
+static inline unsigned long build_cr3_noflush(struct mm_struct *mm, u16 asid)
+{
+       VM_WARN_ON_ONCE(asid > 4094);
+       return __sme_pa(mm->pgd) | (asid + 1) | CR3_NOFLUSH;
+}
 
 /*
  * This can be used from process context to figure out what the value of
@@ -296,10 +322,8 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
  */
 static inline unsigned long __get_current_cr3_fast(void)
 {
-       unsigned long cr3 = __pa(this_cpu_read(cpu_tlbstate.loaded_mm)->pgd);
-
-       if (static_cpu_has(X86_FEATURE_PCID))
-               cr3 |= this_cpu_read(cpu_tlbstate.loaded_mm_asid);
+       unsigned long cr3 = build_cr3(this_cpu_read(cpu_tlbstate.loaded_mm),
+               this_cpu_read(cpu_tlbstate.loaded_mm_asid));
 
        /* For now, be very restrictive about when this can be called. */
        VM_WARN_ON(in_nmi() || preemptible());
index 63cc96f064dc4987813352eb8ceba869d3738856..738503e1f80c14f1b5720275dd57161509927ef8 100644 (file)
@@ -179,7 +179,6 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
        u64 input_address = input ? virt_to_phys(input) : 0;
        u64 output_address = output ? virt_to_phys(output) : 0;
        u64 hv_status;
-       register void *__sp asm(_ASM_SP);
 
 #ifdef CONFIG_X86_64
        if (!hv_hypercall_pg)
@@ -187,7 +186,7 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
 
        __asm__ __volatile__("mov %4, %%r8\n"
                             "call *%5"
-                            : "=a" (hv_status), "+r" (__sp),
+                            : "=a" (hv_status), ASM_CALL_CONSTRAINT,
                               "+c" (control), "+d" (input_address)
                             :  "r" (output_address), "m" (hv_hypercall_pg)
                             : "cc", "memory", "r8", "r9", "r10", "r11");
@@ -202,7 +201,7 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
 
        __asm__ __volatile__("call *%7"
                             : "=A" (hv_status),
-                              "+c" (input_address_lo), "+r" (__sp)
+                              "+c" (input_address_lo), ASM_CALL_CONSTRAINT
                             : "A" (control),
                               "b" (input_address_hi),
                               "D"(output_address_hi), "S"(output_address_lo),
@@ -224,12 +223,11 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
 static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
 {
        u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT;
-       register void *__sp asm(_ASM_SP);
 
 #ifdef CONFIG_X86_64
        {
                __asm__ __volatile__("call *%4"
-                                    : "=a" (hv_status), "+r" (__sp),
+                                    : "=a" (hv_status), ASM_CALL_CONSTRAINT,
                                       "+c" (control), "+d" (input1)
                                     : "m" (hv_hypercall_pg)
                                     : "cc", "r8", "r9", "r10", "r11");
@@ -242,7 +240,7 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
                __asm__ __volatile__ ("call *%5"
                                      : "=A"(hv_status),
                                        "+c"(input1_lo),
-                                       "+r"(__sp)
+                                       ASM_CALL_CONSTRAINT
                                      : "A" (control),
                                        "b" (input1_hi),
                                        "m" (hv_hypercall_pg)
index 42873edd9f9d20cda2d1cfcb92b3798c4a75b3aa..280d94c36dada184fce42cd03d5d05fe7ebc8698 100644 (file)
@@ -459,8 +459,8 @@ int paravirt_disable_iospace(void);
  */
 #ifdef CONFIG_X86_32
 #define PVOP_VCALL_ARGS                                                        \
-       unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx;      \
-       register void *__sp asm("esp")
+       unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx;
+
 #define PVOP_CALL_ARGS                 PVOP_VCALL_ARGS
 
 #define PVOP_CALL_ARG1(x)              "a" ((unsigned long)(x))
@@ -480,8 +480,8 @@ int paravirt_disable_iospace(void);
 /* [re]ax isn't an arg, but the return val */
 #define PVOP_VCALL_ARGS                                                \
        unsigned long __edi = __edi, __esi = __esi,             \
-               __edx = __edx, __ecx = __ecx, __eax = __eax;    \
-       register void *__sp asm("rsp")
+               __edx = __edx, __ecx = __ecx, __eax = __eax;
+
 #define PVOP_CALL_ARGS         PVOP_VCALL_ARGS
 
 #define PVOP_CALL_ARG1(x)              "D" ((unsigned long)(x))
@@ -532,7 +532,7 @@ int paravirt_disable_iospace(void);
                        asm volatile(pre                                \
                                     paravirt_alt(PARAVIRT_CALL)        \
                                     post                               \
-                                    : call_clbr, "+r" (__sp)           \
+                                    : call_clbr, ASM_CALL_CONSTRAINT   \
                                     : paravirt_type(op),               \
                                       paravirt_clobber(clbr),          \
                                       ##__VA_ARGS__                    \
@@ -542,7 +542,7 @@ int paravirt_disable_iospace(void);
                        asm volatile(pre                                \
                                     paravirt_alt(PARAVIRT_CALL)        \
                                     post                               \
-                                    : call_clbr, "+r" (__sp)           \
+                                    : call_clbr, ASM_CALL_CONSTRAINT   \
                                     : paravirt_type(op),               \
                                       paravirt_clobber(clbr),          \
                                       ##__VA_ARGS__                    \
@@ -569,7 +569,7 @@ int paravirt_disable_iospace(void);
                asm volatile(pre                                        \
                             paravirt_alt(PARAVIRT_CALL)                \
                             post                                       \
-                            : call_clbr, "+r" (__sp)                   \
+                            : call_clbr, ASM_CALL_CONSTRAINT           \
                             : paravirt_type(op),                       \
                               paravirt_clobber(clbr),                  \
                               ##__VA_ARGS__                            \
index ec1f3c6511506ee1f0ff5240a9ff95d0e6fa68c1..4f44505dbf870e79d4689af9db2f537fe764b831 100644 (file)
@@ -100,19 +100,14 @@ static __always_inline bool should_resched(int preempt_offset)
 
 #ifdef CONFIG_PREEMPT
   extern asmlinkage void ___preempt_schedule(void);
-# define __preempt_schedule()                                  \
-({                                                             \
-       register void *__sp asm(_ASM_SP);                       \
-       asm volatile ("call ___preempt_schedule" : "+r"(__sp)); \
-})
+# define __preempt_schedule() \
+       asm volatile ("call ___preempt_schedule" : ASM_CALL_CONSTRAINT)
 
   extern asmlinkage void preempt_schedule(void);
   extern asmlinkage void ___preempt_schedule_notrace(void);
-# define __preempt_schedule_notrace()                                  \
-({                                                                     \
-       register void *__sp asm(_ASM_SP);                               \
-       asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp)); \
-})
+# define __preempt_schedule_notrace() \
+       asm volatile ("call ___preempt_schedule_notrace" : ASM_CALL_CONSTRAINT)
+
   extern asmlinkage void preempt_schedule_notrace(void);
 #endif
 
index 3fa26a61eabcef0dc95b19221ca5e76a6ba2a01a..b390ff76e58fd9f28c62ba5e3a8ab169ac18ad62 100644 (file)
@@ -677,8 +677,6 @@ static inline void sync_core(void)
         * Like all of Linux's memory ordering operations, this is a
         * compiler barrier as well.
         */
-       register void *__sp asm(_ASM_SP);
-
 #ifdef CONFIG_X86_32
        asm volatile (
                "pushfl\n\t"
@@ -686,7 +684,7 @@ static inline void sync_core(void)
                "pushl $1f\n\t"
                "iret\n\t"
                "1:"
-               : "+r" (__sp) : : "memory");
+               : ASM_CALL_CONSTRAINT : : "memory");
 #else
        unsigned int tmp;
 
@@ -703,7 +701,7 @@ static inline void sync_core(void)
                "iretq\n\t"
                UNWIND_HINT_RESTORE
                "1:"
-               : "=&r" (tmp), "+r" (__sp) : : "cc", "memory");
+               : "=&r" (tmp), ASM_CALL_CONSTRAINT : : "cc", "memory");
 #endif
 }
 
index a34e0d4b957d639afb5978863e57fefb74a173f2..7116b7931c7b807766fef6d820ec929da43940c7 100644 (file)
@@ -103,7 +103,6 @@ static inline bool __down_read_trylock(struct rw_semaphore *sem)
 ({                                                     \
        long tmp;                                       \
        struct rw_semaphore* ret;                       \
-       register void *__sp asm(_ASM_SP);               \
                                                        \
        asm volatile("# beginning down_write\n\t"       \
                     LOCK_PREFIX "  xadd      %1,(%4)\n\t"      \
@@ -114,7 +113,8 @@ static inline bool __down_read_trylock(struct rw_semaphore *sem)
                     "  call " slow_path "\n"           \
                     "1:\n"                             \
                     "# ending down_write"              \
-                    : "+m" (sem->count), "=d" (tmp), "=a" (ret), "+r" (__sp) \
+                    : "+m" (sem->count), "=d" (tmp),   \
+                      "=a" (ret), ASM_CALL_CONSTRAINT  \
                     : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \
                     : "memory", "cc");                 \
        ret;                                            \
index 5161da1a0fa0a522c80b93f758a84914a88fad46..89e7eeb5cec1dfa6804d5bba2dfe010e6ad8f455 100644 (file)
@@ -158,17 +158,6 @@ struct thread_info {
  */
 #ifndef __ASSEMBLY__
 
-static inline unsigned long current_stack_pointer(void)
-{
-       unsigned long sp;
-#ifdef CONFIG_X86_64
-       asm("mov %%rsp,%0" : "=g" (sp));
-#else
-       asm("mov %%esp,%0" : "=g" (sp));
-#endif
-       return sp;
-}
-
 /*
  * Walks up the stack frames to make sure that the specified object is
  * entirely contained by a single stack frame.
index 342e59789fcdc2e62ce1fd94df32f99f12359bd0..39f7a27bef130fbb6c83a881951e440091ed9168 100644 (file)
@@ -12,25 +12,22 @@ DECLARE_EVENT_CLASS(x86_fpu,
 
        TP_STRUCT__entry(
                __field(struct fpu *, fpu)
-               __field(bool, fpregs_active)
-               __field(bool, fpstate_active)
+               __field(bool, initialized)
                __field(u64, xfeatures)
                __field(u64, xcomp_bv)
                ),
 
        TP_fast_assign(
                __entry->fpu            = fpu;
-               __entry->fpregs_active  = fpu->fpregs_active;
-               __entry->fpstate_active = fpu->fpstate_active;
+               __entry->initialized    = fpu->initialized;
                if (boot_cpu_has(X86_FEATURE_OSXSAVE)) {
                        __entry->xfeatures = fpu->state.xsave.header.xfeatures;
                        __entry->xcomp_bv  = fpu->state.xsave.header.xcomp_bv;
                }
        ),
-       TP_printk("x86/fpu: %p fpregs_active: %d fpstate_active: %d xfeatures: %llx xcomp_bv: %llx",
+       TP_printk("x86/fpu: %p initialized: %d xfeatures: %llx xcomp_bv: %llx",
                        __entry->fpu,
-                       __entry->fpregs_active,
-                       __entry->fpstate_active,
+                       __entry->initialized,
                        __entry->xfeatures,
                        __entry->xcomp_bv
        )
index 184eb9894dae3f2cca10bfe1813a348614830305..4b892917edeb787ce6380fd78a0d1c82f2299982 100644 (file)
@@ -166,11 +166,11 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
 ({                                                                     \
        int __ret_gu;                                                   \
        register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);            \
-       register void *__sp asm(_ASM_SP);                               \
        __chk_user_ptr(ptr);                                            \
        might_fault();                                                  \
        asm volatile("call __get_user_%P4"                              \
-                    : "=a" (__ret_gu), "=r" (__val_gu), "+r" (__sp)    \
+                    : "=a" (__ret_gu), "=r" (__val_gu),                \
+                       ASM_CALL_CONSTRAINT                             \
                     : "0" (ptr), "i" (sizeof(*(ptr))));                \
        (x) = (__force __typeof__(*(ptr))) __val_gu;                    \
        __builtin_expect(__ret_gu, 0);                                  \
@@ -337,7 +337,7 @@ do {                                                                        \
                     _ASM_EXTABLE(1b, 4b)                               \
                     _ASM_EXTABLE(2b, 4b)                               \
                     : "=r" (retval), "=&A"(x)                          \
-                    : "m" (__m(__ptr)), "m" __m(((u32 *)(__ptr)) + 1), \
+                    : "m" (__m(__ptr)), "m" __m(((u32 __user *)(__ptr)) + 1),  \
                       "i" (errret), "0" (retval));                     \
 })
 
index 9606688caa4bea8db0175fe71fe61d9706108aba..7cb282e9e58777aeb2ffd86b344d39a5189c5f84 100644 (file)
@@ -113,10 +113,9 @@ extern struct { char _entry[32]; } hypercall_page[];
        register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
        register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
        register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
-       register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; \
-       register void *__sp asm(_ASM_SP);
+       register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
 
-#define __HYPERCALL_0PARAM     "=r" (__res), "+r" (__sp)
+#define __HYPERCALL_0PARAM     "=r" (__res), ASM_CALL_CONSTRAINT
 #define __HYPERCALL_1PARAM     __HYPERCALL_0PARAM, "+r" (__arg1)
 #define __HYPERCALL_2PARAM     __HYPERCALL_1PARAM, "+r" (__arg2)
 #define __HYPERCALL_3PARAM     __HYPERCALL_2PARAM, "+r" (__arg3)
@@ -552,13 +551,13 @@ static inline void
 MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
                        struct desc_struct desc)
 {
-       u32 *p = (u32 *) &desc;
-
        mcl->op = __HYPERVISOR_update_descriptor;
        if (sizeof(maddr) == sizeof(long)) {
                mcl->args[0] = maddr;
                mcl->args[1] = *(unsigned long *)&desc;
        } else {
+               u32 *p = (u32 *)&desc;
+
                mcl->args[0] = maddr;
                mcl->args[1] = maddr >> 32;
                mcl->args[2] = *p++;
index 9862e2cd6d93da331052f664f49fd4ce1edb8d6b..d58184b7cd4438144e2d0ac3f4744d19ff4ffb31 100644 (file)
@@ -763,6 +763,16 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
        }
 }
 
+static void init_amd_zn(struct cpuinfo_x86 *c)
+{
+       /*
+        * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects
+        * all up to and including B1.
+        */
+       if (c->x86_model <= 1 && c->x86_mask <= 1)
+               set_cpu_cap(c, X86_FEATURE_CPB);
+}
+
 static void init_amd(struct cpuinfo_x86 *c)
 {
        early_init_amd(c);
@@ -791,6 +801,7 @@ static void init_amd(struct cpuinfo_x86 *c)
        case 0x10: init_amd_gh(c); break;
        case 0x12: init_amd_ln(c); break;
        case 0x15: init_amd_bd(c); break;
+       case 0x17: init_amd_zn(c); break;
        }
 
        /* Enable workaround for FXSAVE leak */
index db684880d74ae47fbff37888ff31dd13b9a4653b..0af86d9242da0f6882f1f5252dfa659038c627ac 100644 (file)
 
 void __init check_bugs(void)
 {
-#ifdef CONFIG_X86_32
-       /*
-        * Regardless of whether PCID is enumerated, the SDM says
-        * that it can't be enabled in 32-bit mode.
-        */
-       setup_clear_cpu_cap(X86_FEATURE_PCID);
-#endif
-
        identify_boot_cpu();
 
        if (!IS_ENABLED(CONFIG_SMP)) {
index 775f10100d7febac27a84bb9c8deab24e119a8c8..c9176bae7fd8cdb0e85f6d60766a809b9b36aa42 100644 (file)
@@ -904,6 +904,14 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
 
        setup_force_cpu_cap(X86_FEATURE_ALWAYS);
        fpu__init_system(c);
+
+#ifdef CONFIG_X86_32
+       /*
+        * Regardless of whether PCID is enumerated, the SDM says
+        * that it can't be enabled in 32-bit mode.
+        */
+       setup_clear_cpu_cap(X86_FEATURE_PCID);
+#endif
 }
 
 void __init early_cpu_init(void)
index e1114f070c2dfdedf9911cd587afb7cca1769785..f92a6593de1ec651d244d43d16acbd8d49959e4b 100644 (file)
@@ -100,7 +100,7 @@ void __kernel_fpu_begin(void)
 
        kernel_fpu_disable();
 
-       if (fpu->fpregs_active) {
+       if (fpu->initialized) {
                /*
                 * Ignore return value -- we don't care if reg state
                 * is clobbered.
@@ -116,7 +116,7 @@ void __kernel_fpu_end(void)
 {
        struct fpu *fpu = &current->thread.fpu;
 
-       if (fpu->fpregs_active)
+       if (fpu->initialized)
                copy_kernel_to_fpregs(&fpu->state);
 
        kernel_fpu_enable();
@@ -148,7 +148,7 @@ void fpu__save(struct fpu *fpu)
 
        preempt_disable();
        trace_x86_fpu_before_save(fpu);
-       if (fpu->fpregs_active) {
+       if (fpu->initialized) {
                if (!copy_fpregs_to_fpstate(fpu)) {
                        copy_kernel_to_fpregs(&fpu->state);
                }
@@ -189,10 +189,9 @@ EXPORT_SYMBOL_GPL(fpstate_init);
 
 int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
 {
-       dst_fpu->fpregs_active = 0;
        dst_fpu->last_cpu = -1;
 
-       if (!src_fpu->fpstate_active || !static_cpu_has(X86_FEATURE_FPU))
+       if (!src_fpu->initialized || !static_cpu_has(X86_FEATURE_FPU))
                return 0;
 
        WARN_ON_FPU(src_fpu != &current->thread.fpu);
@@ -206,26 +205,14 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
        /*
         * Save current FPU registers directly into the child
         * FPU context, without any memory-to-memory copying.
-        * In lazy mode, if the FPU context isn't loaded into
-        * fpregs, CR0.TS will be set and do_device_not_available
-        * will load the FPU context.
         *
-        * We have to do all this with preemption disabled,
-        * mostly because of the FNSAVE case, because in that
-        * case we must not allow preemption in the window
-        * between the FNSAVE and us marking the context lazy.
-        *
-        * It shouldn't be an issue as even FNSAVE is plenty
-        * fast in terms of critical section length.
+        * ( The function 'fails' in the FNSAVE case, which destroys
+        *   register contents so we have to copy them back. )
         */
-       preempt_disable();
        if (!copy_fpregs_to_fpstate(dst_fpu)) {
-               memcpy(&src_fpu->state, &dst_fpu->state,
-                      fpu_kernel_xstate_size);
-
+               memcpy(&src_fpu->state, &dst_fpu->state, fpu_kernel_xstate_size);
                copy_kernel_to_fpregs(&src_fpu->state);
        }
-       preempt_enable();
 
        trace_x86_fpu_copy_src(src_fpu);
        trace_x86_fpu_copy_dst(dst_fpu);
@@ -237,45 +224,48 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
  * Activate the current task's in-memory FPU context,
  * if it has not been used before:
  */
-void fpu__activate_curr(struct fpu *fpu)
+void fpu__initialize(struct fpu *fpu)
 {
        WARN_ON_FPU(fpu != &current->thread.fpu);
 
-       if (!fpu->fpstate_active) {
+       if (!fpu->initialized) {
                fpstate_init(&fpu->state);
                trace_x86_fpu_init_state(fpu);
 
                trace_x86_fpu_activate_state(fpu);
                /* Safe to do for the current task: */
-               fpu->fpstate_active = 1;
+               fpu->initialized = 1;
        }
 }
-EXPORT_SYMBOL_GPL(fpu__activate_curr);
+EXPORT_SYMBOL_GPL(fpu__initialize);
 
 /*
  * This function must be called before we read a task's fpstate.
  *
- * If the task has not used the FPU before then initialize its
- * fpstate.
+ * There's two cases where this gets called:
+ *
+ * - for the current task (when coredumping), in which case we have
+ *   to save the latest FPU registers into the fpstate,
+ *
+ * - or it's called for stopped tasks (ptrace), in which case the
+ *   registers were already saved by the context-switch code when
+ *   the task scheduled out - we only have to initialize the registers
+ *   if they've never been initialized.
  *
  * If the task has used the FPU before then save it.
  */
-void fpu__activate_fpstate_read(struct fpu *fpu)
+void fpu__prepare_read(struct fpu *fpu)
 {
-       /*
-        * If fpregs are active (in the current CPU), then
-        * copy them to the fpstate:
-        */
-       if (fpu->fpregs_active) {
+       if (fpu == &current->thread.fpu) {
                fpu__save(fpu);
        } else {
-               if (!fpu->fpstate_active) {
+               if (!fpu->initialized) {
                        fpstate_init(&fpu->state);
                        trace_x86_fpu_init_state(fpu);
 
                        trace_x86_fpu_activate_state(fpu);
                        /* Safe to do for current and for stopped child tasks: */
-                       fpu->fpstate_active = 1;
+                       fpu->initialized = 1;
                }
        }
 }
@@ -283,17 +273,17 @@ void fpu__activate_fpstate_read(struct fpu *fpu)
 /*
  * This function must be called before we write a task's fpstate.
  *
- * If the task has used the FPU before then unlazy it.
+ * If the task has used the FPU before then invalidate any cached FPU registers.
  * If the task has not used the FPU before then initialize its fpstate.
  *
  * After this function call, after registers in the fpstate are
  * modified and the child task has woken up, the child task will
  * restore the modified FPU state from the modified context. If we
- * didn't clear its lazy status here then the lazy in-registers
+ * didn't clear its cached status here then the cached in-registers
  * state pending on its former CPU could be restored, corrupting
  * the modifications.
  */
-void fpu__activate_fpstate_write(struct fpu *fpu)
+void fpu__prepare_write(struct fpu *fpu)
 {
        /*
         * Only stopped child tasks can be used to modify the FPU
@@ -301,8 +291,8 @@ void fpu__activate_fpstate_write(struct fpu *fpu)
         */
        WARN_ON_FPU(fpu == &current->thread.fpu);
 
-       if (fpu->fpstate_active) {
-               /* Invalidate any lazy state: */
+       if (fpu->initialized) {
+               /* Invalidate any cached state: */
                __fpu_invalidate_fpregs_state(fpu);
        } else {
                fpstate_init(&fpu->state);
@@ -310,73 +300,10 @@ void fpu__activate_fpstate_write(struct fpu *fpu)
 
                trace_x86_fpu_activate_state(fpu);
                /* Safe to do for stopped child tasks: */
-               fpu->fpstate_active = 1;
+               fpu->initialized = 1;
        }
 }
 
-/*
- * This function must be called before we write the current
- * task's fpstate.
- *
- * This call gets the current FPU register state and moves
- * it in to the 'fpstate'.  Preemption is disabled so that
- * no writes to the 'fpstate' can occur from context
- * swiches.
- *
- * Must be followed by a fpu__current_fpstate_write_end().
- */
-void fpu__current_fpstate_write_begin(void)
-{
-       struct fpu *fpu = &current->thread.fpu;
-
-       /*
-        * Ensure that the context-switching code does not write
-        * over the fpstate while we are doing our update.
-        */
-       preempt_disable();
-
-       /*
-        * Move the fpregs in to the fpu's 'fpstate'.
-        */
-       fpu__activate_fpstate_read(fpu);
-
-       /*
-        * The caller is about to write to 'fpu'.  Ensure that no
-        * CPU thinks that its fpregs match the fpstate.  This
-        * ensures we will not be lazy and skip a XRSTOR in the
-        * future.
-        */
-       __fpu_invalidate_fpregs_state(fpu);
-}
-
-/*
- * This function must be paired with fpu__current_fpstate_write_begin()
- *
- * This will ensure that the modified fpstate gets placed back in
- * the fpregs if necessary.
- *
- * Note: This function may be called whether or not an _actual_
- * write to the fpstate occurred.
- */
-void fpu__current_fpstate_write_end(void)
-{
-       struct fpu *fpu = &current->thread.fpu;
-
-       /*
-        * 'fpu' now has an updated copy of the state, but the
-        * registers may still be out of date.  Update them with
-        * an XRSTOR if they are active.
-        */
-       if (fpregs_active())
-               copy_kernel_to_fpregs(&fpu->state);
-
-       /*
-        * Our update is done and the fpregs/fpstate are in sync
-        * if necessary.  Context switches can happen again.
-        */
-       preempt_enable();
-}
-
 /*
  * 'fpu__restore()' is called to copy FPU registers from
  * the FPU fpstate to the live hw registers and to activate
@@ -389,7 +316,7 @@ void fpu__current_fpstate_write_end(void)
  */
 void fpu__restore(struct fpu *fpu)
 {
-       fpu__activate_curr(fpu);
+       fpu__initialize(fpu);
 
        /* Avoid __kernel_fpu_begin() right after fpregs_activate() */
        kernel_fpu_disable();
@@ -414,15 +341,17 @@ void fpu__drop(struct fpu *fpu)
 {
        preempt_disable();
 
-       if (fpu->fpregs_active) {
-               /* Ignore delayed exceptions from user space */
-               asm volatile("1: fwait\n"
-                            "2:\n"
-                            _ASM_EXTABLE(1b, 2b));
-               fpregs_deactivate(fpu);
+       if (fpu == &current->thread.fpu) {
+               if (fpu->initialized) {
+                       /* Ignore delayed exceptions from user space */
+                       asm volatile("1: fwait\n"
+                                    "2:\n"
+                                    _ASM_EXTABLE(1b, 2b));
+                       fpregs_deactivate(fpu);
+               }
        }
 
-       fpu->fpstate_active = 0;
+       fpu->initialized = 0;
 
        trace_x86_fpu_dropped(fpu);
 
@@ -462,9 +391,11 @@ void fpu__clear(struct fpu *fpu)
         * Make sure fpstate is cleared and initialized.
         */
        if (static_cpu_has(X86_FEATURE_FPU)) {
-               fpu__activate_curr(fpu);
+               preempt_disable();
+               fpu__initialize(fpu);
                user_fpu_begin();
                copy_init_fpstate_to_fpregs();
+               preempt_enable();
        }
 }
 
index d5d44c452624c88e3abb5c75e68d00b55fee6019..7affb7e3d9a5b94326b51528119787f4f956640b 100644 (file)
@@ -240,7 +240,7 @@ static void __init fpu__init_system_ctx_switch(void)
        WARN_ON_FPU(!on_boot_cpu);
        on_boot_cpu = 0;
 
-       WARN_ON_FPU(current->thread.fpu.fpstate_active);
+       WARN_ON_FPU(current->thread.fpu.initialized);
 }
 
 /*
index b188b16841e376574c5f39e55b7b687ffdd09495..3ea15137238964cc6f972b2d11c83cb619de55bd 100644 (file)
@@ -16,14 +16,14 @@ int regset_fpregs_active(struct task_struct *target, const struct user_regset *r
 {
        struct fpu *target_fpu = &target->thread.fpu;
 
-       return target_fpu->fpstate_active ? regset->n : 0;
+       return target_fpu->initialized ? regset->n : 0;
 }
 
 int regset_xregset_fpregs_active(struct task_struct *target, const struct user_regset *regset)
 {
        struct fpu *target_fpu = &target->thread.fpu;
 
-       if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->fpstate_active)
+       if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->initialized)
                return regset->n;
        else
                return 0;
@@ -38,7 +38,7 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
        if (!boot_cpu_has(X86_FEATURE_FXSR))
                return -ENODEV;
 
-       fpu__activate_fpstate_read(fpu);
+       fpu__prepare_read(fpu);
        fpstate_sanitize_xstate(fpu);
 
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
@@ -55,7 +55,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
        if (!boot_cpu_has(X86_FEATURE_FXSR))
                return -ENODEV;
 
-       fpu__activate_fpstate_write(fpu);
+       fpu__prepare_write(fpu);
        fpstate_sanitize_xstate(fpu);
 
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
@@ -89,10 +89,13 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset,
 
        xsave = &fpu->state.xsave;
 
-       fpu__activate_fpstate_read(fpu);
+       fpu__prepare_read(fpu);
 
        if (using_compacted_format()) {
-               ret = copyout_from_xsaves(pos, count, kbuf, ubuf, xsave);
+               if (kbuf)
+                       ret = copy_xstate_to_kernel(kbuf, xsave, pos, count);
+               else
+                       ret = copy_xstate_to_user(ubuf, xsave, pos, count);
        } else {
                fpstate_sanitize_xstate(fpu);
                /*
@@ -129,28 +132,29 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
 
        xsave = &fpu->state.xsave;
 
-       fpu__activate_fpstate_write(fpu);
+       fpu__prepare_write(fpu);
 
-       if (boot_cpu_has(X86_FEATURE_XSAVES))
-               ret = copyin_to_xsaves(kbuf, ubuf, xsave);
-       else
+       if (using_compacted_format()) {
+               if (kbuf)
+                       ret = copy_kernel_to_xstate(xsave, kbuf);
+               else
+                       ret = copy_user_to_xstate(xsave, ubuf);
+       } else {
                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1);
-
-       /*
-        * In case of failure, mark all states as init:
-        */
-       if (ret)
-               fpstate_init(&fpu->state);
+               if (!ret)
+                       ret = validate_xstate_header(&xsave->header);
+       }
 
        /*
         * mxcsr reserved bits must be masked to zero for security reasons.
         */
        xsave->i387.mxcsr &= mxcsr_feature_mask;
-       xsave->header.xfeatures &= xfeatures_mask;
+
        /*
-        * These bits must be zero.
+        * In case of failure, mark all states as init:
         */
-       memset(&xsave->header.reserved, 0, 48);
+       if (ret)
+               fpstate_init(&fpu->state);
 
        return ret;
 }
@@ -299,7 +303,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
        struct fpu *fpu = &target->thread.fpu;
        struct user_i387_ia32_struct env;
 
-       fpu__activate_fpstate_read(fpu);
+       fpu__prepare_read(fpu);
 
        if (!boot_cpu_has(X86_FEATURE_FPU))
                return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);
@@ -329,7 +333,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
        struct user_i387_ia32_struct env;
        int ret;
 
-       fpu__activate_fpstate_write(fpu);
+       fpu__prepare_write(fpu);
        fpstate_sanitize_xstate(fpu);
 
        if (!boot_cpu_has(X86_FEATURE_FPU))
@@ -369,7 +373,7 @@ int dump_fpu(struct pt_regs *regs, struct user_i387_struct *ufpu)
        struct fpu *fpu = &tsk->thread.fpu;
        int fpvalid;
 
-       fpvalid = fpu->fpstate_active;
+       fpvalid = fpu->initialized;
        if (fpvalid)
                fpvalid = !fpregs_get(tsk, NULL,
                                      0, sizeof(struct user_i387_ia32_struct),
index 83c23c230b4c4fc78664ba08663a04c684c2105b..fb639e70048f58dfaef5576ab73e6998fa8ebbd1 100644 (file)
@@ -155,7 +155,8 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)
  */
 int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
 {
-       struct xregs_state *xsave = &current->thread.fpu.state.xsave;
+       struct fpu *fpu = &current->thread.fpu;
+       struct xregs_state *xsave = &fpu->state.xsave;
        struct task_struct *tsk = current;
        int ia32_fxstate = (buf != buf_fx);
 
@@ -170,13 +171,13 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
                        sizeof(struct user_i387_ia32_struct), NULL,
                        (struct _fpstate_32 __user *) buf) ? -1 : 1;
 
-       if (fpregs_active() || using_compacted_format()) {
+       if (fpu->initialized || using_compacted_format()) {
                /* Save the live register state to the user directly. */
                if (copy_fpregs_to_sigframe(buf_fx))
                        return -1;
                /* Update the thread's fxstate to save the fsave header. */
                if (ia32_fxstate)
-                       copy_fxregs_to_kernel(&tsk->thread.fpu);
+                       copy_fxregs_to_kernel(fpu);
        } else {
                /*
                 * It is a *bug* if kernel uses compacted-format for xsave
@@ -189,7 +190,7 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
                        return -1;
                }
 
-               fpstate_sanitize_xstate(&tsk->thread.fpu);
+               fpstate_sanitize_xstate(fpu);
                if (__copy_to_user(buf_fx, xsave, fpu_user_xstate_size))
                        return -1;
        }
@@ -213,8 +214,11 @@ sanitize_restored_xstate(struct task_struct *tsk,
        struct xstate_header *header = &xsave->header;
 
        if (use_xsave()) {
-               /* These bits must be zero. */
-               memset(header->reserved, 0, 48);
+               /*
+                * Note: we don't need to zero the reserved bits in the
+                * xstate_header here because we either didn't copy them at all,
+                * or we checked earlier that they aren't set.
+                */
 
                /*
                 * Init the state that is not present in the memory
@@ -223,7 +227,7 @@ sanitize_restored_xstate(struct task_struct *tsk,
                if (fx_only)
                        header->xfeatures = XFEATURE_MASK_FPSSE;
                else
-                       header->xfeatures &= (xfeatures_mask & xfeatures);
+                       header->xfeatures &= xfeatures;
        }
 
        if (use_fxsr()) {
@@ -279,7 +283,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
        if (!access_ok(VERIFY_READ, buf, size))
                return -EACCES;
 
-       fpu__activate_curr(fpu);
+       fpu__initialize(fpu);
 
        if (!static_cpu_has(X86_FEATURE_FPU))
                return fpregs_soft_set(current, NULL,
@@ -307,28 +311,29 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
                /*
                 * For 32-bit frames with fxstate, copy the user state to the
                 * thread's fpu state, reconstruct fxstate from the fsave
-                * header. Sanitize the copied state etc.
+                * header. Validate and sanitize the copied state.
                 */
                struct fpu *fpu = &tsk->thread.fpu;
                struct user_i387_ia32_struct env;
                int err = 0;
 
                /*
-                * Drop the current fpu which clears fpu->fpstate_active. This ensures
+                * Drop the current fpu which clears fpu->initialized. This ensures
                 * that any context-switch during the copy of the new state,
                 * avoids the intermediate state from getting restored/saved.
                 * Thus avoiding the new restored state from getting corrupted.
                 * We will be ready to restore/save the state only after
-                * fpu->fpstate_active is again set.
+                * fpu->initialized is again set.
                 */
                fpu__drop(fpu);
 
                if (using_compacted_format()) {
-                       err = copyin_to_xsaves(NULL, buf_fx,
-                                              &fpu->state.xsave);
+                       err = copy_user_to_xstate(&fpu->state.xsave, buf_fx);
                } else {
-                       err = __copy_from_user(&fpu->state.xsave,
-                                              buf_fx, state_size);
+                       err = __copy_from_user(&fpu->state.xsave, buf_fx, state_size);
+
+                       if (!err && state_size > offsetof(struct xregs_state, header))
+                               err = validate_xstate_header(&fpu->state.xsave.header);
                }
 
                if (err || __copy_from_user(&env, buf, sizeof(env))) {
@@ -339,7 +344,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
                        sanitize_restored_xstate(tsk, &env, xfeatures, fx_only);
                }
 
-               fpu->fpstate_active = 1;
+               fpu->initialized = 1;
                preempt_disable();
                fpu__restore(fpu);
                preempt_enable();
index c24ac1efb12d7a1574450a1359699309148afcd6..f1d5476c902209eebeae83d3cd30fe5b6226921c 100644 (file)
@@ -483,6 +483,30 @@ int using_compacted_format(void)
        return boot_cpu_has(X86_FEATURE_XSAVES);
 }
 
+/* Validate an xstate header supplied by userspace (ptrace or sigreturn) */
+int validate_xstate_header(const struct xstate_header *hdr)
+{
+       /* No unknown or supervisor features may be set */
+       if (hdr->xfeatures & (~xfeatures_mask | XFEATURE_MASK_SUPERVISOR))
+               return -EINVAL;
+
+       /* Userspace must use the uncompacted format */
+       if (hdr->xcomp_bv)
+               return -EINVAL;
+
+       /*
+        * If 'reserved' is shrunken to add a new field, make sure to validate
+        * that new field here!
+        */
+       BUILD_BUG_ON(sizeof(hdr->reserved) != 48);
+
+       /* No reserved bits may be set */
+       if (memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
+               return -EINVAL;
+
+       return 0;
+}
+
 static void __xstate_dump_leaves(void)
 {
        int i;
@@ -867,7 +891,7 @@ const void *get_xsave_field_ptr(int xsave_state)
 {
        struct fpu *fpu = &current->thread.fpu;
 
-       if (!fpu->fpstate_active)
+       if (!fpu->initialized)
                return NULL;
        /*
         * fpu__save() takes the CPU's xstate registers
@@ -920,39 +944,130 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
 }
 #endif /* ! CONFIG_ARCH_HAS_PKEYS */
 
+/*
+ * Weird legacy quirk: SSE and YMM states store information in the
+ * MXCSR and MXCSR_FLAGS fields of the FP area. That means if the FP
+ * area is marked as unused in the xfeatures header, we need to copy
+ * MXCSR and MXCSR_FLAGS if either SSE or YMM are in use.
+ */
+static inline bool xfeatures_mxcsr_quirk(u64 xfeatures)
+{
+       if (!(xfeatures & (XFEATURE_MASK_SSE|XFEATURE_MASK_YMM)))
+               return false;
+
+       if (xfeatures & XFEATURE_MASK_FP)
+               return false;
+
+       return true;
+}
+
 /*
  * This is similar to user_regset_copyout(), but will not add offset to
  * the source data pointer or increment pos, count, kbuf, and ubuf.
  */
-static inline int xstate_copyout(unsigned int pos, unsigned int count,
-                                void *kbuf, void __user *ubuf,
-                                const void *data, const int start_pos,
-                                const int end_pos)
+static inline void
+__copy_xstate_to_kernel(void *kbuf, const void *data,
+                       unsigned int offset, unsigned int size, unsigned int size_total)
 {
-       if ((count == 0) || (pos < start_pos))
-               return 0;
+       if (offset < size_total) {
+               unsigned int copy = min(size, size_total - offset);
 
-       if (end_pos < 0 || pos < end_pos) {
-               unsigned int copy = (end_pos < 0 ? count : min(count, end_pos - pos));
+               memcpy(kbuf + offset, data, copy);
+       }
+}
 
-               if (kbuf) {
-                       memcpy(kbuf + pos, data, copy);
-               } else {
-                       if (__copy_to_user(ubuf + pos, data, copy))
-                               return -EFAULT;
+/*
+ * Convert from kernel XSAVES compacted format to standard format and copy
+ * to a kernel-space ptrace buffer.
+ *
+ * It supports partial copy but pos always starts from zero. This is called
+ * from xstateregs_get() and there we check the CPU has XSAVES.
+ */
+int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total)
+{
+       unsigned int offset, size;
+       struct xstate_header header;
+       int i;
+
+       /*
+        * Currently copy_regset_to_user() starts from pos 0:
+        */
+       if (unlikely(offset_start != 0))
+               return -EFAULT;
+
+       /*
+        * The destination is a ptrace buffer; we put in only user xstates:
+        */
+       memset(&header, 0, sizeof(header));
+       header.xfeatures = xsave->header.xfeatures;
+       header.xfeatures &= ~XFEATURE_MASK_SUPERVISOR;
+
+       /*
+        * Copy xregs_state->header:
+        */
+       offset = offsetof(struct xregs_state, header);
+       size = sizeof(header);
+
+       __copy_xstate_to_kernel(kbuf, &header, offset, size, size_total);
+
+       for (i = 0; i < XFEATURE_MAX; i++) {
+               /*
+                * Copy only in-use xstates:
+                */
+               if ((header.xfeatures >> i) & 1) {
+                       void *src = __raw_xsave_addr(xsave, 1 << i);
+
+                       offset = xstate_offsets[i];
+                       size = xstate_sizes[i];
+
+                       /* The next component has to fit fully into the output buffer: */
+                       if (offset + size > size_total)
+                               break;
+
+                       __copy_xstate_to_kernel(kbuf, src, offset, size, size_total);
                }
+
+       }
+
+       if (xfeatures_mxcsr_quirk(header.xfeatures)) {
+               offset = offsetof(struct fxregs_state, mxcsr);
+               size = MXCSR_AND_FLAGS_SIZE;
+               __copy_xstate_to_kernel(kbuf, &xsave->i387.mxcsr, offset, size, size_total);
+       }
+
+       /*
+        * Fill xsave->i387.sw_reserved value for ptrace frame:
+        */
+       offset = offsetof(struct fxregs_state, sw_reserved);
+       size = sizeof(xstate_fx_sw_bytes);
+
+       __copy_xstate_to_kernel(kbuf, xstate_fx_sw_bytes, offset, size, size_total);
+
+       return 0;
+}
+
+static inline int
+__copy_xstate_to_user(void __user *ubuf, const void *data, unsigned int offset, unsigned int size, unsigned int size_total)
+{
+       if (!size)
+               return 0;
+
+       if (offset < size_total) {
+               unsigned int copy = min(size, size_total - offset);
+
+               if (__copy_to_user(ubuf + offset, data, copy))
+                       return -EFAULT;
        }
        return 0;
 }
 
 /*
  * Convert from kernel XSAVES compacted format to standard format and copy
- * to a ptrace buffer. It supports partial copy but pos always starts from
+ * to a user-space buffer. It supports partial copy but pos always starts from
  * zero. This is called from xstateregs_get() and there we check the CPU
  * has XSAVES.
  */
-int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,
-                       void __user *ubuf, struct xregs_state *xsave)
+int copy_xstate_to_user(void __user *ubuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total)
 {
        unsigned int offset, size;
        int ret, i;
@@ -961,7 +1076,7 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,
        /*
         * Currently copy_regset_to_user() starts from pos 0:
         */
-       if (unlikely(pos != 0))
+       if (unlikely(offset_start != 0))
                return -EFAULT;
 
        /*
@@ -977,8 +1092,7 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,
        offset = offsetof(struct xregs_state, header);
        size = sizeof(header);
 
-       ret = xstate_copyout(offset, size, kbuf, ubuf, &header, 0, count);
-
+       ret = __copy_xstate_to_user(ubuf, &header, offset, size, size_total);
        if (ret)
                return ret;
 
@@ -992,25 +1106,30 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,
                        offset = xstate_offsets[i];
                        size = xstate_sizes[i];
 
-                       ret = xstate_copyout(offset, size, kbuf, ubuf, src, 0, count);
+                       /* The next component has to fit fully into the output buffer: */
+                       if (offset + size > size_total)
+                               break;
 
+                       ret = __copy_xstate_to_user(ubuf, src, offset, size, size_total);
                        if (ret)
                                return ret;
-
-                       if (offset + size >= count)
-                               break;
                }
 
        }
 
+       if (xfeatures_mxcsr_quirk(header.xfeatures)) {
+               offset = offsetof(struct fxregs_state, mxcsr);
+               size = MXCSR_AND_FLAGS_SIZE;
+               __copy_xstate_to_user(ubuf, &xsave->i387.mxcsr, offset, size, size_total);
+       }
+
        /*
         * Fill xsave->i387.sw_reserved value for ptrace frame:
         */
        offset = offsetof(struct fxregs_state, sw_reserved);
        size = sizeof(xstate_fx_sw_bytes);
 
-       ret = xstate_copyout(offset, size, kbuf, ubuf, xstate_fx_sw_bytes, 0, count);
-
+       ret = __copy_xstate_to_user(ubuf, xstate_fx_sw_bytes, offset, size, size_total);
        if (ret)
                return ret;
 
@@ -1018,55 +1137,98 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,
 }
 
 /*
- * Convert from a ptrace standard-format buffer to kernel XSAVES format
- * and copy to the target thread. This is called from xstateregs_set() and
- * there we check the CPU has XSAVES and a whole standard-sized buffer
- * exists.
+ * Convert from a ptrace standard-format kernel buffer to kernel XSAVES format
+ * and copy to the target thread. This is called from xstateregs_set().
  */
-int copyin_to_xsaves(const void *kbuf, const void __user *ubuf,
-                    struct xregs_state *xsave)
+int copy_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf)
 {
        unsigned int offset, size;
        int i;
-       u64 xfeatures;
-       u64 allowed_features;
+       struct xstate_header hdr;
 
        offset = offsetof(struct xregs_state, header);
-       size = sizeof(xfeatures);
+       size = sizeof(hdr);
 
-       if (kbuf) {
-               memcpy(&xfeatures, kbuf + offset, size);
-       } else {
-               if (__copy_from_user(&xfeatures, ubuf + offset, size))
-                       return -EFAULT;
+       memcpy(&hdr, kbuf + offset, size);
+
+       if (validate_xstate_header(&hdr))
+               return -EINVAL;
+
+       for (i = 0; i < XFEATURE_MAX; i++) {
+               u64 mask = ((u64)1 << i);
+
+               if (hdr.xfeatures & mask) {
+                       void *dst = __raw_xsave_addr(xsave, 1 << i);
+
+                       offset = xstate_offsets[i];
+                       size = xstate_sizes[i];
+
+                       memcpy(dst, kbuf + offset, size);
+               }
+       }
+
+       if (xfeatures_mxcsr_quirk(hdr.xfeatures)) {
+               offset = offsetof(struct fxregs_state, mxcsr);
+               size = MXCSR_AND_FLAGS_SIZE;
+               memcpy(&xsave->i387.mxcsr, kbuf + offset, size);
        }
 
        /*
-        * Reject if the user sets any disabled or supervisor features:
+        * The state that came in from userspace was user-state only.
+        * Mask all the user states out of 'xfeatures':
+        */
+       xsave->header.xfeatures &= XFEATURE_MASK_SUPERVISOR;
+
+       /*
+        * Add back in the features that came in from userspace:
         */
-       allowed_features = xfeatures_mask & ~XFEATURE_MASK_SUPERVISOR;
+       xsave->header.xfeatures |= hdr.xfeatures;
 
-       if (xfeatures & ~allowed_features)
+       return 0;
+}
+
+/*
+ * Convert from a ptrace or sigreturn standard-format user-space buffer to
+ * kernel XSAVES format and copy to the target thread. This is called from
+ * xstateregs_set(), as well as potentially from the sigreturn() and
+ * rt_sigreturn() system calls.
+ */
+int copy_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf)
+{
+       unsigned int offset, size;
+       int i;
+       struct xstate_header hdr;
+
+       offset = offsetof(struct xregs_state, header);
+       size = sizeof(hdr);
+
+       if (__copy_from_user(&hdr, ubuf + offset, size))
+               return -EFAULT;
+
+       if (validate_xstate_header(&hdr))
                return -EINVAL;
 
        for (i = 0; i < XFEATURE_MAX; i++) {
                u64 mask = ((u64)1 << i);
 
-               if (xfeatures & mask) {
+               if (hdr.xfeatures & mask) {
                        void *dst = __raw_xsave_addr(xsave, 1 << i);
 
                        offset = xstate_offsets[i];
                        size = xstate_sizes[i];
 
-                       if (kbuf) {
-                               memcpy(dst, kbuf + offset, size);
-                       } else {
-                               if (__copy_from_user(dst, ubuf + offset, size))
-                                       return -EFAULT;
-                       }
+                       if (__copy_from_user(dst, ubuf + offset, size))
+                               return -EFAULT;
                }
        }
 
+       if (xfeatures_mxcsr_quirk(hdr.xfeatures)) {
+               offset = offsetof(struct fxregs_state, mxcsr);
+               size = MXCSR_AND_FLAGS_SIZE;
+               if (__copy_from_user(&xsave->i387.mxcsr, ubuf + offset, size))
+                       return -EFAULT;
+       }
+
        /*
         * The state that came in from userspace was user-state only.
         * Mask all the user states out of 'xfeatures':
@@ -1076,7 +1238,7 @@ int copyin_to_xsaves(const void *kbuf, const void __user *ubuf,
        /*
         * Add back in the features that came in from userspace:
         */
-       xsave->header.xfeatures |= xfeatures;
+       xsave->header.xfeatures |= hdr.xfeatures;
 
        return 0;
 }
index 1f38d9a4d9deaf707af2b7e658bd9e9022ba8d75..d4eb450144fdb42c4f667b9f5b1a69d91aa78a2e 100644 (file)
@@ -64,7 +64,7 @@ static void call_on_stack(void *func, void *stack)
 
 static inline void *current_stack(void)
 {
-       return (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1));
+       return (void *)(current_stack_pointer & ~(THREAD_SIZE - 1));
 }
 
 static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc)
@@ -88,7 +88,7 @@ static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc)
 
        /* Save the next esp at the bottom of the stack */
        prev_esp = (u32 *)irqstk;
-       *prev_esp = current_stack_pointer();
+       *prev_esp = current_stack_pointer;
 
        if (unlikely(overflow))
                call_on_stack(print_stack_overflow, isp);
@@ -139,7 +139,7 @@ void do_softirq_own_stack(void)
 
        /* Push the previous esp onto the stack */
        prev_esp = (u32 *)irqstk;
-       *prev_esp = current_stack_pointer();
+       *prev_esp = current_stack_pointer;
 
        call_on_stack(__do_softirq, isp);
 }
index 4b0592ca9e47b332d0ce67f8bcf5f555653587b2..8c1cc08f514f4362bdaefa933fda3cd3769b04f9 100644 (file)
@@ -299,7 +299,7 @@ static int __init create_setup_data_nodes(struct kobject *parent)
        return 0;
 
 out_clean_nodes:
-       for (j = i - 1; j > 0; j--)
+       for (j = i - 1; j >= 0; j--)
                cleanup_setup_data_node(*(kobjp + j));
        kfree(kobjp);
 out_setup_data_kobj:
index aa60a08b65b1090392b542ec7dc642e9827b7606..e675704fa6f7d89ed919631284156717e342979f 100644 (file)
@@ -140,7 +140,8 @@ void kvm_async_pf_task_wait(u32 token)
 
        n.token = token;
        n.cpu = smp_processor_id();
-       n.halted = is_idle_task(current) || preempt_count() > 1;
+       n.halted = is_idle_task(current) || preempt_count() > 1 ||
+                  rcu_preempt_depth();
        init_swait_queue_head(&n.wq);
        hlist_add_head(&n.link, &b->list);
        raw_spin_unlock(&b->lock);
index e04442345fc0977cf73f2573f77b3df71310f0a8..4e188fda59612ed70b98342e8580cd1f311ed141 100644 (file)
@@ -263,7 +263,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
                sp = (unsigned long) ka->sa.sa_restorer;
        }
 
-       if (fpu->fpstate_active) {
+       if (fpu->initialized) {
                sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),
                                          &buf_fx, &math_size);
                *fpstate = (void __user *)sp;
@@ -279,7 +279,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
                return (void __user *)-1L;
 
        /* save i387 and extended state */
-       if (fpu->fpstate_active &&
+       if (fpu->initialized &&
            copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size) < 0)
                return (void __user *)-1L;
 
@@ -755,7 +755,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
                /*
                 * Ensure the signal handler starts with the new fpu state.
                 */
-               if (fpu->fpstate_active)
+               if (fpu->initialized)
                        fpu__clear(fpu);
        }
        signal_setup_done(failed, ksig, stepping);
index 0854ff1692745adf4831e2deea0cb203977847d9..ad59edd84de70cfb978b8c0bc2ac38b892418b71 100644 (file)
@@ -232,12 +232,6 @@ static void notrace start_secondary(void *unused)
         */
        if (boot_cpu_has(X86_FEATURE_PCID))
                __write_cr4(__read_cr4() | X86_CR4_PCIDE);
-       cpu_init();
-       x86_cpuinit.early_percpu_clock_init();
-       preempt_disable();
-       smp_callin();
-
-       enable_start_cpu0 = 0;
 
 #ifdef CONFIG_X86_32
        /* switch away from the initial page table */
@@ -245,6 +239,13 @@ static void notrace start_secondary(void *unused)
        __flush_tlb_all();
 #endif
 
+       cpu_init();
+       x86_cpuinit.early_percpu_clock_init();
+       preempt_disable();
+       smp_callin();
+
+       enable_start_cpu0 = 0;
+
        /* otherwise gcc will move up smp_processor_id before the cpu_init */
        barrier();
        /*
index 34ea3651362ef8383fb456f24125ec4881f42668..67db4f43309ecadc86f4d7e95c6a0db0650a0d18 100644 (file)
@@ -142,7 +142,7 @@ void ist_begin_non_atomic(struct pt_regs *regs)
         * from double_fault.
         */
        BUG_ON((unsigned long)(current_top_of_stack() -
-                              current_stack_pointer()) >= THREAD_SIZE);
+                              current_stack_pointer) >= THREAD_SIZE);
 
        preempt_enable_no_resched();
 }
index 16bf6655aa858e2815135ada11a462329a0df386..a36254cbf7765aabf3e77c45e7cc82c3e3ff0fbb 100644 (file)
@@ -4102,10 +4102,12 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
                ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
                if (efer & EFER_LMA) {
                        u64 maxphyaddr;
-                       u32 eax = 0x80000008;
+                       u32 eax, ebx, ecx, edx;
 
-                       if (ctxt->ops->get_cpuid(ctxt, &eax, NULL, NULL,
-                                                NULL, false))
+                       eax = 0x80000008;
+                       ecx = 0;
+                       if (ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx,
+                                                &edx, false))
                                maxphyaddr = eax & 0xff;
                        else
                                maxphyaddr = 36;
@@ -5296,7 +5298,6 @@ static void fetch_possible_mmx_operand(struct x86_emulate_ctxt *ctxt,
 
 static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *))
 {
-       register void *__sp asm(_ASM_SP);
        ulong flags = (ctxt->eflags & EFLAGS_MASK) | X86_EFLAGS_IF;
 
        if (!(ctxt->d & ByteOp))
@@ -5304,7 +5305,7 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *))
 
        asm("push %[flags]; popf; call *%[fastop]; pushf; pop %[flags]\n"
            : "+a"(ctxt->dst.val), "+d"(ctxt->src.val), [flags]"+D"(flags),
-             [fastop]"+S"(fop), "+r"(__sp)
+             [fastop]"+S"(fop), ASM_CALL_CONSTRAINT
            : "c"(ctxt->src2.val));
 
        ctxt->eflags = (ctxt->eflags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK);
index 06c0c6d0541e9bf95eabbcaa8d20c8ec45f19496..a2b804e10c95d71ac19aebc83c6f89316cea658d 100644 (file)
@@ -200,6 +200,8 @@ struct loaded_vmcs {
        int cpu;
        bool launched;
        bool nmi_known_unmasked;
+       unsigned long vmcs_host_cr3;    /* May not match real cr3 */
+       unsigned long vmcs_host_cr4;    /* May not match real cr4 */
        struct list_head loaded_vmcss_on_cpu_link;
 };
 
@@ -600,8 +602,6 @@ struct vcpu_vmx {
                int           gs_ldt_reload_needed;
                int           fs_reload_needed;
                u64           msr_host_bndcfgs;
-               unsigned long vmcs_host_cr3;    /* May not match real cr3 */
-               unsigned long vmcs_host_cr4;    /* May not match real cr4 */
        } host_state;
        struct {
                int vm86_active;
@@ -2202,46 +2202,44 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
        struct pi_desc old, new;
        unsigned int dest;
 
-       if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-               !irq_remapping_cap(IRQ_POSTING_CAP)  ||
-               !kvm_vcpu_apicv_active(vcpu))
+       /*
+        * In case of hot-plug or hot-unplug, we may have to undo
+        * vmx_vcpu_pi_put even if there is no assigned device.  And we
+        * always keep PI.NDST up to date for simplicity: it makes the
+        * code easier, and CPU migration is not a fast path.
+        */
+       if (!pi_test_sn(pi_desc) && vcpu->cpu == cpu)
+               return;
+
+       /*
+        * First handle the simple case where no cmpxchg is necessary; just
+        * allow posting non-urgent interrupts.
+        *
+        * If the 'nv' field is POSTED_INTR_WAKEUP_VECTOR, do not change
+        * PI.NDST: pi_post_block will do it for us and the wakeup_handler
+        * expects the VCPU to be on the blocked_vcpu_list that matches
+        * PI.NDST.
+        */
+       if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR ||
+           vcpu->cpu == cpu) {
+               pi_clear_sn(pi_desc);
                return;
+       }
 
+       /* The full case.  */
        do {
                old.control = new.control = pi_desc->control;
 
-               /*
-                * If 'nv' field is POSTED_INTR_WAKEUP_VECTOR, there
-                * are two possible cases:
-                * 1. After running 'pre_block', context switch
-                *    happened. For this case, 'sn' was set in
-                *    vmx_vcpu_put(), so we need to clear it here.
-                * 2. After running 'pre_block', we were blocked,
-                *    and woken up by some other guy. For this case,
-                *    we don't need to do anything, 'pi_post_block'
-                *    will do everything for us. However, we cannot
-                *    check whether it is case #1 or case #2 here
-                *    (maybe, not needed), so we also clear sn here,
-                *    I think it is not a big deal.
-                */
-               if (pi_desc->nv != POSTED_INTR_WAKEUP_VECTOR) {
-                       if (vcpu->cpu != cpu) {
-                               dest = cpu_physical_id(cpu);
-
-                               if (x2apic_enabled())
-                                       new.ndst = dest;
-                               else
-                                       new.ndst = (dest << 8) & 0xFF00;
-                       }
+               dest = cpu_physical_id(cpu);
 
-                       /* set 'NV' to 'notification vector' */
-                       new.nv = POSTED_INTR_VECTOR;
-               }
+               if (x2apic_enabled())
+                       new.ndst = dest;
+               else
+                       new.ndst = (dest << 8) & 0xFF00;
 
-               /* Allow posting non-urgent interrupts */
                new.sn = 0;
-       } while (cmpxchg(&pi_desc->control, old.control,
-                       new.control) != old.control);
+       } while (cmpxchg64(&pi_desc->control, old.control,
+                          new.control) != old.control);
 }
 
 static void decache_tsc_multiplier(struct vcpu_vmx *vmx)
@@ -5077,21 +5075,30 @@ static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
        int pi_vec = nested ? POSTED_INTR_NESTED_VECTOR : POSTED_INTR_VECTOR;
 
        if (vcpu->mode == IN_GUEST_MODE) {
-               struct vcpu_vmx *vmx = to_vmx(vcpu);
-
                /*
-                * Currently, we don't support urgent interrupt,
-                * all interrupts are recognized as non-urgent
-                * interrupt, so we cannot post interrupts when
-                * 'SN' is set.
+                * The vector of interrupt to be delivered to vcpu had
+                * been set in PIR before this function.
+                *
+                * Following cases will be reached in this block, and
+                * we always send a notification event in all cases as
+                * explained below.
+                *
+                * Case 1: vcpu keeps in non-root mode. Sending a
+                * notification event posts the interrupt to vcpu.
                 *
-                * If the vcpu is in guest mode, it means it is
-                * running instead of being scheduled out and
-                * waiting in the run queue, and that's the only
-                * case when 'SN' is set currently, warning if
-                * 'SN' is set.
+                * Case 2: vcpu exits to root mode and is still
+                * runnable. PIR will be synced to vIRR before the
+                * next vcpu entry. Sending a notification event in
+                * this case has no effect, as vcpu is not in root
+                * mode.
+                *
+                * Case 3: vcpu exits to root mode and is blocked.
+                * vcpu_block() has already synced PIR to vIRR and
+                * never blocks vcpu if vIRR is not cleared. Therefore,
+                * a blocked vcpu here does not wait for any requested
+                * interrupts in PIR, and sending a notification event
+                * which has no effect is safe here.
                 */
-               WARN_ON_ONCE(pi_test_sn(&vmx->pi_desc));
 
                apic->send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
                return true;
@@ -5169,12 +5176,12 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
         */
        cr3 = __read_cr3();
        vmcs_writel(HOST_CR3, cr3);             /* 22.2.3  FIXME: shadow tables */
-       vmx->host_state.vmcs_host_cr3 = cr3;
+       vmx->loaded_vmcs->vmcs_host_cr3 = cr3;
 
        /* Save the most likely value for this task's CR4 in the VMCS. */
        cr4 = cr4_read_shadow();
        vmcs_writel(HOST_CR4, cr4);                     /* 22.2.3, 22.2.5 */
-       vmx->host_state.vmcs_host_cr4 = cr4;
+       vmx->loaded_vmcs->vmcs_host_cr4 = cr4;
 
        vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS);  /* 22.2.4 */
 #ifdef CONFIG_X86_64
@@ -9036,7 +9043,6 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
 static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 {
        u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-       register void *__sp asm(_ASM_SP);
 
        if ((exit_intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
                        == (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR)) {
@@ -9065,7 +9071,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_X86_64
                        [sp]"=&r"(tmp),
 #endif
-                       "+r"(__sp)
+                       ASM_CALL_CONSTRAINT
                        :
                        [entry]"r"(entry),
                        [ss]"i"(__KERNEL_DS),
@@ -9265,15 +9271,15 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
                vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
 
        cr3 = __get_current_cr3_fast();
-       if (unlikely(cr3 != vmx->host_state.vmcs_host_cr3)) {
+       if (unlikely(cr3 != vmx->loaded_vmcs->vmcs_host_cr3)) {
                vmcs_writel(HOST_CR3, cr3);
-               vmx->host_state.vmcs_host_cr3 = cr3;
+               vmx->loaded_vmcs->vmcs_host_cr3 = cr3;
        }
 
        cr4 = cr4_read_shadow();
-       if (unlikely(cr4 != vmx->host_state.vmcs_host_cr4)) {
+       if (unlikely(cr4 != vmx->loaded_vmcs->vmcs_host_cr4)) {
                vmcs_writel(HOST_CR4, cr4);
-               vmx->host_state.vmcs_host_cr4 = cr4;
+               vmx->loaded_vmcs->vmcs_host_cr4 = cr4;
        }
 
        /* When single-stepping over STI and MOV SS, we must clear the
@@ -9583,6 +9589,13 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
 
        vmx->msr_ia32_feature_control_valid_bits = FEATURE_CONTROL_LOCKED;
 
+       /*
+        * Enforce invariant: pi_desc.nv is always either POSTED_INTR_VECTOR
+        * or POSTED_INTR_WAKEUP_VECTOR.
+        */
+       vmx->pi_desc.nv = POSTED_INTR_VECTOR;
+       vmx->pi_desc.sn = 1;
+
        return &vmx->vcpu;
 
 free_vmcs:
@@ -9831,7 +9844,8 @@ static void vmx_inject_page_fault_nested(struct kvm_vcpu *vcpu,
 
        WARN_ON(!is_guest_mode(vcpu));
 
-       if (nested_vmx_is_page_fault_vmexit(vmcs12, fault->error_code)) {
+       if (nested_vmx_is_page_fault_vmexit(vmcs12, fault->error_code) &&
+               !to_vmx(vcpu)->nested.nested_run_pending) {
                vmcs12->vm_exit_intr_error_code = fault->error_code;
                nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
                                  PF_VECTOR | INTR_TYPE_HARD_EXCEPTION |
@@ -11696,6 +11710,37 @@ static void vmx_enable_log_dirty_pt_masked(struct kvm *kvm,
        kvm_mmu_clear_dirty_pt_masked(kvm, memslot, offset, mask);
 }
 
+static void __pi_post_block(struct kvm_vcpu *vcpu)
+{
+       struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
+       struct pi_desc old, new;
+       unsigned int dest;
+
+       do {
+               old.control = new.control = pi_desc->control;
+               WARN(old.nv != POSTED_INTR_WAKEUP_VECTOR,
+                    "Wakeup handler not enabled while the VCPU is blocked\n");
+
+               dest = cpu_physical_id(vcpu->cpu);
+
+               if (x2apic_enabled())
+                       new.ndst = dest;
+               else
+                       new.ndst = (dest << 8) & 0xFF00;
+
+               /* set 'NV' to 'notification vector' */
+               new.nv = POSTED_INTR_VECTOR;
+       } while (cmpxchg64(&pi_desc->control, old.control,
+                          new.control) != old.control);
+
+       if (!WARN_ON_ONCE(vcpu->pre_pcpu == -1)) {
+               spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
+               list_del(&vcpu->blocked_vcpu_list);
+               spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
+               vcpu->pre_pcpu = -1;
+       }
+}
+
 /*
  * This routine does the following things for vCPU which is going
  * to be blocked if VT-d PI is enabled.
@@ -11711,7 +11756,6 @@ static void vmx_enable_log_dirty_pt_masked(struct kvm *kvm,
  */
 static int pi_pre_block(struct kvm_vcpu *vcpu)
 {
-       unsigned long flags;
        unsigned int dest;
        struct pi_desc old, new;
        struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
@@ -11721,34 +11765,20 @@ static int pi_pre_block(struct kvm_vcpu *vcpu)
                !kvm_vcpu_apicv_active(vcpu))
                return 0;
 
-       vcpu->pre_pcpu = vcpu->cpu;
-       spin_lock_irqsave(&per_cpu(blocked_vcpu_on_cpu_lock,
-                         vcpu->pre_pcpu), flags);
-       list_add_tail(&vcpu->blocked_vcpu_list,
-                     &per_cpu(blocked_vcpu_on_cpu,
-                     vcpu->pre_pcpu));
-       spin_unlock_irqrestore(&per_cpu(blocked_vcpu_on_cpu_lock,
-                              vcpu->pre_pcpu), flags);
+       WARN_ON(irqs_disabled());
+       local_irq_disable();
+       if (!WARN_ON_ONCE(vcpu->pre_pcpu != -1)) {
+               vcpu->pre_pcpu = vcpu->cpu;
+               spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
+               list_add_tail(&vcpu->blocked_vcpu_list,
+                             &per_cpu(blocked_vcpu_on_cpu,
+                                      vcpu->pre_pcpu));
+               spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu));
+       }
 
        do {
                old.control = new.control = pi_desc->control;
 
-               /*
-                * We should not block the vCPU if
-                * an interrupt is posted for it.
-                */
-               if (pi_test_on(pi_desc) == 1) {
-                       spin_lock_irqsave(&per_cpu(blocked_vcpu_on_cpu_lock,
-                                         vcpu->pre_pcpu), flags);
-                       list_del(&vcpu->blocked_vcpu_list);
-                       spin_unlock_irqrestore(
-                                       &per_cpu(blocked_vcpu_on_cpu_lock,
-                                       vcpu->pre_pcpu), flags);
-                       vcpu->pre_pcpu = -1;
-
-                       return 1;
-               }
-
                WARN((pi_desc->sn == 1),
                     "Warning: SN field of posted-interrupts "
                     "is set before blocking\n");
@@ -11770,10 +11800,15 @@ static int pi_pre_block(struct kvm_vcpu *vcpu)
 
                /* set 'NV' to 'wakeup vector' */
                new.nv = POSTED_INTR_WAKEUP_VECTOR;
-       } while (cmpxchg(&pi_desc->control, old.control,
-                       new.control) != old.control);
+       } while (cmpxchg64(&pi_desc->control, old.control,
+                          new.control) != old.control);
 
-       return 0;
+       /* We should not block the vCPU if an interrupt is posted for it.  */
+       if (pi_test_on(pi_desc) == 1)
+               __pi_post_block(vcpu);
+
+       local_irq_enable();
+       return (vcpu->pre_pcpu == -1);
 }
 
 static int vmx_pre_block(struct kvm_vcpu *vcpu)
@@ -11789,44 +11824,13 @@ static int vmx_pre_block(struct kvm_vcpu *vcpu)
 
 static void pi_post_block(struct kvm_vcpu *vcpu)
 {
-       struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
-       struct pi_desc old, new;
-       unsigned int dest;
-       unsigned long flags;
-
-       if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-               !irq_remapping_cap(IRQ_POSTING_CAP)  ||
-               !kvm_vcpu_apicv_active(vcpu))
+       if (vcpu->pre_pcpu == -1)
                return;
 
-       do {
-               old.control = new.control = pi_desc->control;
-
-               dest = cpu_physical_id(vcpu->cpu);
-
-               if (x2apic_enabled())
-                       new.ndst = dest;
-               else
-                       new.ndst = (dest << 8) & 0xFF00;
-
-               /* Allow posting non-urgent interrupts */
-               new.sn = 0;
-
-               /* set 'NV' to 'notification vector' */
-               new.nv = POSTED_INTR_VECTOR;
-       } while (cmpxchg(&pi_desc->control, old.control,
-                       new.control) != old.control);
-
-       if(vcpu->pre_pcpu != -1) {
-               spin_lock_irqsave(
-                       &per_cpu(blocked_vcpu_on_cpu_lock,
-                       vcpu->pre_pcpu), flags);
-               list_del(&vcpu->blocked_vcpu_list);
-               spin_unlock_irqrestore(
-                       &per_cpu(blocked_vcpu_on_cpu_lock,
-                       vcpu->pre_pcpu), flags);
-               vcpu->pre_pcpu = -1;
-       }
+       WARN_ON(irqs_disabled());
+       local_irq_disable();
+       __pi_post_block(vcpu);
+       local_irq_enable();
 }
 
 static void vmx_post_block(struct kvm_vcpu *vcpu)
@@ -11911,12 +11915,8 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
 
                if (set)
                        ret = irq_set_vcpu_affinity(host_irq, &vcpu_info);
-               else {
-                       /* suppress notification event before unposting */
-                       pi_set_sn(vcpu_to_pi_desc(vcpu));
+               else
                        ret = irq_set_vcpu_affinity(host_irq, NULL);
-                       pi_clear_sn(vcpu_to_pi_desc(vcpu));
-               }
 
                if (ret < 0) {
                        printk(KERN_INFO "%s: failed to update PI IRTE\n",
index cd17b7d9a1076c1d28904bc4cd1ea06af5e0f2c0..03869eb7fcd67b64e54dcb67acd559a70fd61139 100644 (file)
@@ -7225,7 +7225,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        int r;
        sigset_t sigsaved;
 
-       fpu__activate_curr(fpu);
+       fpu__initialize(fpu);
 
        if (vcpu->sigset_active)
                sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
index d4a7df2205b8de2576bc7cdbf8455f2fa9987b66..220638a4cb94ea3065e1aaca9caaad7d447c8560 100644 (file)
@@ -114,7 +114,7 @@ void math_emulate(struct math_emu_info *info)
        struct desc_struct code_descriptor;
        struct fpu *fpu = &current->thread.fpu;
 
-       fpu__activate_curr(fpu);
+       fpu__initialize(fpu);
 
 #ifdef RE_ENTRANT_CHECKING
        if (emulating) {
index c076f710de4cb4e283125f706226fc059fbebb5b..c3521e2be39610c3d932c34126fadd5203f28958 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/uaccess.h>
 #include <linux/sched/debug.h>
 
+#include <asm/fpu/internal.h>
 #include <asm/traps.h>
 #include <asm/kdebug.h>
 
@@ -78,6 +79,29 @@ bool ex_handler_refcount(const struct exception_table_entry *fixup,
 }
 EXPORT_SYMBOL_GPL(ex_handler_refcount);
 
+/*
+ * Handler for when we fail to restore a task's FPU state.  We should never get
+ * here because the FPU state of a task using the FPU (task->thread.fpu.state)
+ * should always be valid.  However, past bugs have allowed userspace to set
+ * reserved bits in the XSAVE area using PTRACE_SETREGSET or sys_rt_sigreturn().
+ * These caused XRSTOR to fail when switching to the task, leaking the FPU
+ * registers of the task previously executing on the CPU.  Mitigate this class
+ * of vulnerability by restoring from the initial state (essentially, zeroing
+ * out all the FPU registers) if we can't restore from the task's FPU state.
+ */
+bool ex_handler_fprestore(const struct exception_table_entry *fixup,
+                         struct pt_regs *regs, int trapnr)
+{
+       regs->ip = ex_fixup_addr(fixup);
+
+       WARN_ONCE(1, "Bad FPU state detected at %pB, reinitializing FPU registers.",
+                 (void *)instruction_pointer(regs));
+
+       __copy_kernel_to_fpregs(&init_fpstate, -1);
+       return true;
+}
+EXPORT_SYMBOL_GPL(ex_handler_fprestore);
+
 bool ex_handler_ext(const struct exception_table_entry *fixup,
                   struct pt_regs *regs, int trapnr)
 {
index b836a7274e123af88edd7b4f261da88609778be9..e2baeaa053a5b9feb76a1587fb4756786ffd76db 100644 (file)
@@ -192,8 +192,7 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
  * 6. T1   : reaches here, sees vma_pkey(vma)=5, when we really
  *          faulted on a pte with its pkey=4.
  */
-static void fill_sig_info_pkey(int si_code, siginfo_t *info,
-               struct vm_area_struct *vma)
+static void fill_sig_info_pkey(int si_code, siginfo_t *info, u32 *pkey)
 {
        /* This is effectively an #ifdef */
        if (!boot_cpu_has(X86_FEATURE_OSPKE))
@@ -209,7 +208,7 @@ static void fill_sig_info_pkey(int si_code, siginfo_t *info,
         * valid VMA, so we should never reach this without a
         * valid VMA.
         */
-       if (!vma) {
+       if (!pkey) {
                WARN_ONCE(1, "PKU fault with no VMA passed in");
                info->si_pkey = 0;
                return;
@@ -219,13 +218,12 @@ static void fill_sig_info_pkey(int si_code, siginfo_t *info,
         * absolutely guranteed to be 100% accurate because of
         * the race explained above.
         */
-       info->si_pkey = vma_pkey(vma);
+       info->si_pkey = *pkey;
 }
 
 static void
 force_sig_info_fault(int si_signo, int si_code, unsigned long address,
-                    struct task_struct *tsk, struct vm_area_struct *vma,
-                    int fault)
+                    struct task_struct *tsk, u32 *pkey, int fault)
 {
        unsigned lsb = 0;
        siginfo_t info;
@@ -240,7 +238,7 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address,
                lsb = PAGE_SHIFT;
        info.si_addr_lsb = lsb;
 
-       fill_sig_info_pkey(si_code, &info, vma);
+       fill_sig_info_pkey(si_code, &info, pkey);
 
        force_sig_info(si_signo, &info, tsk);
 }
@@ -762,8 +760,6 @@ no_context(struct pt_regs *regs, unsigned long error_code,
        struct task_struct *tsk = current;
        unsigned long flags;
        int sig;
-       /* No context means no VMA to pass down */
-       struct vm_area_struct *vma = NULL;
 
        /* Are we prepared to handle this kernel fault? */
        if (fixup_exception(regs, X86_TRAP_PF)) {
@@ -788,7 +784,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 
                        /* XXX: hwpoison faults will set the wrong code. */
                        force_sig_info_fault(signal, si_code, address,
-                                            tsk, vma, 0);
+                                            tsk, NULL, 0);
                }
 
                /*
@@ -806,7 +802,6 @@ no_context(struct pt_regs *regs, unsigned long error_code,
        if (is_vmalloc_addr((void *)address) &&
            (((unsigned long)tsk->stack - 1 - address < PAGE_SIZE) ||
             address - ((unsigned long)tsk->stack + THREAD_SIZE) < PAGE_SIZE)) {
-               register void *__sp asm("rsp");
                unsigned long stack = this_cpu_read(orig_ist.ist[DOUBLEFAULT_STACK]) - sizeof(void *);
                /*
                 * We're likely to be running with very little stack space
@@ -821,7 +816,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
                asm volatile ("movq %[stack], %%rsp\n\t"
                              "call handle_stack_overflow\n\t"
                              "1: jmp 1b"
-                             : "+r" (__sp)
+                             : ASM_CALL_CONSTRAINT
                              : "D" ("kernel stack overflow (page fault)"),
                                "S" (regs), "d" (address),
                                [stack] "rm" (stack));
@@ -897,8 +892,7 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code,
 
 static void
 __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
-                      unsigned long address, struct vm_area_struct *vma,
-                      int si_code)
+                      unsigned long address, u32 *pkey, int si_code)
 {
        struct task_struct *tsk = current;
 
@@ -946,7 +940,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
                tsk->thread.error_code  = error_code;
                tsk->thread.trap_nr     = X86_TRAP_PF;
 
-               force_sig_info_fault(SIGSEGV, si_code, address, tsk, vma, 0);
+               force_sig_info_fault(SIGSEGV, si_code, address, tsk, pkey, 0);
 
                return;
        }
@@ -959,9 +953,9 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
 
 static noinline void
 bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
-                    unsigned long address, struct vm_area_struct *vma)
+                    unsigned long address, u32 *pkey)
 {
-       __bad_area_nosemaphore(regs, error_code, address, vma, SEGV_MAPERR);
+       __bad_area_nosemaphore(regs, error_code, address, pkey, SEGV_MAPERR);
 }
 
 static void
@@ -969,6 +963,10 @@ __bad_area(struct pt_regs *regs, unsigned long error_code,
           unsigned long address,  struct vm_area_struct *vma, int si_code)
 {
        struct mm_struct *mm = current->mm;
+       u32 pkey;
+
+       if (vma)
+               pkey = vma_pkey(vma);
 
        /*
         * Something tried to access memory that isn't in our memory map..
@@ -976,7 +974,8 @@ __bad_area(struct pt_regs *regs, unsigned long error_code,
         */
        up_read(&mm->mmap_sem);
 
-       __bad_area_nosemaphore(regs, error_code, address, vma, si_code);
+       __bad_area_nosemaphore(regs, error_code, address,
+                              (vma) ? &pkey : NULL, si_code);
 }
 
 static noinline void
@@ -1019,7 +1018,7 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
 
 static void
 do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
-         struct vm_area_struct *vma, unsigned int fault)
+         u32 *pkey, unsigned int fault)
 {
        struct task_struct *tsk = current;
        int code = BUS_ADRERR;
@@ -1046,13 +1045,12 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
                code = BUS_MCEERR_AR;
        }
 #endif
-       force_sig_info_fault(SIGBUS, code, address, tsk, vma, fault);
+       force_sig_info_fault(SIGBUS, code, address, tsk, pkey, fault);
 }
 
 static noinline void
 mm_fault_error(struct pt_regs *regs, unsigned long error_code,
-              unsigned long address, struct vm_area_struct *vma,
-              unsigned int fault)
+              unsigned long address, u32 *pkey, unsigned int fault)
 {
        if (fatal_signal_pending(current) && !(error_code & PF_USER)) {
                no_context(regs, error_code, address, 0, 0);
@@ -1076,9 +1074,9 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
        } else {
                if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
                             VM_FAULT_HWPOISON_LARGE))
-                       do_sigbus(regs, error_code, address, vma, fault);
+                       do_sigbus(regs, error_code, address, pkey, fault);
                else if (fault & VM_FAULT_SIGSEGV)
-                       bad_area_nosemaphore(regs, error_code, address, vma);
+                       bad_area_nosemaphore(regs, error_code, address, pkey);
                else
                        BUG();
        }
@@ -1268,6 +1266,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code,
        struct mm_struct *mm;
        int fault, major = 0;
        unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+       u32 pkey;
 
        tsk = current;
        mm = tsk->mm;
@@ -1468,9 +1467,10 @@ good_area:
                return;
        }
 
+       pkey = vma_pkey(vma);
        up_read(&mm->mmap_sem);
        if (unlikely(fault & VM_FAULT_ERROR)) {
-               mm_fault_error(regs, error_code, address, vma, fault);
+               mm_fault_error(regs, error_code, address, &pkey, fault);
                return;
        }
 
index 3fcc8e01683bef96b219d65dbdd0315db1f60605..16c5f37933a2ae2d120402f1871af93872aebb07 100644 (file)
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#define DISABLE_BRANCH_PROFILING
+
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <linux/mm.h>
index 2dab69a706ec062affe14eb7d9f10fd8538a9018..d7bc0eea20a5ed2fc8ec43ebc06429517cbb362b 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <asm/cpufeature.h>             /* boot_cpu_has, ...            */
 #include <asm/mmu_context.h>            /* vma_pkey()                   */
-#include <asm/fpu/internal.h>           /* fpregs_active()              */
 
 int __execute_only_pkey(struct mm_struct *mm)
 {
@@ -45,7 +44,7 @@ int __execute_only_pkey(struct mm_struct *mm)
         */
        preempt_disable();
        if (!need_to_set_mm_pkey &&
-           fpregs_active() &&
+           current->thread.fpu.initialized &&
            !__pkru_allows_read(read_pkru(), execute_only_pkey)) {
                preempt_enable();
                return execute_only_pkey;
index 1ab3821f9e2629df571544077d63be950361bc20..49d9778376d774c3d6f17eb47118176efb99b718 100644 (file)
@@ -126,8 +126,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
         * isn't free.
         */
 #ifdef CONFIG_DEBUG_VM
-       if (WARN_ON_ONCE(__read_cr3() !=
-                        (__sme_pa(real_prev->pgd) | prev_asid))) {
+       if (WARN_ON_ONCE(__read_cr3() != build_cr3(real_prev, prev_asid))) {
                /*
                 * If we were to BUG here, we'd be very likely to kill
                 * the system so hard that we don't see the call trace.
@@ -172,7 +171,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                         */
                        this_cpu_write(cpu_tlbstate.ctxs[prev_asid].tlb_gen,
                                       next_tlb_gen);
-                       write_cr3(__sme_pa(next->pgd) | prev_asid);
+                       write_cr3(build_cr3(next, prev_asid));
                        trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH,
                                        TLB_FLUSH_ALL);
                }
@@ -192,7 +191,7 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                         * mapped in the new pgd, we'll double-fault.  Forcibly
                         * map it.
                         */
-                       unsigned int index = pgd_index(current_stack_pointer());
+                       unsigned int index = pgd_index(current_stack_pointer);
                        pgd_t *pgd = next->pgd + index;
 
                        if (unlikely(pgd_none(*pgd)))
@@ -216,12 +215,12 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                if (need_flush) {
                        this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id);
                        this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen);
-                       write_cr3(__sme_pa(next->pgd) | new_asid);
+                       write_cr3(build_cr3(next, new_asid));
                        trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH,
                                        TLB_FLUSH_ALL);
                } else {
                        /* The new ASID is already up to date. */
-                       write_cr3(__sme_pa(next->pgd) | new_asid | CR3_NOFLUSH);
+                       write_cr3(build_cr3_noflush(next, new_asid));
                        trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, 0);
                }
 
@@ -265,7 +264,7 @@ void initialize_tlbstate_and_flush(void)
                !(cr4_read_shadow() & X86_CR4_PCIDE));
 
        /* Force ASID 0 and force a TLB flush. */
-       write_cr3(cr3 & ~CR3_PCID_MASK);
+       write_cr3(build_cr3(mm, 0));
 
        /* Reinitialize tlbstate. */
        this_cpu_write(cpu_tlbstate.loaded_mm_asid, 0);
index 509f560bd0c6d4731cac96fc64296184e6818b9c..71495f1a86d72f7df1464ce3ffe805d880948bbd 100644 (file)
@@ -1238,21 +1238,16 @@ static void __init xen_pagetable_cleanhighmap(void)
         * from _brk_limit way up to the max_pfn_mapped (which is the end of
         * the ramdisk). We continue on, erasing PMD entries that point to page
         * tables - do note that they are accessible at this stage via __va.
-        * For good measure we also round up to the PMD - which means that if
+        * As Xen is aligning the memory end to a 4MB boundary, for good
+        * measure we also round up to PMD_SIZE * 2 - which means that if
         * anybody is using __ka address to the initial boot-stack - and try
         * to use it - they are going to crash. The xen_start_info has been
         * taken care of already in xen_setup_kernel_pagetable. */
        addr = xen_start_info->pt_base;
-       size = roundup(xen_start_info->nr_pt_frames * PAGE_SIZE, PMD_SIZE);
+       size = xen_start_info->nr_pt_frames * PAGE_SIZE;
 
-       xen_cleanhighmap(addr, addr + size);
+       xen_cleanhighmap(addr, roundup(addr + size, PMD_SIZE * 2));
        xen_start_info->pt_base = (unsigned long)__va(__pa(xen_start_info->pt_base));
-#ifdef DEBUG
-       /* This is superfluous and is not necessary, but you know what
-        * lets do it. The MODULES_VADDR -> MODULES_END should be clear of
-        * anything at this stage. */
-       xen_cleanhighmap(MODULES_VADDR, roundup(MODULES_VADDR, PUD_SIZE) - 1);
-#endif
 }
 #endif
 
@@ -2220,7 +2215,7 @@ static void __init xen_write_cr3_init(unsigned long cr3)
  * not the first page table in the page table pool.
  * Iterate through the initial page tables to find the real page table base.
  */
-static phys_addr_t xen_find_pt_base(pmd_t *pmd)
+static phys_addr_t __init xen_find_pt_base(pmd_t *pmd)
 {
        phys_addr_t pt_base, paddr;
        unsigned pmdidx;
index 30ee8c608853d4fb4b238a01319589d38ce018b7..5b0027d4ecc05cff651baec243a612d8deea20bc 100644 (file)
@@ -208,11 +208,6 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
-/* Copy and release all segment info associated with a VM */
-#define copy_segments(p, mm)   do { } while(0)
-#define release_segments(mm)   do { } while(0)
-#define forget_segments()      do { } while (0)
-
 extern unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)          (task_pt_regs(tsk)->pc)
index aebe676225e6fdf360f39760cacf7326cf78cd9f..048be4aa602446f93e3e981f1ece5659e3d7287b 100644 (file)
@@ -854,6 +854,9 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 
        kobject_init(&q->kobj, &blk_queue_ktype);
 
+#ifdef CONFIG_BLK_DEV_IO_TRACE
+       mutex_init(&q->blk_trace_mutex);
+#endif
        mutex_init(&q->sysfs_lock);
        spin_lock_init(&q->__queue_lock);
 
index c82408c7cc3c91181f91d32c0147e18781506691..dbddff8174e57a92d09f5bdc9cc83ee6f7217eb9 100644 (file)
@@ -154,7 +154,6 @@ static int bsg_prepare_job(struct device *dev, struct request *req)
 failjob_rls_rqst_payload:
        kfree(job->request_payload.sg_list);
 failjob_rls_job:
-       kfree(job);
        return -ENOMEM;
 }
 
index 86e8fe1adcdb7f1b10fd5acd8f5c36f712736971..88c555db4e5deee60d852b78b70a20589cc2813f 100644 (file)
@@ -112,7 +112,7 @@ ssize_t part_stat_show(struct device *dev,
                       struct device_attribute *attr, char *buf)
 {
        struct hd_struct *p = dev_to_part(dev);
-       struct request_queue *q = dev_to_disk(dev)->queue;
+       struct request_queue *q = part_to_disk(p)->queue;
        unsigned int inflight[2];
        int cpu;
 
index ffa9f4ccd9b455ef36c48d3ba57d4256574cd450..337cf382718ee3cd81ffe3cdc480052a6f634798 100644 (file)
@@ -619,14 +619,14 @@ void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
        struct af_alg_ctx *ctx = ask->private;
        struct af_alg_tsgl *sgl;
        struct scatterlist *sg;
-       unsigned int i, j;
+       unsigned int i, j = 0;
 
        while (!list_empty(&ctx->tsgl_list)) {
                sgl = list_first_entry(&ctx->tsgl_list, struct af_alg_tsgl,
                                       list);
                sg = sgl->sg;
 
-               for (i = 0, j = 0; i < sgl->cur; i++) {
+               for (i = 0; i < sgl->cur; i++) {
                        size_t plen = min_t(size_t, used, sg[i].length);
                        struct page *page = sg_page(sg + i);
 
index 633a88e93ab0c421b7b01a041726ad9563ce2d49..70018397e59abf10d125864f5770c41cd13f2021 100644 (file)
@@ -1133,10 +1133,10 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
 {
        if (!drbg)
                return;
-       kzfree(drbg->V);
-       drbg->Vbuf = NULL;
-       kzfree(drbg->C);
-       drbg->Cbuf = NULL;
+       kzfree(drbg->Vbuf);
+       drbg->V = NULL;
+       kzfree(drbg->Cbuf);
+       drbg->C = NULL;
        kzfree(drbg->scratchpadbuf);
        drbg->scratchpadbuf = NULL;
        drbg->reseed_ctr = 0;
index bf22c29d25179e937523c026c8028f644f3379f6..11b113f8e36741aeb00e921ee64a5ae871f8d55f 100644 (file)
@@ -66,7 +66,7 @@ void __init acpi_watchdog_init(void)
        for (i = 0; i < wdat->entries; i++) {
                const struct acpi_generic_address *gas;
                struct resource_entry *rentry;
-               struct resource res;
+               struct resource res = {};
                bool found;
 
                gas = &entries[i].register_region;
index 077f9bad6f44a57bd01e930f9dd740001eadcd76..3c3a37b8503bd43db4200230309ddeff96eb4e00 100644 (file)
@@ -743,17 +743,19 @@ static int ghes_proc(struct ghes *ghes)
        }
        ghes_do_proc(ghes, ghes->estatus);
 
+out:
+       ghes_clear_estatus(ghes);
+
+       if (rc == -ENOENT)
+               return rc;
+
        /*
         * GHESv2 type HEST entries introduce support for error acknowledgment,
         * so only acknowledge the error if this support is present.
         */
-       if (is_hest_type_generic_v2(ghes)) {
-               rc = ghes_ack_error(ghes->generic_v2);
-               if (rc)
-                       return rc;
-       }
-out:
-       ghes_clear_estatus(ghes);
+       if (is_hest_type_generic_v2(ghes))
+               return ghes_ack_error(ghes->generic_v2);
+
        return rc;
 }
 
index c1c216163de3f0ab5b044c52527ed10e3090a9e5..3fb8ff5134613fb044b68ab8f9e8b3c7a234f1b5 100644 (file)
@@ -908,11 +908,12 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
                                            struct fwnode_handle *child)
 {
        const struct acpi_device *adev = to_acpi_device_node(fwnode);
-       struct acpi_device *child_adev = NULL;
        const struct list_head *head;
        struct list_head *next;
 
        if (!child || is_acpi_device_node(child)) {
+               struct acpi_device *child_adev;
+
                if (adev)
                        head = &adev->children;
                else
@@ -922,8 +923,8 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
                        goto nondev;
 
                if (child) {
-                       child_adev = to_acpi_device_node(child);
-                       next = child_adev->node.next;
+                       adev = to_acpi_device_node(child);
+                       next = adev->node.next;
                        if (next == head) {
                                child = NULL;
                                goto nondev;
@@ -941,8 +942,8 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
                const struct acpi_data_node *data = to_acpi_data_node(fwnode);
                struct acpi_data_node *dn;
 
-               if (child_adev)
-                       head = &child_adev->data.subnodes;
+               if (adev)
+                       head = &adev->data.subnodes;
                else if (data)
                        head = &data->data.subnodes;
                else
@@ -1293,3 +1294,16 @@ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
 DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
 DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
 const struct fwnode_operations acpi_static_fwnode_ops;
+
+bool is_acpi_device_node(const struct fwnode_handle *fwnode)
+{
+       return !IS_ERR_OR_NULL(fwnode) &&
+               fwnode->ops == &acpi_device_fwnode_ops;
+}
+EXPORT_SYMBOL(is_acpi_device_node);
+
+bool is_acpi_data_node(const struct fwnode_handle *fwnode)
+{
+       return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
+}
+EXPORT_SYMBOL(is_acpi_data_node);
index a39b2166b145616d2a6261da8da7252aa7e28b4d..744f64f43454314c35acc4341def004968aeff87 100644 (file)
@@ -348,16 +348,15 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
        struct dma_coherent_mem *mem = rmem->priv;
        int ret;
 
-       if (!mem)
-               return -ENODEV;
-
-       ret = dma_init_coherent_memory(rmem->base, rmem->base, rmem->size,
-                                      DMA_MEMORY_EXCLUSIVE, &mem);
-
-       if (ret) {
-               pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
-                       &rmem->base, (unsigned long)rmem->size / SZ_1M);
-               return ret;
+       if (!mem) {
+               ret = dma_init_coherent_memory(rmem->base, rmem->base,
+                                              rmem->size,
+                                              DMA_MEMORY_EXCLUSIVE, &mem);
+               if (ret) {
+                       pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
+                               &rmem->base, (unsigned long)rmem->size / SZ_1M);
+                       return ret;
+               }
        }
        mem->use_dev_dma_pfn_offset = true;
        rmem->priv = mem;
index ea1732ed7a9d9071db73784c7e37d505ed8dea0a..770b1539a083d111ba1a65b569d3a75eaa81dd38 100644 (file)
@@ -1860,10 +1860,13 @@ void device_pm_check_callbacks(struct device *dev)
 {
        spin_lock_irq(&dev->power.lock);
        dev->power.no_pm_callbacks =
-               (!dev->bus || pm_ops_is_empty(dev->bus->pm)) &&
-               (!dev->class || pm_ops_is_empty(dev->class->pm)) &&
+               (!dev->bus || (pm_ops_is_empty(dev->bus->pm) &&
+                !dev->bus->suspend && !dev->bus->resume)) &&
+               (!dev->class || (pm_ops_is_empty(dev->class->pm) &&
+                !dev->class->suspend && !dev->class->resume)) &&
                (!dev->type || pm_ops_is_empty(dev->type->pm)) &&
                (!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
-               (!dev->driver || pm_ops_is_empty(dev->driver->pm));
+               (!dev->driver || (pm_ops_is_empty(dev->driver->pm) &&
+                !dev->driver->suspend && !dev->driver->resume));
        spin_unlock_irq(&dev->power.lock);
 }
index a8cc14fd8ae49ff92cb2fc3dd593273aefd6e10d..a6de325306933b57928b8d16d741247e93274102 100644 (file)
@@ -1581,6 +1581,9 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
 
        opp->available = availability_req;
 
+       dev_pm_opp_get(opp);
+       mutex_unlock(&opp_table->lock);
+
        /* Notify the change of the OPP availability */
        if (availability_req)
                blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ENABLE,
@@ -1589,8 +1592,12 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
                blocking_notifier_call_chain(&opp_table->head,
                                             OPP_EVENT_DISABLE, opp);
 
+       dev_pm_opp_put(opp);
+       goto put_table;
+
 unlock:
        mutex_unlock(&opp_table->lock);
+put_table:
        dev_pm_opp_put_opp_table(opp_table);
        return r;
 }
index f850daeffba4417ae6b2cc69a0f4aa5bf065987e..277d43a83f53e8dc011184ebaf6c783c02f7395b 100644 (file)
@@ -277,11 +277,11 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
        mutex_unlock(&dev_pm_qos_sysfs_mtx);
 }
 
-static bool dev_pm_qos_invalid_request(struct device *dev,
-                                      struct dev_pm_qos_request *req)
+static bool dev_pm_qos_invalid_req_type(struct device *dev,
+                                       enum dev_pm_qos_req_type type)
 {
-       return !req || (req->type == DEV_PM_QOS_LATENCY_TOLERANCE
-                       && !dev->power.set_latency_tolerance);
+       return type == DEV_PM_QOS_LATENCY_TOLERANCE &&
+              !dev->power.set_latency_tolerance;
 }
 
 static int __dev_pm_qos_add_request(struct device *dev,
@@ -290,7 +290,7 @@ static int __dev_pm_qos_add_request(struct device *dev,
 {
        int ret = 0;
 
-       if (!dev || dev_pm_qos_invalid_request(dev, req))
+       if (!dev || !req || dev_pm_qos_invalid_req_type(dev, type))
                return -EINVAL;
 
        if (WARN(dev_pm_qos_request_active(req),
index bbd0d186cfc00ff89f9378b5816ff15ee90b1005..2d7178f7754edddf06278e46e87cc9aefc6d4427 100644 (file)
@@ -342,7 +342,7 @@ static long __brd_direct_access(struct brd_device *brd, pgoff_t pgoff,
 
        if (!brd)
                return -ENODEV;
-       page = brd_insert_page(brd, PFN_PHYS(pgoff) / 512);
+       page = brd_insert_page(brd, (sector_t)pgoff << PAGE_SECTORS_SHIFT);
        if (!page)
                return -ENOSPC;
        *kaddr = page_address(page);
index f68c1d50802fddb3289480124fc1459c9b66ea9e..1f3956702993883859070b2ef39a9b164978a213 100644 (file)
@@ -67,10 +67,8 @@ struct loop_device {
 struct loop_cmd {
        struct kthread_work work;
        struct request *rq;
-       union {
-               bool use_aio; /* use AIO interface to handle I/O */
-               atomic_t ref; /* only for aio */
-       };
+       bool use_aio; /* use AIO interface to handle I/O */
+       atomic_t ref; /* only for aio */
        long ret;
        struct kiocb iocb;
        struct bio_vec *bvec;
index 2aa87cbdede0ed19b77c8e4aaffea2c2d8146758..3684e21d543f23e95bda09fb895e8933b9bce186 100644 (file)
@@ -1194,6 +1194,12 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       /* The block layer will pass back some non-nbd ioctls in case we have
+        * special handling for them, but we don't so just return an error.
+        */
+       if (_IOC_TYPE(cmd) != 0xab)
+               return -EINVAL;
+
        mutex_lock(&nbd->config_lock);
 
        /* Don't allow ioctl operations on a nbd device that was created with
index fe597e6c55c40ca34f070f83a2af53e9b42a66de..1d6729be4cd6376727b9b210319bd77f03ccfb02 100644 (file)
@@ -455,7 +455,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
                        goto out;
                }
 
-               msleep(TPM_TIMEOUT);    /* CHECK */
+               tpm_msleep(TPM_TIMEOUT);
                rmb();
        } while (time_before(jiffies, stop));
 
@@ -970,7 +970,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
                        dev_info(
                            &chip->dev, HW_ERR
                            "TPM command timed out during continue self test");
-                       msleep(delay_msec);
+                       tpm_msleep(delay_msec);
                        continue;
                }
 
@@ -985,7 +985,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
                }
                if (rc != TPM_WARN_DOING_SELFTEST)
                        return rc;
-               msleep(delay_msec);
+               tpm_msleep(delay_msec);
        } while (--loops > 0);
 
        return rc;
@@ -1085,7 +1085,7 @@ again:
                }
        } else {
                do {
-                       msleep(TPM_TIMEOUT);
+                       tpm_msleep(TPM_TIMEOUT);
                        status = chip->ops->status(chip);
                        if ((status & mask) == mask)
                                return 0;
@@ -1150,7 +1150,7 @@ int tpm_pm_suspend(struct device *dev)
                 */
                if (rc != TPM_WARN_RETRY)
                        break;
-               msleep(TPM_TIMEOUT_RETRY);
+               tpm_msleep(TPM_TIMEOUT_RETRY);
        }
 
        if (rc)
index 04fbff2edbf38ce19845e5c1fdd1cd619293419d..2d5466a72e40f82b3272b857b74a1f822f82b966 100644 (file)
@@ -50,7 +50,8 @@ enum tpm_const {
 
 enum tpm_timeout {
        TPM_TIMEOUT = 5,        /* msecs */
-       TPM_TIMEOUT_RETRY = 100 /* msecs */
+       TPM_TIMEOUT_RETRY = 100, /* msecs */
+       TPM_TIMEOUT_RANGE_US = 300      /* usecs */
 };
 
 /* TPM addresses */
@@ -527,6 +528,12 @@ int tpm_pm_resume(struct device *dev);
 int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
                      wait_queue_head_t *queue, bool check_cancel);
 
+static inline void tpm_msleep(unsigned int delay_msec)
+{
+       usleep_range(delay_msec * 1000,
+                    (delay_msec * 1000) + TPM_TIMEOUT_RANGE_US);
+};
+
 struct tpm_chip *tpm_chip_find_get(int chip_num);
 __must_check int tpm_try_get_ops(struct tpm_chip *chip);
 void tpm_put_ops(struct tpm_chip *chip);
index f7f34b2aa98190c7474b3dd6c0f02b2abc032ec9..e1a41b788f081c829ad0d0353ac7d3622752c82f 100644 (file)
@@ -899,7 +899,7 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
                if (rc != TPM2_RC_TESTING)
                        break;
 
-               msleep(delay_msec);
+               tpm_msleep(delay_msec);
        }
 
        return rc;
index a4ac63a21d8a051da3c336f5343b9dc72574b719..8f0a98dea327a5bc90d7fcf3529c3701d17abd6b 100644 (file)
@@ -665,7 +665,7 @@ static const struct dev_pm_ops crb_pm = {
        SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL)
 };
 
-static struct acpi_device_id crb_device_ids[] = {
+static const struct acpi_device_id crb_device_ids[] = {
        {"MSFT0101", 0},
        {"", 0},
 };
index f01d083eced2fc056d6d74e4423a62f28470e302..25f6e2665385d063d47c50ad9f21e25591f828c9 100644 (file)
 
 static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
 
-static struct vio_device_id tpm_ibmvtpm_device_table[] = {
+static const struct vio_device_id tpm_ibmvtpm_device_table[] = {
        { "IBM,vtpm", "IBM,vtpm"},
        { "", "" }
 };
 MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);
 
 /**
+ *
+ * ibmvtpm_send_crq_word - Send a CRQ request
+ * @vdev:      vio device struct
+ * @w1:                pre-constructed first word of tpm crq (second word is reserved)
+ *
+ * Return:
+ *     0 - Success
+ *     Non-zero - Failure
+ */
+static int ibmvtpm_send_crq_word(struct vio_dev *vdev, u64 w1)
+{
+       return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, 0);
+}
+
+/**
+ *
  * ibmvtpm_send_crq - Send a CRQ request
  *
  * @vdev:      vio device struct
- * @w1:                first word
- * @w2:                second word
+ * @valid:     Valid field
+ * @msg:       Type field
+ * @len:       Length field
+ * @data:      Data field
+ *
+ * The ibmvtpm crq is defined as follows:
+ *
+ * Byte  |   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7
+ * -----------------------------------------------------------------------
+ * Word0 | Valid | Type  |     Length    |              Data
+ * -----------------------------------------------------------------------
+ * Word1 |                Reserved
+ * -----------------------------------------------------------------------
+ *
+ * Which matches the following structure (on bigendian host):
+ *
+ * struct ibmvtpm_crq {
+ *         u8 valid;
+ *         u8 msg;
+ *         __be16 len;
+ *         __be32 data;
+ *         __be64 reserved;
+ * } __attribute__((packed, aligned(8)));
+ *
+ * However, the value is passed in a register so just compute the numeric value
+ * to load into the register avoiding byteswap altogether. Endian only affects
+ * memory loads and stores - registers are internally represented the same.
  *
  * Return:
- *     0 -Sucess
+ *     0 (H_SUCCESS) - Success
  *     Non-zero - Failure
  */
-static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
+static int ibmvtpm_send_crq(struct vio_dev *vdev,
+               u8 valid, u8 msg, u16 len, u32 data)
 {
-       return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
+       u64 w1 = ((u64)valid << 56) | ((u64)msg << 48) | ((u64)len << 32) |
+               (u64)data;
+       return ibmvtpm_send_crq_word(vdev, w1);
 }
 
 /**
@@ -109,8 +153,6 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
 {
        struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
-       struct ibmvtpm_crq crq;
-       __be64 *word = (__be64 *)&crq;
        int rc, sig;
 
        if (!ibmvtpm->rtce_buf) {
@@ -137,10 +179,6 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
        spin_lock(&ibmvtpm->rtce_lock);
        ibmvtpm->res_len = 0;
        memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
-       crq.valid = (u8)IBMVTPM_VALID_CMD;
-       crq.msg = (u8)VTPM_TPM_COMMAND;
-       crq.len = cpu_to_be16(count);
-       crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);
 
        /*
         * set the processing flag before the Hcall, since we may get the
@@ -148,8 +186,9 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
         */
        ibmvtpm->tpm_processing_cmd = true;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
-                             be64_to_cpu(word[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev,
+                       IBMVTPM_VALID_CMD, VTPM_TPM_COMMAND,
+                       count, ibmvtpm->rtce_dma_handle);
        if (rc != H_SUCCESS) {
                dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
                rc = 0;
@@ -182,15 +221,10 @@ static u8 tpm_ibmvtpm_status(struct tpm_chip *chip)
  */
 static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
 {
-       struct ibmvtpm_crq crq;
-       u64 *buf = (u64 *) &crq;
        int rc;
 
-       crq.valid = (u8)IBMVTPM_VALID_CMD;
-       crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
-
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
-                             cpu_to_be64(buf[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev,
+                       IBMVTPM_VALID_CMD, VTPM_GET_RTCE_BUFFER_SIZE, 0, 0);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
@@ -210,15 +244,10 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
  */
 static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
 {
-       struct ibmvtpm_crq crq;
-       u64 *buf = (u64 *) &crq;
        int rc;
 
-       crq.valid = (u8)IBMVTPM_VALID_CMD;
-       crq.msg = (u8)VTPM_GET_VERSION;
-
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
-                             cpu_to_be64(buf[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev,
+                       IBMVTPM_VALID_CMD, VTPM_GET_VERSION, 0, 0);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_get_version failed rc=%d\n", rc);
@@ -238,7 +267,7 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
 {
        int rc;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_COMP_CMD, 0);
+       rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_COMP_CMD);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_send_init_complete failed rc=%d\n", rc);
@@ -258,7 +287,7 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
 {
        int rc;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_CMD, 0);
+       rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_send_init failed rc=%d\n", rc);
@@ -340,15 +369,10 @@ static int tpm_ibmvtpm_suspend(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
        struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
-       struct ibmvtpm_crq crq;
-       u64 *buf = (u64 *) &crq;
        int rc = 0;
 
-       crq.valid = (u8)IBMVTPM_VALID_CMD;
-       crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
-
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
-                             cpu_to_be64(buf[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev,
+                       IBMVTPM_VALID_CMD, VTPM_PREPARE_TO_SUSPEND, 0, 0);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "tpm_ibmvtpm_suspend failed rc=%d\n", rc);
index 3b1b9f9322d5547120f35f490b7ec7b802d2b085..d8f10047fbbaf1f2f965a795358e60be859fb759 100644 (file)
@@ -191,7 +191,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
                /* check the status-register if wait_for_bit is set */
                if (status & 1 << wait_for_bit)
                        break;
-               msleep(TPM_MSLEEP_TIME);
+               tpm_msleep(TPM_MSLEEP_TIME);
        }
        if (i == TPM_MAX_TRIES) {       /* timeout occurs */
                if (wait_for_bit == STAT_XFE)
@@ -226,7 +226,7 @@ static void tpm_wtx(struct tpm_chip *chip)
        wait_and_send(chip, TPM_CTRL_WTX);
        wait_and_send(chip, 0x00);
        wait_and_send(chip, 0x00);
-       msleep(TPM_WTX_MSLEEP_TIME);
+       tpm_msleep(TPM_WTX_MSLEEP_TIME);
 }
 
 static void tpm_wtx_abort(struct tpm_chip *chip)
@@ -237,7 +237,7 @@ static void tpm_wtx_abort(struct tpm_chip *chip)
        wait_and_send(chip, 0x00);
        wait_and_send(chip, 0x00);
        number_of_wtx = 0;
-       msleep(TPM_WTX_MSLEEP_TIME);
+       tpm_msleep(TPM_WTX_MSLEEP_TIME);
 }
 
 static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
index b617b2eeb080ad41034b7b7cbd1b21aaed524a3a..63bc6c3b949e51406527a484d356e24959ed9615 100644 (file)
@@ -51,7 +51,7 @@ static int wait_startup(struct tpm_chip *chip, int l)
 
                if (access & TPM_ACCESS_VALID)
                        return 0;
-               msleep(TPM_TIMEOUT);
+               tpm_msleep(TPM_TIMEOUT);
        } while (time_before(jiffies, stop));
        return -1;
 }
@@ -117,7 +117,7 @@ again:
                do {
                        if (check_locality(chip, l))
                                return l;
-                       msleep(TPM_TIMEOUT);
+                       tpm_msleep(TPM_TIMEOUT);
                } while (time_before(jiffies, stop));
        }
        return -1;
@@ -164,7 +164,7 @@ static int get_burstcount(struct tpm_chip *chip)
                burstcnt = (value >> 8) & 0xFFFF;
                if (burstcnt)
                        return burstcnt;
-               msleep(TPM_TIMEOUT);
+               tpm_msleep(TPM_TIMEOUT);
        } while (time_before(jiffies, stop));
        return -EBUSY;
 }
@@ -396,7 +396,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
        priv->irq = irq;
        chip->flags |= TPM_CHIP_FLAG_IRQ;
        if (!priv->irq_tested)
-               msleep(1);
+               tpm_msleep(1);
        if (!priv->irq_tested)
                disable_interrupts(chip);
        priv->irq_tested = true;
index 6a20dc8b253f4c66981e39bec82f1e2634c50f41..9a7d7f0f23feae971f1f8d959b66578e9c59833e 100644 (file)
@@ -43,7 +43,7 @@ static int numachip2_set_next_event(unsigned long delta, struct clock_event_devi
        return 0;
 }
 
-static struct clock_event_device numachip2_clockevent = {
+static const struct clock_event_device numachip2_clockevent __initconst = {
        .name            = "numachip2",
        .rating          = 400,
        .set_next_event  = numachip2_set_next_event,
index 2ff64d9d4fb31a3a10a85361d8f5b3b33039f76d..62d24690ba0205df997f588207bfe3e9b649c325 100644 (file)
@@ -36,8 +36,8 @@ static u64 notrace integrator_read_sched_clock(void)
        return -readl(sched_clk_base + TIMER_VALUE);
 }
 
-static int integrator_clocksource_init(unsigned long inrate,
-                                      void __iomem *base)
+static int __init integrator_clocksource_init(unsigned long inrate,
+                                             void __iomem *base)
 {
        u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
        unsigned long rate = inrate;
index a020da7940d6395a326d5c2ddb6dd01c8f5835e3..a753c50e9e412ea96cb69fa454e81e084a3016be 100644 (file)
@@ -106,6 +106,22 @@ static const struct of_device_id whitelist[] __initconst = {
  * platforms using "operating-points-v2" property.
  */
 static const struct of_device_id blacklist[] __initconst = {
+       { .compatible = "calxeda,highbank", },
+       { .compatible = "calxeda,ecx-2000", },
+
+       { .compatible = "marvell,armadaxp", },
+
+       { .compatible = "nvidia,tegra124", },
+
+       { .compatible = "st,stih407", },
+       { .compatible = "st,stih410", },
+
+       { .compatible = "sigma,tango4", },
+
+       { .compatible = "ti,am33xx", },
+       { .compatible = "ti,am43", },
+       { .compatible = "ti,dra7", },
+
        { }
 };
 
index b29cd339846302402dcee8333765ad670555a2b3..4bf47de6101faca3896966cd4a3214d190568b5c 100644 (file)
@@ -190,7 +190,7 @@ static int ti_cpufreq_setup_syscon_register(struct ti_cpufreq_data *opp_data)
 
 static const struct of_device_id ti_cpufreq_of_match[] = {
        { .compatible = "ti,am33xx", .data = &am3x_soc_data, },
-       { .compatible = "ti,am4372", .data = &am4x_soc_data, },
+       { .compatible = "ti,am43", .data = &am4x_soc_data, },
        { .compatible = "ti,dra7", .data = &dra7_soc_data },
        {},
 };
index 7080c384ad5de656e8c345a336167624b236a2bb..52a75053ee0312146e0ab879bc351b46153faee7 100644 (file)
@@ -104,13 +104,13 @@ static int __init arm_idle_init(void)
                ret = dt_init_idle_driver(drv, arm_idle_state_match, 1);
                if (ret <= 0) {
                        ret = ret ? : -ENODEV;
-                       goto out_fail;
+                       goto init_fail;
                }
 
                ret = cpuidle_register_driver(drv);
                if (ret) {
                        pr_err("Failed to register cpuidle driver\n");
-                       goto out_fail;
+                       goto init_fail;
                }
 
                /*
@@ -149,6 +149,8 @@ static int __init arm_idle_init(void)
        }
 
        return 0;
+init_fail:
+       kfree(drv);
 out_fail:
        while (--cpu >= 0) {
                dev = per_cpu(cpuidle_devices, cpu);
index e36aeacd763596e76ce9eac46e3a1edd5f5443c8..1eb852765469e6633a0af44e3d6ed26ad52234ec 100644 (file)
@@ -1,6 +1,7 @@
 config CRYPTO_DEV_FSL_CAAM
        tristate "Freescale CAAM-Multicore driver backend"
        depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE
+       select SOC_BUS
        help
          Enables the driver module for Freescale's Cryptographic Accelerator
          and Assurance Module (CAAM), also known as the SEC version 4 (SEC4).
@@ -141,10 +142,6 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
          To compile this as a module, choose M here: the module
          will be called caamrng.
 
-config CRYPTO_DEV_FSL_CAAM_IMX
-       def_bool SOC_IMX6 || SOC_IMX7D
-       depends on CRYPTO_DEV_FSL_CAAM
-
 config CRYPTO_DEV_FSL_CAAM_DEBUG
        bool "Enable debug output in CAAM driver"
        depends on CRYPTO_DEV_FSL_CAAM
index dacb53fb690e9583323500333de5d74be3af20f5..027e121c6f70aa9214a29692e8a3ef1e6d886496 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/device.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/sys_soc.h>
 
 #include "compat.h"
 #include "regs.h"
@@ -19,6 +20,8 @@ bool caam_little_end;
 EXPORT_SYMBOL(caam_little_end);
 bool caam_dpaa2;
 EXPORT_SYMBOL(caam_dpaa2);
+bool caam_imx;
+EXPORT_SYMBOL(caam_imx);
 
 #ifdef CONFIG_CAAM_QI
 #include "qi.h"
@@ -28,19 +31,11 @@ EXPORT_SYMBOL(caam_dpaa2);
  * i.MX targets tend to have clock control subsystems that can
  * enable/disable clocking to our device.
  */
-#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_IMX
 static inline struct clk *caam_drv_identify_clk(struct device *dev,
                                                char *clk_name)
 {
-       return devm_clk_get(dev, clk_name);
+       return caam_imx ? devm_clk_get(dev, clk_name) : NULL;
 }
-#else
-static inline struct clk *caam_drv_identify_clk(struct device *dev,
-                                               char *clk_name)
-{
-       return NULL;
-}
-#endif
 
 /*
  * Descriptor to instantiate RNG State Handle 0 in normal mode and
@@ -430,6 +425,10 @@ static int caam_probe(struct platform_device *pdev)
 {
        int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
        u64 caam_id;
+       static const struct soc_device_attribute imx_soc[] = {
+               {.family = "Freescale i.MX"},
+               {},
+       };
        struct device *dev;
        struct device_node *nprop, *np;
        struct caam_ctrl __iomem *ctrl;
@@ -451,6 +450,8 @@ static int caam_probe(struct platform_device *pdev)
        dev_set_drvdata(dev, ctrlpriv);
        nprop = pdev->dev.of_node;
 
+       caam_imx = (bool)soc_device_match(imx_soc);
+
        /* Enable clocking */
        clk = caam_drv_identify_clk(&pdev->dev, "ipg");
        if (IS_ERR(clk)) {
index 2b5efff9ec3caa69a49bd48b1121aa680e08a2c1..17cfd23a38faa3fbe3152d5925821082f2c2dfb3 100644 (file)
@@ -67,6 +67,7 @@
  */
 
 extern bool caam_little_end;
+extern bool caam_imx;
 
 #define caam_to_cpu(len)                               \
 static inline u##len caam##len ## _to_cpu(u##len val)  \
@@ -154,13 +155,10 @@ static inline u64 rd_reg64(void __iomem *reg)
 #else /* CONFIG_64BIT */
 static inline void wr_reg64(void __iomem *reg, u64 data)
 {
-#ifndef CONFIG_CRYPTO_DEV_FSL_CAAM_IMX
-       if (caam_little_end) {
+       if (!caam_imx && caam_little_end) {
                wr_reg32((u32 __iomem *)(reg) + 1, data >> 32);
                wr_reg32((u32 __iomem *)(reg), data);
-       } else
-#endif
-       {
+       } else {
                wr_reg32((u32 __iomem *)(reg), data >> 32);
                wr_reg32((u32 __iomem *)(reg) + 1, data);
        }
@@ -168,41 +166,40 @@ static inline void wr_reg64(void __iomem *reg, u64 data)
 
 static inline u64 rd_reg64(void __iomem *reg)
 {
-#ifndef CONFIG_CRYPTO_DEV_FSL_CAAM_IMX
-       if (caam_little_end)
+       if (!caam_imx && caam_little_end)
                return ((u64)rd_reg32((u32 __iomem *)(reg) + 1) << 32 |
                        (u64)rd_reg32((u32 __iomem *)(reg)));
-       else
-#endif
-               return ((u64)rd_reg32((u32 __iomem *)(reg)) << 32 |
-                       (u64)rd_reg32((u32 __iomem *)(reg) + 1));
+
+       return ((u64)rd_reg32((u32 __iomem *)(reg)) << 32 |
+               (u64)rd_reg32((u32 __iomem *)(reg) + 1));
 }
 #endif /* CONFIG_64BIT  */
 
+static inline u64 cpu_to_caam_dma64(dma_addr_t value)
+{
+       if (caam_imx)
+               return (((u64)cpu_to_caam32(lower_32_bits(value)) << 32) |
+                        (u64)cpu_to_caam32(upper_32_bits(value)));
+
+       return cpu_to_caam64(value);
+}
+
+static inline u64 caam_dma64_to_cpu(u64 value)
+{
+       if (caam_imx)
+               return (((u64)caam32_to_cpu(lower_32_bits(value)) << 32) |
+                        (u64)caam32_to_cpu(upper_32_bits(value)));
+
+       return caam64_to_cpu(value);
+}
+
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-#ifdef CONFIG_SOC_IMX7D
-#define cpu_to_caam_dma(value) \
-               (((u64)cpu_to_caam32(lower_32_bits(value)) << 32) | \
-                 (u64)cpu_to_caam32(upper_32_bits(value)))
-#define caam_dma_to_cpu(value) \
-               (((u64)caam32_to_cpu(lower_32_bits(value)) << 32) | \
-                 (u64)caam32_to_cpu(upper_32_bits(value)))
-#else
-#define cpu_to_caam_dma(value) cpu_to_caam64(value)
-#define caam_dma_to_cpu(value) caam64_to_cpu(value)
-#endif /* CONFIG_SOC_IMX7D */
+#define cpu_to_caam_dma(value) cpu_to_caam_dma64(value)
+#define caam_dma_to_cpu(value) caam_dma64_to_cpu(value)
 #else
 #define cpu_to_caam_dma(value) cpu_to_caam32(value)
 #define caam_dma_to_cpu(value) caam32_to_cpu(value)
-#endif /* CONFIG_ARCH_DMA_ADDR_T_64BIT  */
-
-#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_IMX
-#define cpu_to_caam_dma64(value) \
-               (((u64)cpu_to_caam32(lower_32_bits(value)) << 32) | \
-                (u64)cpu_to_caam32(upper_32_bits(value)))
-#else
-#define cpu_to_caam_dma64(value) cpu_to_caam64(value)
-#endif
+#endif /* CONFIG_ARCH_DMA_ADDR_T_64BIT */
 
 /*
  * jr_outentry
index d2207ac5ba19cdd357ab5bbae3a128d1fa92183e..5438552bc6d783b57a23763e64c59afb90c340ae 100644 (file)
@@ -386,7 +386,7 @@ static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm)
        struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
        struct safexcel_crypto_priv *priv = ctx->priv;
        struct skcipher_request req;
-       struct safexcel_inv_result result = { 0 };
+       struct safexcel_inv_result result = {};
        int ring = ctx->base.ring;
 
        memset(&req, 0, sizeof(struct skcipher_request));
index 3f819399cd95519a9956ed1d3ecba76fa2aa62b4..3980f946874fa08b64288b5d8b04bcac9134a0ad 100644 (file)
@@ -419,7 +419,7 @@ static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
        struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
        struct safexcel_crypto_priv *priv = ctx->priv;
        struct ahash_request req;
-       struct safexcel_inv_result result = { 0 };
+       struct safexcel_inv_result result = {};
        int ring = ctx->base.ring;
 
        memset(&req, 0, sizeof(struct ahash_request));
index 79791c690858fb1cea4aa057fb726efe46160df9..dff88838dce762c33ca7e898420f051c3a2f80cb 100644 (file)
@@ -1756,9 +1756,9 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
                req_ctx->swinit = 0;
        } else {
                desc->ptr[1] = zero_entry;
-               /* Indicate next op is not the first. */
-               req_ctx->first = 0;
        }
+       /* Indicate next op is not the first. */
+       req_ctx->first = 0;
 
        /* HMAC key */
        if (ctx->keylen)
@@ -1769,7 +1769,7 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
 
        sg_count = edesc->src_nents ?: 1;
        if (is_sec1 && sg_count > 1)
-               sg_copy_to_buffer(areq->src, sg_count, edesc->buf, length);
+               sg_copy_to_buffer(req_ctx->psrc, sg_count, edesc->buf, length);
        else
                sg_count = dma_map_sg(dev, req_ctx->psrc, sg_count,
                                      DMA_TO_DEVICE);
@@ -3057,7 +3057,8 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
                t_alg->algt.alg.hash.final = ahash_final;
                t_alg->algt.alg.hash.finup = ahash_finup;
                t_alg->algt.alg.hash.digest = ahash_digest;
-               t_alg->algt.alg.hash.setkey = ahash_setkey;
+               if (!strncmp(alg->cra_name, "hmac", 4))
+                       t_alg->algt.alg.hash.setkey = ahash_setkey;
                t_alg->algt.alg.hash.import = ahash_import;
                t_alg->algt.alg.hash.export = ahash_export;
 
index d228f5a990449f0b2c28314c972db2664c6bc1cd..dbbe986f90f29ffb6c77662866e336d8130d1af2 100644 (file)
@@ -636,7 +636,194 @@ static void gfx_v6_0_tiling_mode_table_init(struct amdgpu_device *adev)
                                NUM_BANKS(ADDR_SURF_2_BANK);
                for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
                        WREG32(mmGB_TILE_MODE0 + reg_offset, tilemode[reg_offset]);
-       } else if (adev->asic_type == CHIP_OLAND || adev->asic_type == CHIP_HAINAN) {
+       } else if (adev->asic_type == CHIP_OLAND) {
+               tilemode[0] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4);
+               tilemode[1] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4);
+               tilemode[2] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4);
+               tilemode[3] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4);
+               tilemode[4] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[5] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(split_equal_to_row_size) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[6] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(split_equal_to_row_size) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[7] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(split_equal_to_row_size) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4);
+               tilemode[8] =   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[9] =   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[10] =  MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4);
+               tilemode[11] =  MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[12] =  MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[13] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[14] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[15] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[16] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[17] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+                               TILE_SPLIT(split_equal_to_row_size) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[21] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[22] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4);
+               tilemode[23] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[24] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+                               NUM_BANKS(ADDR_SURF_16_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2);
+               tilemode[25] =  MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+                               ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                               PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+                               NUM_BANKS(ADDR_SURF_8_BANK) |
+                               BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1);
+               for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+                       WREG32(mmGB_TILE_MODE0 + reg_offset, tilemode[reg_offset]);
+       } else if (adev->asic_type == CHIP_HAINAN) {
                tilemode[0] =   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
                                ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                PIPE_CONFIG(ADDR_SURF_P2) |
index e4a8c2e52cb2c14ab566d015b178a2e6bd243cac..660b3fbade4194f796ebe0be8e4fc7f7e9c46109 100644 (file)
@@ -892,6 +892,8 @@ static int kfd_ioctl_get_tile_config(struct file *filep,
        int err = 0;
 
        dev = kfd_device_by_id(args->gpu_id);
+       if (!dev)
+               return -EINVAL;
 
        dev->kfd2kgd->get_tile_config(dev->kgd, &config);
 
index 5979158c3f7b93e96627af2c03cd814228b0fe01..944abfad39c1f67447ca720d5e47c4b086336a82 100644 (file)
@@ -292,7 +292,10 @@ static int create_signal_event(struct file *devkfd,
                                struct kfd_event *ev)
 {
        if (p->signal_event_count == KFD_SIGNAL_EVENT_LIMIT) {
-               pr_warn("Signal event wasn't created because limit was reached\n");
+               if (!p->signal_event_limit_reached) {
+                       pr_warn("Signal event wasn't created because limit was reached\n");
+                       p->signal_event_limit_reached = true;
+               }
                return -ENOMEM;
        }
 
index 681b639f51330b78af84854880cae988fd90b252..ed71ad40e8f797ca3c7b7d4f129f5e9fda382d27 100644 (file)
@@ -183,8 +183,8 @@ static void uninitialize(struct kernel_queue *kq)
 {
        if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ)
                kq->mqd->destroy_mqd(kq->mqd,
-                                       NULL,
-                                       false,
+                                       kq->queue->mqd,
+                                       KFD_PREEMPT_TYPE_WAVEFRONT_RESET,
                                        QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS,
                                        kq->queue->pipe,
                                        kq->queue->queue);
@@ -210,6 +210,11 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
        uint32_t wptr, rptr;
        unsigned int *queue_address;
 
+       /* When rptr == wptr, the buffer is empty.
+        * When rptr == wptr + 1, the buffer is full.
+        * It is always rptr that advances to the position of wptr, rather than
+        * the opposite. So we can only use up to queue_size_dwords - 1 dwords.
+        */
        rptr = *kq->rptr_kernel;
        wptr = *kq->wptr_kernel;
        queue_address = (unsigned int *)kq->pq_kernel_addr;
@@ -219,11 +224,10 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
        pr_debug("wptr: %d\n", wptr);
        pr_debug("queue_address 0x%p\n", queue_address);
 
-       available_size = (rptr - 1 - wptr + queue_size_dwords) %
+       available_size = (rptr + queue_size_dwords - 1 - wptr) %
                                                        queue_size_dwords;
 
-       if (packet_size_in_dwords >= queue_size_dwords ||
-                       packet_size_in_dwords >= available_size) {
+       if (packet_size_in_dwords > available_size) {
                /*
                 * make sure calling functions know
                 * acquire_packet_buffer() failed
@@ -233,6 +237,14 @@ static int acquire_packet_buffer(struct kernel_queue *kq,
        }
 
        if (wptr + packet_size_in_dwords >= queue_size_dwords) {
+               /* make sure after rolling back to position 0, there is
+                * still enough space.
+                */
+               if (packet_size_in_dwords >= rptr) {
+                       *buffer_ptr = NULL;
+                       return -ENOMEM;
+               }
+               /* fill nops, roll back and start at position 0 */
                while (wptr > 0) {
                        queue_address[wptr] = kq->nop_packet;
                        wptr = (wptr + 1) % queue_size_dwords;
index b397ec726400c2a52533356363b36bfd275dfb39..b87e96cee5facfea112a874f4e69bfad52f3b70b 100644 (file)
@@ -521,6 +521,7 @@ struct kfd_process {
        struct list_head signal_event_pages;
        u32 next_nonsignal_event_id;
        size_t signal_event_count;
+       bool signal_event_limit_reached;
 };
 
 /**
index 1cae95e2b13adedfb19760279861fae827d057a7..03bec765b03d949de8bdac3cd8db62f8c684c92a 100644 (file)
@@ -143,7 +143,6 @@ int pqm_create_queue(struct process_queue_manager *pqm,
        int num_queues = 0;
        struct queue *cur;
 
-       memset(&q_properties, 0, sizeof(struct queue_properties));
        memcpy(&q_properties, properties, sizeof(struct queue_properties));
        q = NULL;
        kq = NULL;
index 5a634594a6cea2d2be20e19a0e359229a860775c..57881167ccd22c9c16df18e1d93401edef2e1f82 100644 (file)
@@ -551,12 +551,15 @@ static const struct etnaviv_gem_ops etnaviv_gem_shmem_ops = {
 void etnaviv_gem_free_object(struct drm_gem_object *obj)
 {
        struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+       struct etnaviv_drm_private *priv = obj->dev->dev_private;
        struct etnaviv_vram_mapping *mapping, *tmp;
 
        /* object should not be active */
        WARN_ON(is_active(etnaviv_obj));
 
+       mutex_lock(&priv->gem_lock);
        list_del(&etnaviv_obj->gem_node);
+       mutex_unlock(&priv->gem_lock);
 
        list_for_each_entry_safe(mapping, tmp, &etnaviv_obj->vram_list,
                                 obj_node) {
index 026ef4e02f85cab130586c5c0b8c9b97bd0101bb..46dfe0737f438d37e4e65dec320e9a7e773e3856 100644 (file)
@@ -445,8 +445,10 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
        cmdbuf->user_size = ALIGN(args->stream_size, 8);
 
        ret = etnaviv_gpu_submit(gpu, submit, cmdbuf);
-       if (ret == 0)
-               cmdbuf = NULL;
+       if (ret)
+               goto out;
+
+       cmdbuf = NULL;
 
        if (args->flags & ETNA_SUBMIT_FENCE_FD_OUT) {
                /*
index 730b8d9db18704c42346b9553c8d7ab737493392..6be5b53c3b279f42ee6dbcc445173fa539721ce5 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/iopoll.h>
+#include <linux/irq.h>
 #include <linux/mfd/syscon.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
index b1f7299600f040947240618cf2cfc262d1847b70..e651a58c18cf2d5b743439776dd62d50b64f8a7a 100644 (file)
@@ -168,23 +168,19 @@ static struct drm_driver exynos_drm_driver = {
 static int exynos_drm_suspend(struct device *dev)
 {
        struct drm_device *drm_dev = dev_get_drvdata(dev);
-       struct drm_connector *connector;
-       struct drm_connector_list_iter conn_iter;
+       struct exynos_drm_private *private = drm_dev->dev_private;
 
        if (pm_runtime_suspended(dev) || !drm_dev)
                return 0;
 
-       drm_connector_list_iter_begin(drm_dev, &conn_iter);
-       drm_for_each_connector_iter(connector, &conn_iter) {
-               int old_dpms = connector->dpms;
-
-               if (connector->funcs->dpms)
-                       connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
-
-               /* Set the old mode back to the connector for resume */
-               connector->dpms = old_dpms;
+       drm_kms_helper_poll_disable(drm_dev);
+       exynos_drm_fbdev_suspend(drm_dev);
+       private->suspend_state = drm_atomic_helper_suspend(drm_dev);
+       if (IS_ERR(private->suspend_state)) {
+               exynos_drm_fbdev_resume(drm_dev);
+               drm_kms_helper_poll_enable(drm_dev);
+               return PTR_ERR(private->suspend_state);
        }
-       drm_connector_list_iter_end(&conn_iter);
 
        return 0;
 }
@@ -192,22 +188,14 @@ static int exynos_drm_suspend(struct device *dev)
 static int exynos_drm_resume(struct device *dev)
 {
        struct drm_device *drm_dev = dev_get_drvdata(dev);
-       struct drm_connector *connector;
-       struct drm_connector_list_iter conn_iter;
+       struct exynos_drm_private *private = drm_dev->dev_private;
 
        if (pm_runtime_suspended(dev) || !drm_dev)
                return 0;
 
-       drm_connector_list_iter_begin(drm_dev, &conn_iter);
-       drm_for_each_connector_iter(connector, &conn_iter) {
-               if (connector->funcs->dpms) {
-                       int dpms = connector->dpms;
-
-                       connector->dpms = DRM_MODE_DPMS_OFF;
-                       connector->funcs->dpms(connector, dpms);
-               }
-       }
-       drm_connector_list_iter_end(&conn_iter);
+       drm_atomic_helper_resume(drm_dev, private->suspend_state);
+       exynos_drm_fbdev_resume(drm_dev);
+       drm_kms_helper_poll_enable(drm_dev);
 
        return 0;
 }
index cf131c2aa23e431f13a44fe1985bad58c32da250..f8bae4cb4823653562de92a20bec51f87747d07f 100644 (file)
@@ -202,6 +202,7 @@ struct drm_exynos_file_private {
  */
 struct exynos_drm_private {
        struct drm_fb_helper *fb_helper;
+       struct drm_atomic_state *suspend_state;
 
        struct device *dma_dev;
        void *mapping;
index c3a068409b484fda04bbf837626f011beb875c1f..dfb66ecf417b5c8ba9bd26b8966a52a5f14b4aaa 100644 (file)
@@ -18,6 +18,8 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/exynos_drm.h>
 
+#include <linux/console.h>
+
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_fbdev.h"
@@ -285,3 +287,21 @@ void exynos_drm_output_poll_changed(struct drm_device *dev)
 
        drm_fb_helper_hotplug_event(fb_helper);
 }
+
+void exynos_drm_fbdev_suspend(struct drm_device *dev)
+{
+       struct exynos_drm_private *private = dev->dev_private;
+
+       console_lock();
+       drm_fb_helper_set_suspend(private->fb_helper, 1);
+       console_unlock();
+}
+
+void exynos_drm_fbdev_resume(struct drm_device *dev)
+{
+       struct exynos_drm_private *private = dev->dev_private;
+
+       console_lock();
+       drm_fb_helper_set_suspend(private->fb_helper, 0);
+       console_unlock();
+}
index 330eef87f7180b1b726ff41933874a6568b0474d..645d1bb7f665faed0dfa30bf3ab36c090a2c1c1f 100644 (file)
@@ -21,6 +21,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev);
 void exynos_drm_fbdev_fini(struct drm_device *dev);
 void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
 void exynos_drm_output_poll_changed(struct drm_device *dev);
+void exynos_drm_fbdev_suspend(struct drm_device *drm);
+void exynos_drm_fbdev_resume(struct drm_device *drm);
 
 #else
 
@@ -39,6 +41,14 @@ static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
 
 #define exynos_drm_output_poll_changed (NULL)
 
+static inline void exynos_drm_fbdev_suspend(struct drm_device *drm)
+{
+}
+
+static inline void exynos_drm_fbdev_resume(struct drm_device *drm)
+{
+}
+
 #endif
 
 #endif
index 214fa5e51963898ee5288f98d536681cdbebdcd6..0109ff40b1db2a95da6997e982fe0adaf4496196 100644 (file)
@@ -944,22 +944,27 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder,
        struct drm_device *dev = encoder->dev;
        struct drm_connector *connector;
        struct drm_display_mode *m;
+       struct drm_connector_list_iter conn_iter;
        int mode_ok;
 
        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_connector_list_iter_begin(dev, &conn_iter);
+       drm_for_each_connector_iter(connector, &conn_iter) {
                if (connector->encoder == encoder)
                        break;
        }
+       if (connector)
+               drm_connector_get(connector);
+       drm_connector_list_iter_end(&conn_iter);
 
-       if (connector->encoder != encoder)
+       if (!connector)
                return true;
 
        mode_ok = hdmi_mode_valid(connector, adjusted_mode);
 
        if (mode_ok == MODE_OK)
-               return true;
+               goto cleanup;
 
        /*
         * Find the most suitable mode and copy it to adjusted_mode.
@@ -979,6 +984,9 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder,
                }
        }
 
+cleanup:
+       drm_connector_put(connector);
+
        return true;
 }
 
index 40af17ec6312533d4080cc1581faa4683a0405b9..ff3154fe6588b6aa48d4c2618d65f1f2d912b137 100644 (file)
@@ -197,78 +197,65 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu,
 static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset,
        void *p_data, unsigned int bytes)
 {
-       unsigned int bar_index =
-               (rounddown(offset, 8) % PCI_BASE_ADDRESS_0) / 8;
        u32 new = *(u32 *)(p_data);
        bool lo = IS_ALIGNED(offset, 8);
        u64 size;
        int ret = 0;
        bool mmio_enabled =
                vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY;
+       struct intel_vgpu_pci_bar *bars = vgpu->cfg_space.bar;
 
-       if (WARN_ON(bar_index >= INTEL_GVT_PCI_BAR_MAX))
-               return -EINVAL;
-
+       /*
+        * Power-up software can determine how much address
+        * space the device requires by writing a value of
+        * all 1's to the register and then reading the value
+        * back. The device will return 0's in all don't-care
+        * address bits.
+        */
        if (new == 0xffffffff) {
-               /*
-                * Power-up software can determine how much address
-                * space the device requires by writing a value of
-                * all 1's to the register and then reading the value
-                * back. The device will return 0's in all don't-care
-                * address bits.
-                */
-               size = vgpu->cfg_space.bar[bar_index].size;
-               if (lo) {
-                       new = rounddown(new, size);
-               } else {
-                       u32 val = vgpu_cfg_space(vgpu)[rounddown(offset, 8)];
-                       /* for 32bit mode bar it returns all-0 in upper 32
-                        * bit, for 64bit mode bar it will calculate the
-                        * size with lower 32bit and return the corresponding
-                        * value
+               switch (offset) {
+               case PCI_BASE_ADDRESS_0:
+               case PCI_BASE_ADDRESS_1:
+                       size = ~(bars[INTEL_GVT_PCI_BAR_GTTMMIO].size -1);
+                       intel_vgpu_write_pci_bar(vgpu, offset,
+                                               size >> (lo ? 0 : 32), lo);
+                       /*
+                        * Untrap the BAR, since guest hasn't configured a
+                        * valid GPA
                         */
-                       if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
-                               new &= (~(size-1)) >> 32;
-                       else
-                               new = 0;
-               }
-               /*
-                * Unmapp & untrap the BAR, since guest hasn't configured a
-                * valid GPA
-                */
-               switch (bar_index) {
-               case INTEL_GVT_PCI_BAR_GTTMMIO:
                        ret = trap_gttmmio(vgpu, false);
                        break;
-               case INTEL_GVT_PCI_BAR_APERTURE:
+               case PCI_BASE_ADDRESS_2:
+               case PCI_BASE_ADDRESS_3:
+                       size = ~(bars[INTEL_GVT_PCI_BAR_APERTURE].size -1);
+                       intel_vgpu_write_pci_bar(vgpu, offset,
+                                               size >> (lo ? 0 : 32), lo);
                        ret = map_aperture(vgpu, false);
                        break;
+               default:
+                       /* Unimplemented BARs */
+                       intel_vgpu_write_pci_bar(vgpu, offset, 0x0, false);
                }
-               intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
        } else {
-               /*
-                * Unmapp & untrap the old BAR first, since guest has
-                * re-configured the BAR
-                */
-               switch (bar_index) {
-               case INTEL_GVT_PCI_BAR_GTTMMIO:
-                       ret = trap_gttmmio(vgpu, false);
+               switch (offset) {
+               case PCI_BASE_ADDRESS_0:
+               case PCI_BASE_ADDRESS_1:
+                       /*
+                        * Untrap the old BAR first, since guest has
+                        * re-configured the BAR
+                        */
+                       trap_gttmmio(vgpu, false);
+                       intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
+                       ret = trap_gttmmio(vgpu, mmio_enabled);
                        break;
-               case INTEL_GVT_PCI_BAR_APERTURE:
-                       ret = map_aperture(vgpu, false);
+               case PCI_BASE_ADDRESS_2:
+               case PCI_BASE_ADDRESS_3:
+                       map_aperture(vgpu, false);
+                       intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
+                       ret = map_aperture(vgpu, mmio_enabled);
                        break;
-               }
-               intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
-               /* Track the new BAR */
-               if (mmio_enabled) {
-                       switch (bar_index) {
-                       case INTEL_GVT_PCI_BAR_GTTMMIO:
-                               ret = trap_gttmmio(vgpu, true);
-                               break;
-                       case INTEL_GVT_PCI_BAR_APERTURE:
-                               ret = map_aperture(vgpu, true);
-                               break;
-                       }
+               default:
+                       intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
                }
        }
        return ret;
@@ -299,10 +286,7 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
        }
 
        switch (rounddown(offset, 4)) {
-       case PCI_BASE_ADDRESS_0:
-       case PCI_BASE_ADDRESS_1:
-       case PCI_BASE_ADDRESS_2:
-       case PCI_BASE_ADDRESS_3:
+       case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5:
                if (WARN_ON(!IS_ALIGNED(offset, 4)))
                        return -EINVAL;
                return emulate_pci_bar_write(vgpu, offset, p_data, bytes);
@@ -344,7 +328,6 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
        struct intel_gvt *gvt = vgpu->gvt;
        const struct intel_gvt_device_info *info = &gvt->device_info;
        u16 *gmch_ctl;
-       int i;
 
        memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
               info->cfg_space_size);
@@ -371,13 +354,13 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
         */
        memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
        memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
+       memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_4, 0, 8);
        memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
 
-       for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {
-               vgpu->cfg_space.bar[i].size = pci_resource_len(
-                                             gvt->dev_priv->drm.pdev, i * 2);
-               vgpu->cfg_space.bar[i].tracked = false;
-       }
+       vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size =
+                               pci_resource_len(gvt->dev_priv->drm.pdev, 0);
+       vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size =
+                               pci_resource_len(gvt->dev_priv->drm.pdev, 2);
 }
 
 /**
index e21ce9c18b6eee10ad8556d5fb310cd544987c88..b63893eeca73ddf78070bbecf055f6560f8636b7 100644 (file)
@@ -839,7 +839,6 @@ static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
                                                                pipe);
        int position;
        int vbl_start, vbl_end, hsync_start, htotal, vtotal;
-       bool in_vbl = true;
        unsigned long irqflags;
 
        if (WARN_ON(!mode->crtc_clock)) {
@@ -922,8 +921,6 @@ static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 
-       in_vbl = position >= vbl_start && position < vbl_end;
-
        /*
         * While in vblank, position will be negative
         * counting up towards 0 at vbl_end. And outside
index f17275519484bd8f598401269959c038fe139171..00cd17c76fdcc3bc5427f53bf45e416d66400655 100644 (file)
@@ -14030,7 +14030,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
 
                if (mode_cmd->handles[i] != mode_cmd->handles[0]) {
                        DRM_DEBUG_KMS("bad plane %d handle\n", i);
-                       return -EINVAL;
+                       goto err;
                }
 
                stride_alignment = intel_fb_stride_alignment(fb, i);
index f0c11aec5ea5c99933f4243d9ce408692cd66cda..7442891762be4e486f8e1bd4c4f9a365819d7c88 100644 (file)
@@ -892,8 +892,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder,
                              struct intel_crtc_state *old_crtc_state,
                              struct drm_connector_state *old_conn_state)
 {
-       struct drm_device *dev = encoder->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        enum port port;
 
@@ -902,15 +900,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder,
        intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_OFF);
        intel_panel_disable_backlight(old_conn_state);
 
-       /*
-        * Disable Device ready before the port shutdown in order
-        * to avoid split screen
-        */
-       if (IS_BROXTON(dev_priv)) {
-               for_each_dsi_port(port, intel_dsi->ports)
-                       I915_WRITE(MIPI_DEVICE_READY(port), 0);
-       }
-
        /*
         * According to the spec we should send SHUTDOWN before
         * MIPI_SEQ_DISPLAY_OFF only for v3+ VBTs, but field testing
index a17b1de7d7e0edf9ec2f605a2d257227587599ba..3b1c5d783ee7ccf12fc9d0cda009ab695fef4e57 100644 (file)
@@ -1699,6 +1699,8 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
        if (!panel->backlight.max)
                return -ENODEV;
 
+       panel->backlight.min = get_backlight_min_vbt(connector);
+
        val = bxt_get_backlight(connector);
        val = intel_panel_compute_brightness(connector, val);
        panel->backlight.level = clamp(val, panel->backlight.min,
@@ -1735,6 +1737,8 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused)
        if (!panel->backlight.max)
                return -ENODEV;
 
+       panel->backlight.min = get_backlight_min_vbt(connector);
+
        val = bxt_get_backlight(connector);
        val = intel_panel_compute_brightness(connector, val);
        panel->backlight.level = clamp(val, panel->backlight.min,
index 14c5613b4388a839461915fc448d4772422861a3..afbf50d0c08fa1c89c49120717b7a51cb05d5b98 100644 (file)
@@ -509,23 +509,25 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
            .y2 = qfb->base.height
        };
 
-       if (!old_state->fb) {
-               qxl_io_log(qdev,
-                          "create primary fb: %dx%d,%d,%d\n",
-                          bo->surf.width, bo->surf.height,
-                          bo->surf.stride, bo->surf.format);
+       if (old_state->fb) {
+               qfb_old = to_qxl_framebuffer(old_state->fb);
+               bo_old = gem_to_qxl_bo(qfb_old->obj);
+       } else {
+               bo_old = NULL;
+       }
 
-               qxl_io_create_primary(qdev, 0, bo);
-               bo->is_primary = true;
+       if (bo == bo_old)
                return;
 
-       } else {
-               qfb_old = to_qxl_framebuffer(old_state->fb);
-               bo_old = gem_to_qxl_bo(qfb_old->obj);
+       if (bo_old && bo_old->is_primary) {
+               qxl_io_destroy_primary(qdev);
                bo_old->is_primary = false;
        }
 
-       bo->is_primary = true;
+       if (!bo->is_primary) {
+               qxl_io_create_primary(qdev, 0, bo);
+               bo->is_primary = true;
+       }
        qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
 }
 
@@ -534,13 +536,15 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane,
 {
        struct qxl_device *qdev = plane->dev->dev_private;
 
-       if (old_state->fb)
-       {       struct qxl_framebuffer *qfb =
+       if (old_state->fb) {
+               struct qxl_framebuffer *qfb =
                        to_qxl_framebuffer(old_state->fb);
                struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
 
-               qxl_io_destroy_primary(qdev);
-               bo->is_primary = false;
+               if (bo->is_primary) {
+                       qxl_io_destroy_primary(qdev);
+                       bo->is_primary = false;
+               }
        }
 }
 
@@ -698,14 +702,15 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
        struct drm_gem_object *obj;
        struct qxl_bo *user_bo;
 
-       if (!plane->state->fb) {
-               /* we never executed prepare_fb, so there's nothing to
+       if (!old_state->fb) {
+               /*
+                * we never executed prepare_fb, so there's nothing to
                 * unpin.
                 */
                return;
        }
 
-       obj = to_qxl_framebuffer(plane->state->fb)->obj;
+       obj = to_qxl_framebuffer(old_state->fb)->obj;
        user_bo = gem_to_qxl_bo(obj);
        qxl_bo_unpin(user_bo);
 }
index 997131d58c7f639f8dbb765e51433a35a7da27ba..ffc10cadcf34ccb79a7d09ae253b4a2dffda7cfe 100644 (file)
@@ -1663,7 +1663,7 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend,
        radeon_agp_suspend(rdev);
 
        pci_save_state(dev->pdev);
-       if (freeze && rdev->family >= CHIP_CEDAR) {
+       if (freeze && rdev->family >= CHIP_CEDAR && !(rdev->flags & RADEON_IS_IGP)) {
                rdev->asic->asic_reset(rdev, true);
                pci_restore_state(dev->pdev);
        } else if (suspend) {
index 06f05302ee75e33b2a05f9c468b1a3bbd60619be..882d85db90539ae1b00e194a0cae43bf8fb4918d 100644 (file)
@@ -26,7 +26,7 @@ config DRM_SUN4I_HDMI_CEC
        bool "Allwinner A10 HDMI CEC Support"
        depends on DRM_SUN4I_HDMI
        select CEC_CORE
-       depends on CEC_PIN
+       select CEC_PIN
        help
          Choose this option if you have an Allwinner SoC with an HDMI
          controller and want to use CEC.
index 1457750988da4930792eceb3e543f211d66f84f7..a1f8cba251a245af7227d853da784518d19d405d 100644 (file)
@@ -15,7 +15,7 @@
 #include <drm/drm_connector.h>
 #include <drm/drm_encoder.h>
 
-#include <media/cec.h>
+#include <media/cec-pin.h>
 
 #define SUN4I_HDMI_CTRL_REG            0x004
 #define SUN4I_HDMI_CTRL_ENABLE                 BIT(31)
index e9b7cdad5c4c1beac73bca274321cc57280006bd..5a1ab4046e926fefe4cb6d73d2c3ebe031eb45bb 100644 (file)
@@ -63,6 +63,6 @@ DEFINE_EVENT(register_access, sor_readl,
 
 /* This part must be outside protection */
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/tegra
 #define TRACE_INCLUDE_FILE trace
 #include <trace/define_trace.h>
index 70ad19c4c73e77da961ffccd9958887dcead8027..88bdafb297f5fe9f722c7a8edee27554ea3b6862 100644 (file)
@@ -432,8 +432,10 @@ int ib_create_qp_security(struct ib_qp *qp, struct ib_device *dev)
        atomic_set(&qp->qp_sec->error_list_count, 0);
        init_completion(&qp->qp_sec->error_complete);
        ret = security_ib_alloc_security(&qp->qp_sec->security);
-       if (ret)
+       if (ret) {
                kfree(qp->qp_sec);
+               qp->qp_sec = NULL;
+       }
 
        return ret;
 }
index 4ab30d832ac5b8a5ac4994b9c4f0b3f3802e019c..52a2cf2d83aaf483944ad9720e55121f2adb6484 100644 (file)
@@ -3869,15 +3869,15 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
        resp.raw_packet_caps = attr.raw_packet_caps;
        resp.response_length += sizeof(resp.raw_packet_caps);
 
-       if (ucore->outlen < resp.response_length + sizeof(resp.xrq_caps))
+       if (ucore->outlen < resp.response_length + sizeof(resp.tm_caps))
                goto end;
 
-       resp.xrq_caps.max_rndv_hdr_size = attr.xrq_caps.max_rndv_hdr_size;
-       resp.xrq_caps.max_num_tags      = attr.xrq_caps.max_num_tags;
-       resp.xrq_caps.max_ops           = attr.xrq_caps.max_ops;
-       resp.xrq_caps.max_sge           = attr.xrq_caps.max_sge;
-       resp.xrq_caps.flags             = attr.xrq_caps.flags;
-       resp.response_length += sizeof(resp.xrq_caps);
+       resp.tm_caps.max_rndv_hdr_size  = attr.tm_caps.max_rndv_hdr_size;
+       resp.tm_caps.max_num_tags       = attr.tm_caps.max_num_tags;
+       resp.tm_caps.max_ops            = attr.tm_caps.max_ops;
+       resp.tm_caps.max_sge            = attr.tm_caps.max_sge;
+       resp.tm_caps.flags              = attr.tm_caps.flags;
+       resp.response_length += sizeof(resp.tm_caps);
 end:
        err = ib_copy_to_udata(ucore, &resp, resp.response_length);
        return err;
index ee9e27dc799b50ead4663cd5fd13c94a3ac020d4..de57d6c11a25428d96e8bcb4868fc19794cc374d 100644 (file)
@@ -1646,7 +1646,7 @@ static bool is_valid_mcast_lid(struct ib_qp *qp, u16 lid)
         */
        if (!ib_query_qp(qp, &attr, IB_QP_STATE | IB_QP_PORT, &init_attr)) {
                if (attr.qp_state >= IB_QPS_INIT) {
-                       if (qp->device->get_link_layer(qp->device, attr.port_num) !=
+                       if (rdma_port_get_link_layer(qp->device, attr.port_num) !=
                            IB_LINK_LAYER_INFINIBAND)
                                return true;
                        goto lid_check;
@@ -1655,7 +1655,7 @@ static bool is_valid_mcast_lid(struct ib_qp *qp, u16 lid)
 
        /* Can't get a quick answer, iterate over all ports */
        for (port = 0; port < qp->device->phys_port_cnt; port++)
-               if (qp->device->get_link_layer(qp->device, port) !=
+               if (rdma_port_get_link_layer(qp->device, port) !=
                    IB_LINK_LAYER_INFINIBAND)
                        num_eth_ports++;
 
index b3ad37fec578be497cc55e3dc48552e62d71c595..ecbac91b2e1441acf4529d6d40fa4256892349c0 100644 (file)
@@ -93,11 +93,13 @@ struct bnxt_re_dev {
        struct ib_device                ibdev;
        struct list_head                list;
        unsigned long                   flags;
-#define BNXT_RE_FLAG_NETDEV_REGISTERED 0
-#define BNXT_RE_FLAG_IBDEV_REGISTERED  1
-#define BNXT_RE_FLAG_GOT_MSIX          2
-#define BNXT_RE_FLAG_RCFW_CHANNEL_EN   8
-#define BNXT_RE_FLAG_QOS_WORK_REG      16
+#define BNXT_RE_FLAG_NETDEV_REGISTERED         0
+#define BNXT_RE_FLAG_IBDEV_REGISTERED          1
+#define BNXT_RE_FLAG_GOT_MSIX                  2
+#define BNXT_RE_FLAG_HAVE_L2_REF               3
+#define BNXT_RE_FLAG_RCFW_CHANNEL_EN           4
+#define BNXT_RE_FLAG_QOS_WORK_REG              5
+#define BNXT_RE_FLAG_TASK_IN_PROG              6
        struct net_device               *netdev;
        unsigned int                    version, major, minor;
        struct bnxt_en_dev              *en_dev;
@@ -108,6 +110,8 @@ struct bnxt_re_dev {
 
        struct delayed_work             worker;
        u8                              cur_prio_map;
+       u8                              active_speed;
+       u8                              active_width;
 
        /* FP Notification Queue (CQ & SRQ) */
        struct tasklet_struct           nq_task;
index 01eee15bbd6598fa6ae103aa1b86a81023e67f1d..0d89621d9fe8ed81b0d28c031d48ffcacb31fdfd 100644 (file)
@@ -259,14 +259,9 @@ int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num,
        port_attr->sm_sl = 0;
        port_attr->subnet_timeout = 0;
        port_attr->init_type_reply = 0;
-       /* call the underlying netdev's ethtool hooks to query speed settings
-        * for which we acquire rtnl_lock _only_ if it's registered with
-        * IB stack to avoid race in the NETDEV_UNREG path
-        */
-       if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags))
-               if (ib_get_eth_speed(ibdev, port_num, &port_attr->active_speed,
-                                    &port_attr->active_width))
-                       return -EINVAL;
+       port_attr->active_speed = rdev->active_speed;
+       port_attr->active_width = rdev->active_width;
+
        return 0;
 }
 
@@ -319,6 +314,7 @@ int bnxt_re_del_gid(struct ib_device *ibdev, u8 port_num,
        struct bnxt_re_gid_ctx *ctx, **ctx_tbl;
        struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
        struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
+       struct bnxt_qplib_gid *gid_to_del;
 
        /* Delete the entry from the hardware */
        ctx = *context;
@@ -328,11 +324,25 @@ int bnxt_re_del_gid(struct ib_device *ibdev, u8 port_num,
        if (sgid_tbl && sgid_tbl->active) {
                if (ctx->idx >= sgid_tbl->max)
                        return -EINVAL;
+               gid_to_del = &sgid_tbl->tbl[ctx->idx];
+               /* DEL_GID is called in WQ context(netdevice_event_work_handler)
+                * or via the ib_unregister_device path. In the former case QP1
+                * may not be destroyed yet, in which case just return as FW
+                * needs that entry to be present and will fail it's deletion.
+                * We could get invoked again after QP1 is destroyed OR get an
+                * ADD_GID call with a different GID value for the same index
+                * where we issue MODIFY_GID cmd to update the GID entry -- TBD
+                */
+               if (ctx->idx == 0 &&
+                   rdma_link_local_addr((struct in6_addr *)gid_to_del) &&
+                   ctx->refcnt == 1 && rdev->qp1_sqp) {
+                       dev_dbg(rdev_to_dev(rdev),
+                               "Trying to delete GID0 while QP1 is alive\n");
+                       return -EFAULT;
+               }
                ctx->refcnt--;
                if (!ctx->refcnt) {
-                       rc = bnxt_qplib_del_sgid(sgid_tbl,
-                                                &sgid_tbl->tbl[ctx->idx],
-                                                true);
+                       rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del, true);
                        if (rc) {
                                dev_err(rdev_to_dev(rdev),
                                        "Failed to remove GID: %#x", rc);
@@ -816,6 +826,8 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp)
 
                kfree(rdev->sqp_ah);
                kfree(rdev->qp1_sqp);
+               rdev->qp1_sqp = NULL;
+               rdev->sqp_ah = NULL;
        }
 
        if (!IS_ERR_OR_NULL(qp->rumem))
@@ -1436,11 +1448,14 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
                qp->qplib_qp.modify_flags |=
                                CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
                qp->qplib_qp.path_mtu = __from_ib_mtu(qp_attr->path_mtu);
+               qp->qplib_qp.mtu = ib_mtu_enum_to_int(qp_attr->path_mtu);
        } else if (qp_attr->qp_state == IB_QPS_RTR) {
                qp->qplib_qp.modify_flags |=
                        CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
                qp->qplib_qp.path_mtu =
                        __from_ib_mtu(iboe_get_mtu(rdev->netdev->mtu));
+               qp->qplib_qp.mtu =
+                       ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
        }
 
        if (qp_attr_mask & IB_QP_TIMEOUT) {
@@ -1551,43 +1566,46 @@ int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
 {
        struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
        struct bnxt_re_dev *rdev = qp->rdev;
-       struct bnxt_qplib_qp qplib_qp;
+       struct bnxt_qplib_qp *qplib_qp;
        int rc;
 
-       memset(&qplib_qp, 0, sizeof(struct bnxt_qplib_qp));
-       qplib_qp.id = qp->qplib_qp.id;
-       qplib_qp.ah.host_sgid_index = qp->qplib_qp.ah.host_sgid_index;
+       qplib_qp = kzalloc(sizeof(*qplib_qp), GFP_KERNEL);
+       if (!qplib_qp)
+               return -ENOMEM;
+
+       qplib_qp->id = qp->qplib_qp.id;
+       qplib_qp->ah.host_sgid_index = qp->qplib_qp.ah.host_sgid_index;
 
-       rc = bnxt_qplib_query_qp(&rdev->qplib_res, &qplib_qp);
+       rc = bnxt_qplib_query_qp(&rdev->qplib_res, qplib_qp);
        if (rc) {
                dev_err(rdev_to_dev(rdev), "Failed to query HW QP");
-               return rc;
+               goto out;
        }
-       qp_attr->qp_state = __to_ib_qp_state(qplib_qp.state);
-       qp_attr->en_sqd_async_notify = qplib_qp.en_sqd_async_notify ? 1 : 0;
-       qp_attr->qp_access_flags = __to_ib_access_flags(qplib_qp.access);
-       qp_attr->pkey_index = qplib_qp.pkey_index;
-       qp_attr->qkey = qplib_qp.qkey;
+       qp_attr->qp_state = __to_ib_qp_state(qplib_qp->state);
+       qp_attr->en_sqd_async_notify = qplib_qp->en_sqd_async_notify ? 1 : 0;
+       qp_attr->qp_access_flags = __to_ib_access_flags(qplib_qp->access);
+       qp_attr->pkey_index = qplib_qp->pkey_index;
+       qp_attr->qkey = qplib_qp->qkey;
        qp_attr->ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE;
-       rdma_ah_set_grh(&qp_attr->ah_attr, NULL, qplib_qp.ah.flow_label,
-                       qplib_qp.ah.host_sgid_index,
-                       qplib_qp.ah.hop_limit,
-                       qplib_qp.ah.traffic_class);
-       rdma_ah_set_dgid_raw(&qp_attr->ah_attr, qplib_qp.ah.dgid.data);
-       rdma_ah_set_sl(&qp_attr->ah_attr, qplib_qp.ah.sl);
-       ether_addr_copy(qp_attr->ah_attr.roce.dmac, qplib_qp.ah.dmac);
-       qp_attr->path_mtu = __to_ib_mtu(qplib_qp.path_mtu);
-       qp_attr->timeout = qplib_qp.timeout;
-       qp_attr->retry_cnt = qplib_qp.retry_cnt;
-       qp_attr->rnr_retry = qplib_qp.rnr_retry;
-       qp_attr->min_rnr_timer = qplib_qp.min_rnr_timer;
-       qp_attr->rq_psn = qplib_qp.rq.psn;
-       qp_attr->max_rd_atomic = qplib_qp.max_rd_atomic;
-       qp_attr->sq_psn = qplib_qp.sq.psn;
-       qp_attr->max_dest_rd_atomic = qplib_qp.max_dest_rd_atomic;
-       qp_init_attr->sq_sig_type = qplib_qp.sig_type ? IB_SIGNAL_ALL_WR :
-                                                       IB_SIGNAL_REQ_WR;
-       qp_attr->dest_qp_num = qplib_qp.dest_qpn;
+       rdma_ah_set_grh(&qp_attr->ah_attr, NULL, qplib_qp->ah.flow_label,
+                       qplib_qp->ah.host_sgid_index,
+                       qplib_qp->ah.hop_limit,
+                       qplib_qp->ah.traffic_class);
+       rdma_ah_set_dgid_raw(&qp_attr->ah_attr, qplib_qp->ah.dgid.data);
+       rdma_ah_set_sl(&qp_attr->ah_attr, qplib_qp->ah.sl);
+       ether_addr_copy(qp_attr->ah_attr.roce.dmac, qplib_qp->ah.dmac);
+       qp_attr->path_mtu = __to_ib_mtu(qplib_qp->path_mtu);
+       qp_attr->timeout = qplib_qp->timeout;
+       qp_attr->retry_cnt = qplib_qp->retry_cnt;
+       qp_attr->rnr_retry = qplib_qp->rnr_retry;
+       qp_attr->min_rnr_timer = qplib_qp->min_rnr_timer;
+       qp_attr->rq_psn = qplib_qp->rq.psn;
+       qp_attr->max_rd_atomic = qplib_qp->max_rd_atomic;
+       qp_attr->sq_psn = qplib_qp->sq.psn;
+       qp_attr->max_dest_rd_atomic = qplib_qp->max_dest_rd_atomic;
+       qp_init_attr->sq_sig_type = qplib_qp->sig_type ? IB_SIGNAL_ALL_WR :
+                                                        IB_SIGNAL_REQ_WR;
+       qp_attr->dest_qp_num = qplib_qp->dest_qpn;
 
        qp_attr->cap.max_send_wr = qp->qplib_qp.sq.max_wqe;
        qp_attr->cap.max_send_sge = qp->qplib_qp.sq.max_sge;
@@ -1596,7 +1614,9 @@ int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
        qp_attr->cap.max_inline_data = qp->qplib_qp.max_inline_data;
        qp_init_attr->cap = qp_attr->cap;
 
-       return 0;
+out:
+       kfree(qplib_qp);
+       return rc;
 }
 
 /* Routine for sending QP1 packets for RoCE V1 an V2
@@ -1908,6 +1928,7 @@ static int bnxt_re_build_atomic_wqe(struct ib_send_wr *wr,
        switch (wr->opcode) {
        case IB_WR_ATOMIC_CMP_AND_SWP:
                wqe->type = BNXT_QPLIB_SWQE_TYPE_ATOMIC_CMP_AND_SWP;
+               wqe->atomic.cmp_data = atomic_wr(wr)->compare_add;
                wqe->atomic.swap_data = atomic_wr(wr)->swap;
                break;
        case IB_WR_ATOMIC_FETCH_AND_ADD:
@@ -3062,7 +3083,7 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr)
                return rc;
        }
 
-       if (mr->npages && mr->pages) {
+       if (mr->pages) {
                rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
                                                        &mr->qplib_frpl);
                kfree(mr->pages);
index 82d1cbc27aeec80af4ac927227af347eba6f9714..e7450ea92aa9e11ba0d28792f54fcf373e470a66 100644 (file)
@@ -1161,6 +1161,8 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
                }
        }
        set_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags);
+       ib_get_eth_speed(&rdev->ibdev, 1, &rdev->active_speed,
+                        &rdev->active_width);
        bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, IB_EVENT_PORT_ACTIVE);
        bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, IB_EVENT_GID_CHANGE);
 
@@ -1255,10 +1257,14 @@ static void bnxt_re_task(struct work_struct *work)
                else if (netif_carrier_ok(rdev->netdev))
                        bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1,
                                               IB_EVENT_PORT_ACTIVE);
+               ib_get_eth_speed(&rdev->ibdev, 1, &rdev->active_speed,
+                                &rdev->active_width);
                break;
        default:
                break;
        }
+       smp_mb__before_atomic();
+       clear_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags);
        kfree(re_work);
 }
 
@@ -1317,6 +1323,11 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
                break;
 
        case NETDEV_UNREGISTER:
+               /* netdev notifier will call NETDEV_UNREGISTER again later since
+                * we are still holding the reference to the netdev
+                */
+               if (test_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags))
+                       goto exit;
                bnxt_re_ib_unreg(rdev, false);
                bnxt_re_remove_one(rdev);
                bnxt_re_dev_unreg(rdev);
@@ -1335,6 +1346,7 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
                        re_work->vlan_dev = (real_dev == netdev ?
                                             NULL : netdev);
                        INIT_WORK(&re_work->work, bnxt_re_task);
+                       set_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags);
                        queue_work(bnxt_re_wq, &re_work->work);
                }
        }
@@ -1375,6 +1387,22 @@ err_netdev:
 
 static void __exit bnxt_re_mod_exit(void)
 {
+       struct bnxt_re_dev *rdev;
+       LIST_HEAD(to_be_deleted);
+
+       mutex_lock(&bnxt_re_dev_lock);
+       /* Free all adapter allocated resources */
+       if (!list_empty(&bnxt_re_dev_list))
+               list_splice_init(&bnxt_re_dev_list, &to_be_deleted);
+       mutex_unlock(&bnxt_re_dev_lock);
+
+       list_for_each_entry(rdev, &to_be_deleted, list) {
+               dev_info(rdev_to_dev(rdev), "Unregistering Device");
+               bnxt_re_dev_stop(rdev);
+               bnxt_re_ib_unreg(rdev, true);
+               bnxt_re_remove_one(rdev);
+               bnxt_re_dev_unreg(rdev);
+       }
        unregister_netdevice_notifier(&bnxt_re_netdev_notifier);
        if (bnxt_re_wq)
                destroy_workqueue(bnxt_re_wq);
index 391bb7006e8ffb5fe42175e662c3b80c87d74f35..2bdb1562bd2197e850f14bcc353d6ee12c3271c4 100644 (file)
@@ -107,6 +107,9 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
                return -EINVAL;
        }
 
+       if (test_bit(FIRMWARE_TIMED_OUT, &rcfw->flags))
+               return -ETIMEDOUT;
+
        /* Cmdq are in 16-byte units, each request can consume 1 or more
         * cmdqe
         */
@@ -226,6 +229,7 @@ int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
                /* timed out */
                dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x timedout (%d)msec",
                        cookie, opcode, RCFW_CMD_WAIT_TIME_MS);
+               set_bit(FIRMWARE_TIMED_OUT, &rcfw->flags);
                return rc;
        }
 
index 0ed312f17c8de8025feea00fdd47feb063d65aa5..85b16da287f99edfee396fcdaa11ccef1c7c8d3b 100644 (file)
@@ -162,8 +162,9 @@ struct bnxt_qplib_rcfw {
        unsigned long           *cmdq_bitmap;
        u32                     bmap_size;
        unsigned long           flags;
-#define FIRMWARE_INITIALIZED_FLAG      1
+#define FIRMWARE_INITIALIZED_FLAG      BIT(0)
 #define FIRMWARE_FIRST_FLAG            BIT(31)
+#define FIRMWARE_TIMED_OUT             BIT(3)
        wait_queue_head_t       waitq;
        int                     (*aeq_handler)(struct bnxt_qplib_rcfw *,
                                               struct creq_func_event *);
index ceaa2fa54d322d2c9368576602a8d47e448527d0..daf7a56e5d7ebe4a7b6dffd93245d5a1655b3805 100644 (file)
@@ -2333,9 +2333,14 @@ static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        unsigned int stid = GET_TID(rpl);
        struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid);
 
+       if (!ep) {
+               pr_debug("%s stid %d lookup failure!\n", __func__, stid);
+               goto out;
+       }
        pr_debug("%s ep %p\n", __func__, ep);
        c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status));
        c4iw_put_ep(&ep->com);
+out:
        return 0;
 }
 
@@ -2594,9 +2599,9 @@ fail:
        c4iw_put_ep(&child_ep->com);
 reject:
        reject_cr(dev, hwtid, skb);
+out:
        if (parent_ep)
                c4iw_put_ep(&parent_ep->com);
-out:
        return 0;
 }
 
@@ -3457,7 +3462,7 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
                cm_id->provider_data = ep;
                goto out;
        }
-
+       remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid);
        cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid,
                        ep->com.local_addr.ss_family);
 fail2:
index b2ed4b9cda6eef62f81b5ac22b71b4cc3a5a2d10..0be42787759fa78c73d0e0d9776209c2362a3ddc 100644 (file)
@@ -1066,6 +1066,8 @@ static int read_idle_sma(struct hfi1_devdata *dd, u64 *data);
 static int thermal_init(struct hfi1_devdata *dd);
 
 static void update_statusp(struct hfi1_pportdata *ppd, u32 state);
+static int wait_phys_link_offline_substates(struct hfi1_pportdata *ppd,
+                                           int msecs);
 static int wait_logical_linkstate(struct hfi1_pportdata *ppd, u32 state,
                                  int msecs);
 static void log_state_transition(struct hfi1_pportdata *ppd, u32 state);
@@ -8238,6 +8240,7 @@ static irqreturn_t general_interrupt(int irq, void *data)
        u64 regs[CCE_NUM_INT_CSRS];
        u32 bit;
        int i;
+       irqreturn_t handled = IRQ_NONE;
 
        this_cpu_inc(*dd->int_counter);
 
@@ -8258,9 +8261,10 @@ static irqreturn_t general_interrupt(int irq, void *data)
        for_each_set_bit(bit, (unsigned long *)&regs[0],
                         CCE_NUM_INT_CSRS * 64) {
                is_interrupt(dd, bit);
+               handled = IRQ_HANDLED;
        }
 
-       return IRQ_HANDLED;
+       return handled;
 }
 
 static irqreturn_t sdma_interrupt(int irq, void *data)
@@ -9413,7 +9417,7 @@ static void set_qsfp_int_n(struct hfi1_pportdata *ppd, u8 enable)
        write_csr(dd, dd->hfi1_id ? ASIC_QSFP2_MASK : ASIC_QSFP1_MASK, mask);
 }
 
-void reset_qsfp(struct hfi1_pportdata *ppd)
+int reset_qsfp(struct hfi1_pportdata *ppd)
 {
        struct hfi1_devdata *dd = ppd->dd;
        u64 mask, qsfp_mask;
@@ -9443,6 +9447,13 @@ void reset_qsfp(struct hfi1_pportdata *ppd)
         * for alarms and warnings
         */
        set_qsfp_int_n(ppd, 1);
+
+       /*
+        * After the reset, AOC transmitters are enabled by default. They need
+        * to be turned off to complete the QSFP setup before they can be
+        * enabled again.
+        */
+       return set_qsfp_tx(ppd, 0);
 }
 
 static int handle_qsfp_error_conditions(struct hfi1_pportdata *ppd,
@@ -10305,6 +10316,7 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
 {
        struct hfi1_devdata *dd = ppd->dd;
        u32 previous_state;
+       int offline_state_ret;
        int ret;
 
        update_lcb_cache(dd);
@@ -10326,28 +10338,11 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
                ppd->offline_disabled_reason =
                HFI1_ODR_MASK(OPA_LINKDOWN_REASON_TRANSIENT);
 
-       /*
-        * Wait for offline transition. It can take a while for
-        * the link to go down.
-        */
-       ret = wait_physical_linkstate(ppd, PLS_OFFLINE, 10000);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Now in charge of LCB - must be after the physical state is
-        * offline.quiet and before host_link_state is changed.
-        */
-       set_host_lcb_access(dd);
-       write_csr(dd, DC_LCB_ERR_EN, ~0ull); /* watch LCB errors */
-
-       /* make sure the logical state is also down */
-       ret = wait_logical_linkstate(ppd, IB_PORT_DOWN, 1000);
-       if (ret)
-               force_logical_link_state_down(ppd);
-
-       ppd->host_link_state = HLS_LINK_COOLDOWN; /* LCB access allowed */
+       offline_state_ret = wait_phys_link_offline_substates(ppd, 10000);
+       if (offline_state_ret < 0)
+               return offline_state_ret;
 
+       /* Disabling AOC transmitters */
        if (ppd->port_type == PORT_TYPE_QSFP &&
            ppd->qsfp_info.limiting_active &&
            qsfp_mod_present(ppd)) {
@@ -10364,6 +10359,30 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
                }
        }
 
+       /*
+        * Wait for the offline.Quiet transition if it hasn't happened yet. It
+        * can take a while for the link to go down.
+        */
+       if (offline_state_ret != PLS_OFFLINE_QUIET) {
+               ret = wait_physical_linkstate(ppd, PLS_OFFLINE, 30000);
+               if (ret < 0)
+                       return ret;
+       }
+
+       /*
+        * Now in charge of LCB - must be after the physical state is
+        * offline.quiet and before host_link_state is changed.
+        */
+       set_host_lcb_access(dd);
+       write_csr(dd, DC_LCB_ERR_EN, ~0ull); /* watch LCB errors */
+
+       /* make sure the logical state is also down */
+       ret = wait_logical_linkstate(ppd, IB_PORT_DOWN, 1000);
+       if (ret)
+               force_logical_link_state_down(ppd);
+
+       ppd->host_link_state = HLS_LINK_COOLDOWN; /* LCB access allowed */
+
        /*
         * The LNI has a mandatory wait time after the physical state
         * moves to Offline.Quiet.  The wait time may be different
@@ -10396,6 +10415,9 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
                        & (HLS_DN_POLL | HLS_VERIFY_CAP | HLS_GOING_UP)) {
                /* went down while attempting link up */
                check_lni_states(ppd);
+
+               /* The QSFP doesn't need to be reset on LNI failure */
+               ppd->qsfp_info.reset_needed = 0;
        }
 
        /* the active link width (downgrade) is 0 on link down */
@@ -12804,6 +12826,39 @@ static int wait_physical_linkstate(struct hfi1_pportdata *ppd, u32 state,
        return 0;
 }
 
+/*
+ * wait_phys_link_offline_quiet_substates - wait for any offline substate
+ * @ppd: port device
+ * @msecs: the number of milliseconds to wait
+ *
+ * Wait up to msecs milliseconds for any offline physical link
+ * state change to occur.
+ * Returns 0 if at least one state is reached, otherwise -ETIMEDOUT.
+ */
+static int wait_phys_link_offline_substates(struct hfi1_pportdata *ppd,
+                                           int msecs)
+{
+       u32 read_state;
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(msecs);
+       while (1) {
+               read_state = read_physical_state(ppd->dd);
+               if ((read_state & 0xF0) == PLS_OFFLINE)
+                       break;
+               if (time_after(jiffies, timeout)) {
+                       dd_dev_err(ppd->dd,
+                                  "timeout waiting for phy link offline.quiet substates. Read state 0x%x, %dms\n",
+                                  read_state, msecs);
+                       return -ETIMEDOUT;
+               }
+               usleep_range(1950, 2050); /* sleep 2ms-ish */
+       }
+
+       log_state_transition(ppd, read_state);
+       return read_state;
+}
+
 #define CLEAR_STATIC_RATE_CONTROL_SMASK(r) \
 (r &= ~SEND_CTXT_CHECK_ENABLE_DISALLOW_PBC_STATIC_RATE_CONTROL_SMASK)
 
index b8345a60a0fbc452215dba3c679daa6785fb4e4a..50b8645d0b876dbf6d58f56d677e3cfcc7984e55 100644 (file)
 #define PLS_OFFLINE_READY_TO_QUIET_LT     0x92
 #define PLS_OFFLINE_REPORT_FAILURE                0x93
 #define PLS_OFFLINE_READY_TO_QUIET_BCC    0x94
+#define PLS_OFFLINE_QUIET_DURATION        0x95
 #define PLS_POLLING                               0x20
 #define PLS_POLLING_QUIET                         0x20
 #define PLS_POLLING_ACTIVE                        0x21
@@ -722,7 +723,7 @@ void handle_link_downgrade(struct work_struct *work);
 void handle_link_bounce(struct work_struct *work);
 void handle_start_link(struct work_struct *work);
 void handle_sma_message(struct work_struct *work);
-void reset_qsfp(struct hfi1_pportdata *ppd);
+int reset_qsfp(struct hfi1_pportdata *ppd);
 void qsfp_event(struct work_struct *work);
 void start_freeze_handling(struct hfi1_pportdata *ppd, int flags);
 int send_idle_sma(struct hfi1_devdata *dd, u64 message);
index d46b171079010d2cf7e42dd7557f0abc2bef1348..1613af1c58d9ddaafca831b1282a6462fdc10b66 100644 (file)
@@ -204,7 +204,10 @@ done_asic:
        return ret;
 }
 
-/* magic character sequence that trails an image */
+/* magic character sequence that begins an image */
+#define IMAGE_START_MAGIC "APO="
+
+/* magic character sequence that might trail an image */
 #define IMAGE_TRAIL_MAGIC "egamiAPO"
 
 /* EPROM file types */
@@ -250,6 +253,7 @@ static int read_partition_platform_config(struct hfi1_devdata *dd, void **data,
 {
        void *buffer;
        void *p;
+       u32 length;
        int ret;
 
        buffer = kmalloc(P1_SIZE, GFP_KERNEL);
@@ -262,15 +266,21 @@ static int read_partition_platform_config(struct hfi1_devdata *dd, void **data,
                return ret;
        }
 
-       /* scan for image magic that may trail the actual data */
-       p = strnstr(buffer, IMAGE_TRAIL_MAGIC, P1_SIZE);
-       if (!p) {
+       /* config partition is valid only if it starts with IMAGE_START_MAGIC */
+       if (memcmp(buffer, IMAGE_START_MAGIC, strlen(IMAGE_START_MAGIC))) {
                kfree(buffer);
                return -ENOENT;
        }
 
+       /* scan for image magic that may trail the actual data */
+       p = strnstr(buffer, IMAGE_TRAIL_MAGIC, P1_SIZE);
+       if (p)
+               length = p - buffer;
+       else
+               length = P1_SIZE;
+
        *data = buffer;
-       *size = p - buffer;
+       *size = length;
        return 0;
 }
 
index 2bc89260235a1db1c744931cde7ec07fd3202495..d9a1e989313641b06f32ffdd4677ce8aa7e32802 100644 (file)
@@ -930,15 +930,8 @@ static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo)
        switch (ret) {
        case 0:
                ret = setup_base_ctxt(fd, uctxt);
-               if (uctxt->subctxt_cnt) {
-                       /*
-                        * Base context is done (successfully or not), notify
-                        * anybody using a sub-context that is waiting for
-                        * this completion.
-                        */
-                       clear_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags);
-                       wake_up(&uctxt->wait);
-               }
+               if (ret)
+                       deallocate_ctxt(uctxt);
                break;
        case 1:
                ret = complete_subctxt(fd);
@@ -1305,25 +1298,25 @@ static int setup_base_ctxt(struct hfi1_filedata *fd,
        /* Now allocate the RcvHdr queue and eager buffers. */
        ret = hfi1_create_rcvhdrq(dd, uctxt);
        if (ret)
-               return ret;
+               goto done;
 
        ret = hfi1_setup_eagerbufs(uctxt);
        if (ret)
-               goto setup_failed;
+               goto done;
 
        /* If sub-contexts are enabled, do the appropriate setup */
        if (uctxt->subctxt_cnt)
                ret = setup_subctxt(uctxt);
        if (ret)
-               goto setup_failed;
+               goto done;
 
        ret = hfi1_alloc_ctxt_rcv_groups(uctxt);
        if (ret)
-               goto setup_failed;
+               goto done;
 
        ret = init_user_ctxt(fd, uctxt);
        if (ret)
-               goto setup_failed;
+               goto done;
 
        user_init(uctxt);
 
@@ -1331,12 +1324,22 @@ static int setup_base_ctxt(struct hfi1_filedata *fd,
        fd->uctxt = uctxt;
        hfi1_rcd_get(uctxt);
 
-       return 0;
+done:
+       if (uctxt->subctxt_cnt) {
+               /*
+                * On error, set the failed bit so sub-contexts will clean up
+                * correctly.
+                */
+               if (ret)
+                       set_bit(HFI1_CTXT_BASE_FAILED, &uctxt->event_flags);
 
-setup_failed:
-       /* Set the failed bit so sub-context init can do the right thing */
-       set_bit(HFI1_CTXT_BASE_FAILED, &uctxt->event_flags);
-       deallocate_ctxt(uctxt);
+               /*
+                * Base context is done (successfully or not), notify anybody
+                * using a sub-context that is waiting for this completion.
+                */
+               clear_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags);
+               wake_up(&uctxt->wait);
+       }
 
        return ret;
 }
index 82447b7cdda1e958d7e7c42c3447ec4a72c1fb4a..09e50fd2a08f07bf7b2d42d3d4b4a1a00644b2ce 100644 (file)
@@ -68,7 +68,7 @@
 /*
  * Code to adjust PCIe capabilities.
  */
-static int tune_pcie_caps(struct hfi1_devdata *);
+static void tune_pcie_caps(struct hfi1_devdata *);
 
 /*
  * Do all the common PCIe setup and initialization.
@@ -351,7 +351,7 @@ int pcie_speeds(struct hfi1_devdata *dd)
  */
 int request_msix(struct hfi1_devdata *dd, u32 msireq)
 {
-       int nvec, ret;
+       int nvec;
 
        nvec = pci_alloc_irq_vectors(dd->pcidev, 1, msireq,
                                     PCI_IRQ_MSIX | PCI_IRQ_LEGACY);
@@ -360,12 +360,7 @@ int request_msix(struct hfi1_devdata *dd, u32 msireq)
                return nvec;
        }
 
-       ret = tune_pcie_caps(dd);
-       if (ret) {
-               dd_dev_err(dd, "tune_pcie_caps() failed: %d\n", ret);
-               pci_free_irq_vectors(dd->pcidev);
-               return ret;
-       }
+       tune_pcie_caps(dd);
 
        /* check for legacy IRQ */
        if (nvec == 1 && !dd->pcidev->msix_enabled)
@@ -502,7 +497,7 @@ uint aspm_mode = ASPM_MODE_DISABLED;
 module_param_named(aspm, aspm_mode, uint, S_IRUGO);
 MODULE_PARM_DESC(aspm, "PCIe ASPM: 0: disable, 1: enable, 2: dynamic");
 
-static int tune_pcie_caps(struct hfi1_devdata *dd)
+static void tune_pcie_caps(struct hfi1_devdata *dd)
 {
        struct pci_dev *parent;
        u16 rc_mpss, rc_mps, ep_mpss, ep_mps;
@@ -513,22 +508,14 @@ static int tune_pcie_caps(struct hfi1_devdata *dd)
         * Turn on extended tags in DevCtl in case the BIOS has turned it off
         * to improve WFR SDMA bandwidth
         */
-       ret = pcie_capability_read_word(dd->pcidev,
-                                       PCI_EXP_DEVCTL, &ectl);
-       if (ret) {
-               dd_dev_err(dd, "Unable to read from PCI config\n");
-               return ret;
-       }
-
-       if (!(ectl & PCI_EXP_DEVCTL_EXT_TAG)) {
+       ret = pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &ectl);
+       if ((!ret) && !(ectl & PCI_EXP_DEVCTL_EXT_TAG)) {
                dd_dev_info(dd, "Enabling PCIe extended tags\n");
                ectl |= PCI_EXP_DEVCTL_EXT_TAG;
                ret = pcie_capability_write_word(dd->pcidev,
                                                 PCI_EXP_DEVCTL, ectl);
-               if (ret) {
-                       dd_dev_err(dd, "Unable to write to PCI config\n");
-                       return ret;
-               }
+               if (ret)
+                       dd_dev_info(dd, "Unable to write to PCI config\n");
        }
        /* Find out supported and configured values for parent (root) */
        parent = dd->pcidev->bus->self;
@@ -536,15 +523,22 @@ static int tune_pcie_caps(struct hfi1_devdata *dd)
         * The driver cannot perform the tuning if it does not have
         * access to the upstream component.
         */
-       if (!parent)
-               return -EINVAL;
+       if (!parent) {
+               dd_dev_info(dd, "Parent not found\n");
+               return;
+       }
        if (!pci_is_root_bus(parent->bus)) {
                dd_dev_info(dd, "Parent not root\n");
-               return -EINVAL;
+               return;
+       }
+       if (!pci_is_pcie(parent)) {
+               dd_dev_info(dd, "Parent is not PCI Express capable\n");
+               return;
+       }
+       if (!pci_is_pcie(dd->pcidev)) {
+               dd_dev_info(dd, "PCI device is not PCI Express capable\n");
+               return;
        }
-
-       if (!pci_is_pcie(parent) || !pci_is_pcie(dd->pcidev))
-               return -EINVAL;
        rc_mpss = parent->pcie_mpss;
        rc_mps = ffs(pcie_get_mps(parent)) - 8;
        /* Find out supported and configured values for endpoint (us) */
@@ -590,8 +584,6 @@ static int tune_pcie_caps(struct hfi1_devdata *dd)
                ep_mrrs = max_mrrs;
                pcie_set_readrq(dd->pcidev, ep_mrrs);
        }
-
-       return 0;
 }
 
 /* End of PCIe capability tuning */
index a8af96d2b1b0ae0dc5e98ae08e3b5c9b5faa50e9..d486355880cb0da37e23755e8ed49197fed90fc8 100644 (file)
@@ -790,7 +790,9 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
         * reuse of stale settings established in our previous pass through.
         */
        if (ppd->qsfp_info.reset_needed) {
-               reset_qsfp(ppd);
+               ret = reset_qsfp(ppd);
+               if (ret)
+                       return ret;
                refresh_qsfp_cache(ppd, &ppd->qsfp_info);
        } else {
                ppd->qsfp_info.reset_needed = 1;
index 9b1566468744ed81a922188f220e7ef64629273b..a65e4cbdce2f6ad336d58a226e84ac35fc7f7eda 100644 (file)
@@ -201,7 +201,6 @@ enum init_completion_state {
        CEQ_CREATED,
        ILQ_CREATED,
        IEQ_CREATED,
-       INET_NOTIFIER,
        IP_ADDR_REGISTERED,
        RDMA_DEV_REGISTERED
 };
index 14f36ba4e5bebf8e35970c9cc5b6030c95ffa213..5230dd3c938c2c506bc590afd8ef054d300ac480 100644 (file)
@@ -1504,23 +1504,40 @@ static void i40iw_add_hte_node(struct i40iw_cm_core *cm_core,
 }
 
 /**
- * listen_port_in_use - determine if port is in use
- * @port: Listen port number
+ * i40iw_port_in_use - determine if port is in use
+ * @port: port number
+ * @active_side: flag for listener side vs active side
  */
-static bool i40iw_listen_port_in_use(struct i40iw_cm_core *cm_core, u16 port)
+static bool i40iw_port_in_use(struct i40iw_cm_core *cm_core, u16 port, bool active_side)
 {
        struct i40iw_cm_listener *listen_node;
+       struct i40iw_cm_node *cm_node;
        unsigned long flags;
        bool ret = false;
 
-       spin_lock_irqsave(&cm_core->listen_list_lock, flags);
-       list_for_each_entry(listen_node, &cm_core->listen_nodes, list) {
-               if (listen_node->loc_port == port) {
-                       ret = true;
-                       break;
+       if (active_side) {
+               /* search connected node list */
+               spin_lock_irqsave(&cm_core->ht_lock, flags);
+               list_for_each_entry(cm_node, &cm_core->connected_nodes, list) {
+                       if (cm_node->loc_port == port) {
+                               ret = true;
+                               break;
+                       }
+               }
+                       if (!ret)
+                               clear_bit(port, cm_core->active_side_ports);
+               spin_unlock_irqrestore(&cm_core->ht_lock, flags);
+       } else {
+               spin_lock_irqsave(&cm_core->listen_list_lock, flags);
+               list_for_each_entry(listen_node, &cm_core->listen_nodes, list) {
+                       if (listen_node->loc_port == port) {
+                               ret = true;
+                               break;
+                       }
                }
+               spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
        }
-       spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
+
        return ret;
 }
 
@@ -1868,7 +1885,7 @@ static int i40iw_dec_refcnt_listen(struct i40iw_cm_core *cm_core,
                spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 
                if (listener->iwdev) {
-                       if (apbvt_del && !i40iw_listen_port_in_use(cm_core, listener->loc_port))
+                       if (apbvt_del && !i40iw_port_in_use(cm_core, listener->loc_port, false))
                                i40iw_manage_apbvt(listener->iwdev,
                                                   listener->loc_port,
                                                   I40IW_MANAGE_APBVT_DEL);
@@ -2247,21 +2264,21 @@ static void i40iw_rem_ref_cm_node(struct i40iw_cm_node *cm_node)
        if (cm_node->listener) {
                i40iw_dec_refcnt_listen(cm_core, cm_node->listener, 0, true);
        } else {
-               if (!i40iw_listen_port_in_use(cm_core, cm_node->loc_port) &&
-                   cm_node->apbvt_set) {
+               if (!i40iw_port_in_use(cm_core, cm_node->loc_port, true) && cm_node->apbvt_set) {
                        i40iw_manage_apbvt(cm_node->iwdev,
                                           cm_node->loc_port,
                                           I40IW_MANAGE_APBVT_DEL);
-                       i40iw_get_addr_info(cm_node, &nfo);
-                       if (cm_node->qhash_set) {
-                               i40iw_manage_qhash(cm_node->iwdev,
-                                                  &nfo,
-                                                  I40IW_QHASH_TYPE_TCP_ESTABLISHED,
-                                                  I40IW_QHASH_MANAGE_TYPE_DELETE,
-                                                  NULL,
-                                                  false);
-                               cm_node->qhash_set = 0;
-                       }
+                       cm_node->apbvt_set = 0;
+               }
+               i40iw_get_addr_info(cm_node, &nfo);
+               if (cm_node->qhash_set) {
+                       i40iw_manage_qhash(cm_node->iwdev,
+                                          &nfo,
+                                          I40IW_QHASH_TYPE_TCP_ESTABLISHED,
+                                          I40IW_QHASH_MANAGE_TYPE_DELETE,
+                                          NULL,
+                                          false);
+                       cm_node->qhash_set = 0;
                }
        }
 
@@ -3255,7 +3272,8 @@ static void i40iw_init_tcp_ctx(struct i40iw_cm_node *cm_node,
        tcp_info->snd_mss = cpu_to_le32(((u32)cm_node->tcp_cntxt.mss));
        if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
                tcp_info->insert_vlan_tag = true;
-               tcp_info->vlan_tag = cpu_to_le16(cm_node->vlan_id);
+               tcp_info->vlan_tag = cpu_to_le16(((u16)cm_node->user_pri << I40IW_VLAN_PRIO_SHIFT) |
+                                                 cm_node->vlan_id);
        }
        if (cm_node->ipv4) {
                tcp_info->src_port = cpu_to_le16(cm_node->loc_port);
@@ -3737,10 +3755,8 @@ int i40iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        struct sockaddr_in *raddr;
        struct sockaddr_in6 *laddr6;
        struct sockaddr_in6 *raddr6;
-       bool qhash_set = false;
-       int apbvt_set = 0;
-       int err = 0;
-       enum i40iw_status_code status;
+       int ret = 0;
+       unsigned long flags;
 
        ibqp = i40iw_get_qp(cm_id->device, conn_param->qpn);
        if (!ibqp)
@@ -3789,32 +3805,6 @@ int i40iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        cm_info.user_pri = rt_tos2priority(cm_id->tos);
        i40iw_debug(&iwdev->sc_dev, I40IW_DEBUG_DCB, "%s TOS:[%d] UP:[%d]\n",
                    __func__, cm_id->tos, cm_info.user_pri);
-       if ((cm_info.ipv4 && (laddr->sin_addr.s_addr != raddr->sin_addr.s_addr)) ||
-           (!cm_info.ipv4 && memcmp(laddr6->sin6_addr.in6_u.u6_addr32,
-                                    raddr6->sin6_addr.in6_u.u6_addr32,
-                                    sizeof(laddr6->sin6_addr.in6_u.u6_addr32)))) {
-               status = i40iw_manage_qhash(iwdev,
-                                           &cm_info,
-                                           I40IW_QHASH_TYPE_TCP_ESTABLISHED,
-                                           I40IW_QHASH_MANAGE_TYPE_ADD,
-                                           NULL,
-                                           true);
-               if (status)
-                       return -EINVAL;
-               qhash_set = true;
-       }
-       status = i40iw_manage_apbvt(iwdev, cm_info.loc_port, I40IW_MANAGE_APBVT_ADD);
-       if (status) {
-               i40iw_manage_qhash(iwdev,
-                                  &cm_info,
-                                  I40IW_QHASH_TYPE_TCP_ESTABLISHED,
-                                  I40IW_QHASH_MANAGE_TYPE_DELETE,
-                                  NULL,
-                                  false);
-               return -EINVAL;
-       }
-
-       apbvt_set = 1;
        cm_id->add_ref(cm_id);
        cm_node = i40iw_create_cm_node(&iwdev->cm_core, iwdev,
                                       conn_param->private_data_len,
@@ -3822,17 +3812,40 @@ int i40iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                                       &cm_info);
 
        if (IS_ERR(cm_node)) {
-               err = PTR_ERR(cm_node);
-               goto err_out;
+               ret = PTR_ERR(cm_node);
+               cm_id->rem_ref(cm_id);
+               return ret;
+       }
+
+       if ((cm_info.ipv4 && (laddr->sin_addr.s_addr != raddr->sin_addr.s_addr)) ||
+           (!cm_info.ipv4 && memcmp(laddr6->sin6_addr.in6_u.u6_addr32,
+                                    raddr6->sin6_addr.in6_u.u6_addr32,
+                                    sizeof(laddr6->sin6_addr.in6_u.u6_addr32)))) {
+               if (i40iw_manage_qhash(iwdev, &cm_info, I40IW_QHASH_TYPE_TCP_ESTABLISHED,
+                                      I40IW_QHASH_MANAGE_TYPE_ADD, NULL, true)) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+               cm_node->qhash_set = true;
        }
 
+       spin_lock_irqsave(&iwdev->cm_core.ht_lock, flags);
+       if (!test_and_set_bit(cm_info.loc_port, iwdev->cm_core.active_side_ports)) {
+               spin_unlock_irqrestore(&iwdev->cm_core.ht_lock, flags);
+               if (i40iw_manage_apbvt(iwdev, cm_info.loc_port, I40IW_MANAGE_APBVT_ADD)) {
+                       ret =  -EINVAL;
+                       goto err;
+               }
+       } else {
+               spin_unlock_irqrestore(&iwdev->cm_core.ht_lock, flags);
+       }
+
+       cm_node->apbvt_set = true;
        i40iw_record_ird_ord(cm_node, (u16)conn_param->ird, (u16)conn_param->ord);
        if (cm_node->send_rdma0_op == SEND_RDMA_READ_ZERO &&
            !cm_node->ord_size)
                cm_node->ord_size = 1;
 
-       cm_node->apbvt_set = apbvt_set;
-       cm_node->qhash_set = qhash_set;
        iwqp->cm_node = cm_node;
        cm_node->iwqp = iwqp;
        iwqp->cm_id = cm_id;
@@ -3840,11 +3853,9 @@ int i40iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 
        if (cm_node->state != I40IW_CM_STATE_OFFLOADED) {
                cm_node->state = I40IW_CM_STATE_SYN_SENT;
-               err = i40iw_send_syn(cm_node, 0);
-               if (err) {
-                       i40iw_rem_ref_cm_node(cm_node);
-                       goto err_out;
-               }
+               ret = i40iw_send_syn(cm_node, 0);
+               if (ret)
+                       goto err;
        }
 
        i40iw_debug(cm_node->dev,
@@ -3853,9 +3864,10 @@ int i40iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                    cm_node->rem_port,
                    cm_node,
                    cm_node->cm_id);
+
        return 0;
 
-err_out:
+err:
        if (cm_info.ipv4)
                i40iw_debug(&iwdev->sc_dev,
                            I40IW_DEBUG_CM,
@@ -3867,22 +3879,10 @@ err_out:
                            "Api - connect() FAILED: dest addr=%pI6",
                            cm_info.rem_addr);
 
-       if (qhash_set)
-               i40iw_manage_qhash(iwdev,
-                                  &cm_info,
-                                  I40IW_QHASH_TYPE_TCP_ESTABLISHED,
-                                  I40IW_QHASH_MANAGE_TYPE_DELETE,
-                                  NULL,
-                                  false);
-
-       if (apbvt_set && !i40iw_listen_port_in_use(&iwdev->cm_core,
-                                                  cm_info.loc_port))
-               i40iw_manage_apbvt(iwdev,
-                                  cm_info.loc_port,
-                                  I40IW_MANAGE_APBVT_DEL);
+       i40iw_rem_ref_cm_node(cm_node);
        cm_id->rem_ref(cm_id);
        iwdev->cm_core.stats_connect_errs++;
-       return err;
+       return ret;
 }
 
 /**
index 2e52e38ffcf37cf5673868f873536907dddc2cf1..45abef76295b24429accdce4e7a49d91dbc33cce 100644 (file)
@@ -71,6 +71,9 @@
 #define        I40IW_HW_IRD_SETTING_32 32
 #define        I40IW_HW_IRD_SETTING_64 64
 
+#define MAX_PORTS              65536
+#define I40IW_VLAN_PRIO_SHIFT   13
+
 enum ietf_mpa_flags {
        IETF_MPA_FLAGS_MARKERS = 0x80,  /* receive Markers */
        IETF_MPA_FLAGS_CRC = 0x40,      /* receive Markers */
@@ -411,6 +414,8 @@ struct i40iw_cm_core {
        spinlock_t ht_lock; /* manage hash table */
        spinlock_t listen_list_lock; /* listen list */
 
+       unsigned long active_side_ports[BITS_TO_LONGS(MAX_PORTS)];
+
        u64     stats_nodes_created;
        u64     stats_nodes_destroyed;
        u64     stats_listen_created;
index cc742c3132c6f49afa38282a9f694e2fa68385f7..27590ae21881e91508bc0eb88308e97a7693f094 100644 (file)
@@ -99,8 +99,6 @@ static struct notifier_block i40iw_net_notifier = {
        .notifier_call = i40iw_net_event
 };
 
-static atomic_t i40iw_notifiers_registered;
-
 /**
  * i40iw_find_i40e_handler - find a handler given a client info
  * @ldev: pointer to a client info
@@ -1376,11 +1374,20 @@ error:
  */
 static void i40iw_register_notifiers(void)
 {
-       if (atomic_inc_return(&i40iw_notifiers_registered) == 1) {
-               register_inetaddr_notifier(&i40iw_inetaddr_notifier);
-               register_inet6addr_notifier(&i40iw_inetaddr6_notifier);
-               register_netevent_notifier(&i40iw_net_notifier);
-       }
+       register_inetaddr_notifier(&i40iw_inetaddr_notifier);
+       register_inet6addr_notifier(&i40iw_inetaddr6_notifier);
+       register_netevent_notifier(&i40iw_net_notifier);
+}
+
+/**
+ * i40iw_unregister_notifiers - unregister tcp ip notifiers
+ */
+
+static void i40iw_unregister_notifiers(void)
+{
+       unregister_netevent_notifier(&i40iw_net_notifier);
+       unregister_inetaddr_notifier(&i40iw_inetaddr_notifier);
+       unregister_inet6addr_notifier(&i40iw_inetaddr6_notifier);
 }
 
 /**
@@ -1400,6 +1407,11 @@ static enum i40iw_status_code i40iw_save_msix_info(struct i40iw_device *iwdev,
        u32 i;
        u32 size;
 
+       if (!ldev->msix_count) {
+               i40iw_pr_err("No MSI-X vectors\n");
+               return I40IW_ERR_CONFIG;
+       }
+
        iwdev->msix_count = ldev->msix_count;
 
        size = sizeof(struct i40iw_msix_vector) * iwdev->msix_count;
@@ -1462,12 +1474,6 @@ static void i40iw_deinit_device(struct i40iw_device *iwdev)
                if (!iwdev->reset)
                        i40iw_del_macip_entry(iwdev, (u8)iwdev->mac_ip_table_idx);
                /* fallthrough */
-       case INET_NOTIFIER:
-               if (!atomic_dec_return(&i40iw_notifiers_registered)) {
-                       unregister_netevent_notifier(&i40iw_net_notifier);
-                       unregister_inetaddr_notifier(&i40iw_inetaddr_notifier);
-                       unregister_inet6addr_notifier(&i40iw_inetaddr6_notifier);
-               }
                /* fallthrough */
        case PBLE_CHUNK_MEM:
                i40iw_destroy_pble_pool(dev, iwdev->pble_rsrc);
@@ -1550,7 +1556,7 @@ static enum i40iw_status_code i40iw_setup_init_state(struct i40iw_handler *hdl,
 
        status = i40iw_save_msix_info(iwdev, ldev);
        if (status)
-               goto exit;
+               return status;
        iwdev->hw.dev_context = (void *)ldev->pcidev;
        iwdev->hw.hw_addr = ldev->hw_addr;
        status = i40iw_allocate_dma_mem(&iwdev->hw,
@@ -1667,8 +1673,6 @@ static int i40iw_open(struct i40e_info *ldev, struct i40e_client *client)
                        break;
                iwdev->init_state = PBLE_CHUNK_MEM;
                iwdev->virtchnl_wq = alloc_ordered_workqueue("iwvch", WQ_MEM_RECLAIM);
-               i40iw_register_notifiers();
-               iwdev->init_state = INET_NOTIFIER;
                status = i40iw_add_mac_ip(iwdev);
                if (status)
                        break;
@@ -2018,6 +2022,8 @@ static int __init i40iw_init_module(void)
        i40iw_client.type = I40E_CLIENT_IWARP;
        spin_lock_init(&i40iw_handler_lock);
        ret = i40e_register_client(&i40iw_client);
+       i40iw_register_notifiers();
+
        return ret;
 }
 
@@ -2029,6 +2035,7 @@ static int __init i40iw_init_module(void)
  */
 static void __exit i40iw_exit_module(void)
 {
+       i40iw_unregister_notifiers();
        i40e_unregister_client(&i40iw_client);
 }
 
index 62f1f45b8737a4716d04d8a340ab5612ef4f1047..e52dbbb4165ec555d94eb5f55f5310c71562b387 100644 (file)
@@ -160,7 +160,7 @@ int i40iw_inetaddr_event(struct notifier_block *notifier,
                return NOTIFY_DONE;
 
        iwdev = &hdl->device;
-       if (iwdev->init_state < INET_NOTIFIER)
+       if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing)
                return NOTIFY_DONE;
 
        netdev = iwdev->ldev->netdev;
@@ -217,7 +217,7 @@ int i40iw_inet6addr_event(struct notifier_block *notifier,
                return NOTIFY_DONE;
 
        iwdev = &hdl->device;
-       if (iwdev->init_state < INET_NOTIFIER)
+       if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing)
                return NOTIFY_DONE;
 
        netdev = iwdev->ldev->netdev;
@@ -266,7 +266,7 @@ int i40iw_net_event(struct notifier_block *notifier, unsigned long event, void *
                if (!iwhdl)
                        return NOTIFY_DONE;
                iwdev = &iwhdl->device;
-               if (iwdev->init_state < INET_NOTIFIER)
+               if (iwdev->init_state < IP_ADDR_REGISTERED || iwdev->closing)
                        return NOTIFY_DONE;
                p = (__be32 *)neigh->primary_key;
                i40iw_copy_ip_ntohl(local_ipaddr, p);
index 1aa411034a272457ba9a0fda16761d808b38f5f8..28b3d02d511b35f60c44437c47ed88bb4a04d424 100644 (file)
@@ -1027,7 +1027,19 @@ int i40iw_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                iwqp->hw_tcp_state = I40IW_TCP_STATE_CLOSED;
                                iwqp->last_aeq = I40IW_AE_RESET_SENT;
                                spin_unlock_irqrestore(&iwqp->lock, flags);
+                               i40iw_cm_disconn(iwqp);
                        }
+               } else {
+                       spin_lock_irqsave(&iwqp->lock, flags);
+                       if (iwqp->cm_id) {
+                               if (atomic_inc_return(&iwqp->close_timer_started) == 1) {
+                                       iwqp->cm_id->add_ref(iwqp->cm_id);
+                                       i40iw_schedule_cm_timer(iwqp->cm_node,
+                                                               (struct i40iw_puda_buf *)iwqp,
+                                                                I40IW_TIMER_TYPE_CLOSE, 1, 0);
+                               }
+                       }
+                       spin_unlock_irqrestore(&iwqp->lock, flags);
                }
        }
        return 0;
index ab3c562d5ba7f7fbfa95cb730576a64a2d038e49..d6fbad8f34aa71848c7291122ad847b6944a27a6 100644 (file)
@@ -778,13 +778,13 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
        }
 
        if (MLX5_CAP_GEN(mdev, tag_matching)) {
-               props->xrq_caps.max_rndv_hdr_size = MLX5_TM_MAX_RNDV_MSG_SIZE;
-               props->xrq_caps.max_num_tags =
+               props->tm_caps.max_rndv_hdr_size = MLX5_TM_MAX_RNDV_MSG_SIZE;
+               props->tm_caps.max_num_tags =
                        (1 << MLX5_CAP_GEN(mdev, log_tag_matching_list_sz)) - 1;
-               props->xrq_caps.flags = IB_TM_CAP_RC;
-               props->xrq_caps.max_ops =
+               props->tm_caps.flags = IB_TM_CAP_RC;
+               props->tm_caps.max_ops =
                        1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
-               props->xrq_caps.max_sge = MLX5_TM_MAX_SGE;
+               props->tm_caps.max_sge = MLX5_TM_MAX_SGE;
        }
 
        if (field_avail(typeof(resp), cqe_comp_caps, uhw->outlen)) {
@@ -3837,11 +3837,13 @@ static int delay_drop_debugfs_init(struct mlx5_ib_dev *dev)
        if (!dbg)
                return -ENOMEM;
 
+       dev->delay_drop.dbg = dbg;
+
        dbg->dir_debugfs =
                debugfs_create_dir("delay_drop",
                                   dev->mdev->priv.dbg_root);
        if (!dbg->dir_debugfs)
-               return -ENOMEM;
+               goto out_debugfs;
 
        dbg->events_cnt_debugfs =
                debugfs_create_atomic_t("num_timeout_events", 0400,
@@ -3865,8 +3867,6 @@ static int delay_drop_debugfs_init(struct mlx5_ib_dev *dev)
        if (!dbg->timeout_debugfs)
                goto out_debugfs;
 
-       dev->delay_drop.dbg = dbg;
-
        return 0;
 
 out_debugfs:
index 914f212e7ef60652a655682a2d668c9cec19b64a..f3dbd75a0a968eade1c316e0fec9179e0012730a 100644 (file)
@@ -50,13 +50,9 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
 {
        unsigned long tmp;
        unsigned long m;
-       int i, k;
-       u64 base = 0;
-       int p = 0;
-       int skip;
-       int mask;
-       u64 len;
-       u64 pfn;
+       u64 base = ~0, p = 0;
+       u64 len, pfn;
+       int i = 0;
        struct scatterlist *sg;
        int entry;
        unsigned long page_shift = umem->page_shift;
@@ -76,33 +72,24 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
        m = find_first_bit(&tmp, BITS_PER_LONG);
        if (max_page_shift)
                m = min_t(unsigned long, max_page_shift - page_shift, m);
-       skip = 1 << m;
-       mask = skip - 1;
-       i = 0;
+
        for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
                len = sg_dma_len(sg) >> page_shift;
                pfn = sg_dma_address(sg) >> page_shift;
-               for (k = 0; k < len; k++) {
-                       if (!(i & mask)) {
-                               tmp = (unsigned long)pfn;
-                               m = min_t(unsigned long, m, find_first_bit(&tmp, BITS_PER_LONG));
-                               skip = 1 << m;
-                               mask = skip - 1;
-                               base = pfn;
-                               p = 0;
-                       } else {
-                               if (base + p != pfn) {
-                                       tmp = (unsigned long)p;
-                                       m = find_first_bit(&tmp, BITS_PER_LONG);
-                                       skip = 1 << m;
-                                       mask = skip - 1;
-                                       base = pfn;
-                                       p = 0;
-                               }
-                       }
-                       p++;
-                       i++;
+               if (base + p != pfn) {
+                       /* If either the offset or the new
+                        * base are unaligned update m
+                        */
+                       tmp = (unsigned long)(pfn | p);
+                       if (!IS_ALIGNED(tmp, 1 << m))
+                               m = find_first_bit(&tmp, BITS_PER_LONG);
+
+                       base = pfn;
+                       p = 0;
                }
+
+               p += len;
+               i += len;
        }
 
        if (i) {
index 0e2789d9bb4d0575561aab569e227125cbc38882..37bbc543847a528f73f613df066fdbb4e36484c1 100644 (file)
@@ -47,7 +47,8 @@ enum {
 
 #define MLX5_UMR_ALIGN 2048
 
-static int clean_mr(struct mlx5_ib_mr *mr);
+static int clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
+static int dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
 static int mr_cache_max_order(struct mlx5_ib_dev *dev);
 static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
 
@@ -1270,8 +1271,9 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 
                err = mlx5_ib_update_xlt(mr, 0, ncont, page_shift,
                                         update_xlt_flags);
+
                if (err) {
-                       mlx5_ib_dereg_mr(&mr->ibmr);
+                       dereg_mr(dev, mr);
                        return ERR_PTR(err);
                }
        }
@@ -1356,7 +1358,7 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
                err = mr_umem_get(pd, addr, len, access_flags, &mr->umem,
                                  &npages, &page_shift, &ncont, &order);
                if (err < 0) {
-                       clean_mr(mr);
+                       clean_mr(dev, mr);
                        return err;
                }
        }
@@ -1410,7 +1412,7 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
                if (err) {
                        mlx5_ib_warn(dev, "Failed to rereg UMR\n");
                        ib_umem_release(mr->umem);
-                       clean_mr(mr);
+                       clean_mr(dev, mr);
                        return err;
                }
        }
@@ -1469,9 +1471,8 @@ mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
        }
 }
 
-static int clean_mr(struct mlx5_ib_mr *mr)
+static int clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
 {
-       struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device);
        int allocated_from_cache = mr->allocated_from_cache;
        int err;
 
@@ -1507,10 +1508,8 @@ static int clean_mr(struct mlx5_ib_mr *mr)
        return 0;
 }
 
-int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
+static int dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
 {
-       struct mlx5_ib_dev *dev = to_mdev(ibmr->device);
-       struct mlx5_ib_mr *mr = to_mmr(ibmr);
        int npages = mr->npages;
        struct ib_umem *umem = mr->umem;
 
@@ -1539,7 +1538,7 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
        }
 #endif
 
-       clean_mr(mr);
+       clean_mr(dev, mr);
 
        if (umem) {
                ib_umem_release(umem);
@@ -1549,6 +1548,14 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
        return 0;
 }
 
+int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
+{
+       struct mlx5_ib_dev *dev = to_mdev(ibmr->device);
+       struct mlx5_ib_mr *mr = to_mmr(ibmr);
+
+       return dereg_mr(dev, mr);
+}
+
 struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
                               enum ib_mr_type mr_type,
                               u32 max_num_sg)
index f0dc5f4aa177e26d622574ec638368fcb7d988cf..442b9bdc0f03bc70d955700e51703b14676b1661 100644 (file)
@@ -3232,7 +3232,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
                                            mr->ibmr.iova);
                        set_wqe_32bit_value(wqe->wqe_words,
                                            NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
-                                           mr->ibmr.length);
+                                           lower_32_bits(mr->ibmr.length));
                        set_wqe_32bit_value(wqe->wqe_words,
                                            NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
                        set_wqe_32bit_value(wqe->wqe_words,
@@ -3274,7 +3274,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
                                            mr->npages * 8);
 
                        nes_debug(NES_DBG_IW_TX, "SQ_REG_MR: iova_start: %llx, "
-                                 "length: %d, rkey: %0x, pgl_paddr: %llx, "
+                                 "length: %lld, rkey: %0x, pgl_paddr: %llx, "
                                  "page_list_len: %u, wqe_misc: %x\n",
                                  (unsigned long long) mr->ibmr.iova,
                                  mr->ibmr.length,
index dcb5942f9fb5a830f37e1757dd64cc0d836523b9..65b166cc743748fde5f89153dd96ed1950abb762 100644 (file)
@@ -252,7 +252,10 @@ static int ocrdma_get_mbx_errno(u32 status)
                case OCRDMA_MBX_ADDI_STATUS_INSUFFICIENT_RESOURCES:
                        err_num = -EAGAIN;
                        break;
+               default:
+                       err_num = -EFAULT;
                }
+               break;
        default:
                err_num = -EFAULT;
        }
index 663a0c301c4382d942fc594d1529b53a0936811b..984aa3484928d691db083c2c694aa90632d803d7 100644 (file)
@@ -416,9 +416,34 @@ static inline enum ib_wc_status pvrdma_wc_status_to_ib(
        return (enum ib_wc_status)status;
 }
 
-static inline int pvrdma_wc_opcode_to_ib(int opcode)
-{
-       return opcode;
+static inline int pvrdma_wc_opcode_to_ib(unsigned int opcode)
+{
+       switch (opcode) {
+       case PVRDMA_WC_SEND:
+               return IB_WC_SEND;
+       case PVRDMA_WC_RDMA_WRITE:
+               return IB_WC_RDMA_WRITE;
+       case PVRDMA_WC_RDMA_READ:
+               return IB_WC_RDMA_READ;
+       case PVRDMA_WC_COMP_SWAP:
+               return IB_WC_COMP_SWAP;
+       case PVRDMA_WC_FETCH_ADD:
+               return IB_WC_FETCH_ADD;
+       case PVRDMA_WC_LOCAL_INV:
+               return IB_WC_LOCAL_INV;
+       case PVRDMA_WC_FAST_REG_MR:
+               return IB_WC_REG_MR;
+       case PVRDMA_WC_MASKED_COMP_SWAP:
+               return IB_WC_MASKED_COMP_SWAP;
+       case PVRDMA_WC_MASKED_FETCH_ADD:
+               return IB_WC_MASKED_FETCH_ADD;
+       case PVRDMA_WC_RECV:
+               return IB_WC_RECV;
+       case PVRDMA_WC_RECV_RDMA_WITH_IMM:
+               return IB_WC_RECV_RDMA_WITH_IMM;
+       default:
+               return IB_WC_SEND;
+       }
 }
 
 static inline int pvrdma_wc_flags_to_ib(int flags)
index 14b62f7472b4f6632f344d7d4ac2eb81518cf3c8..7774654c2ccbce600f99e751c7b37e15e7f1dd8a 100644 (file)
@@ -823,12 +823,18 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
            wc->status != IB_WC_WR_FLUSH_ERR) {
                struct ipoib_neigh *neigh;
 
-               if (wc->status != IB_WC_RNR_RETRY_EXC_ERR)
-                       ipoib_warn(priv, "failed cm send event (status=%d, wrid=%d vend_err %x)\n",
-                                  wc->status, wr_id, wc->vendor_err);
+               /* IB_WC[_RNR]_RETRY_EXC_ERR error is part of the life cycle,
+                * so don't make waves.
+                */
+               if (wc->status == IB_WC_RNR_RETRY_EXC_ERR ||
+                   wc->status == IB_WC_RETRY_EXC_ERR)
+                       ipoib_dbg(priv,
+                                 "%s: failed cm send event (status=%d, wrid=%d vend_err 0x%x)\n",
+                                  __func__, wc->status, wr_id, wc->vendor_err);
                else
-                       ipoib_dbg(priv, "failed cm send event (status=%d, wrid=%d vend_err %x)\n",
-                                 wc->status, wr_id, wc->vendor_err);
+                       ipoib_warn(priv,
+                                   "%s: failed cm send event (status=%d, wrid=%d vend_err 0x%x)\n",
+                                  __func__, wc->status, wr_id, wc->vendor_err);
 
                spin_lock_irqsave(&priv->lock, flags);
                neigh = tx->neigh;
index 2e075377242e2baccc54cda5859d5b3ba7e768d0..6cd61638b44142029b85d0f057b8d04c6b2138c6 100644 (file)
@@ -1000,19 +1000,6 @@ static inline int update_parent_pkey(struct ipoib_dev_priv *priv)
                 */
                priv->dev->broadcast[8] = priv->pkey >> 8;
                priv->dev->broadcast[9] = priv->pkey & 0xff;
-
-               /*
-                * Update the broadcast address in the priv->broadcast object,
-                * in case it already exists, otherwise no one will do that.
-                */
-               if (priv->broadcast) {
-                       spin_lock_irq(&priv->lock);
-                       memcpy(priv->broadcast->mcmember.mgid.raw,
-                              priv->dev->broadcast + 4,
-                       sizeof(union ib_gid));
-                       spin_unlock_irq(&priv->lock);
-               }
-
                return 0;
        }
 
index bac95b509a9b2edc23af7b5e8505fc03acbb80c0..dcc77014018db037cd24540dfe8ddf06d9b70fef 100644 (file)
@@ -2180,6 +2180,7 @@ static struct net_device *ipoib_add_port(const char *format,
 {
        struct ipoib_dev_priv *priv;
        struct ib_port_attr attr;
+       struct rdma_netdev *rn;
        int result = -ENOMEM;
 
        priv = ipoib_intf_alloc(hca, port, format);
@@ -2279,7 +2280,8 @@ register_failed:
        ipoib_dev_cleanup(priv->dev);
 
 device_init_failed:
-       free_netdev(priv->dev);
+       rn = netdev_priv(priv->dev);
+       rn->free_rdma_netdev(priv->dev);
        kfree(priv);
 
 alloc_mem_failed:
@@ -2328,7 +2330,7 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
                return;
 
        list_for_each_entry_safe(priv, tmp, dev_list, list) {
-               struct rdma_netdev *rn = netdev_priv(priv->dev);
+               struct rdma_netdev *parent_rn = netdev_priv(priv->dev);
 
                ib_unregister_event_handler(&priv->event_handler);
                flush_workqueue(ipoib_workqueue);
@@ -2350,10 +2352,15 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
                unregister_netdev(priv->dev);
                mutex_unlock(&priv->sysfs_mutex);
 
-               rn->free_rdma_netdev(priv->dev);
+               parent_rn->free_rdma_netdev(priv->dev);
+
+               list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) {
+                       struct rdma_netdev *child_rn;
 
-               list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list)
+                       child_rn = netdev_priv(cpriv->dev);
+                       child_rn->free_rdma_netdev(cpriv->dev);
                        kfree(cpriv);
+               }
 
                kfree(priv);
        }
index 9927cd6b7082b1dc24cbfa38431e6156646bf15f..55a9b71ed05a7ff8ff0ac9f7eb84af1d4f6476a0 100644 (file)
@@ -141,14 +141,17 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
                return restart_syscall();
        }
 
-       priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
-       if (!priv) {
+       if (!down_write_trylock(&ppriv->vlan_rwsem)) {
                rtnl_unlock();
                mutex_unlock(&ppriv->sysfs_mutex);
-               return -ENOMEM;
+               return restart_syscall();
        }
 
-       down_write(&ppriv->vlan_rwsem);
+       priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
+       if (!priv) {
+               result = -ENOMEM;
+               goto out;
+       }
 
        /*
         * First ensure this isn't a duplicate. We check the parent device and
@@ -175,8 +178,11 @@ out:
        rtnl_unlock();
        mutex_unlock(&ppriv->sysfs_mutex);
 
-       if (result) {
-               free_netdev(priv->dev);
+       if (result && priv) {
+               struct rdma_netdev *rn;
+
+               rn = netdev_priv(priv->dev);
+               rn->free_rdma_netdev(priv->dev);
                kfree(priv);
        }
 
@@ -204,7 +210,12 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
                return restart_syscall();
        }
 
-       down_write(&ppriv->vlan_rwsem);
+       if (!down_write_trylock(&ppriv->vlan_rwsem)) {
+               rtnl_unlock();
+               mutex_unlock(&ppriv->sysfs_mutex);
+               return restart_syscall();
+       }
+
        list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
                if (priv->pkey == pkey &&
                    priv->child_type == IPOIB_LEGACY_CHILD) {
@@ -224,7 +235,10 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
        mutex_unlock(&ppriv->sysfs_mutex);
 
        if (dev) {
-               free_netdev(dev);
+               struct rdma_netdev *rn;
+
+               rn = netdev_priv(dev);
+               rn->free_rdma_netdev(priv->dev);
                kfree(priv);
                return 0;
        }
index 9c3e9ab53a415710b0e8bef65647efc4716dc239..322209d5ff5829b6dfd5f4de54f4d11fe141c63d 100644 (file)
@@ -154,7 +154,7 @@ static void iser_dump_page_vec(struct iser_page_vec *page_vec)
 {
        int i;
 
-       iser_err("page vec npages %d data length %d\n",
+       iser_err("page vec npages %d data length %lld\n",
                 page_vec->npages, page_vec->fake_mr.length);
        for (i = 0; i < page_vec->npages; i++)
                iser_err("vec[%d]: %llx\n", i, page_vec->pages[i]);
index 8f2042432c85151b25fab1e885fe321e1563d641..66a46c84e28f543bc27f91479d5da669984e0d89 100644 (file)
@@ -237,9 +237,15 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file)
 EXPORT_SYMBOL_GPL(input_ff_erase);
 
 /*
- * flush_effects - erase all effects owned by a file handle
+ * input_ff_flush - erase all effects owned by a file handle
+ * @dev: input device to erase effect from
+ * @file: purported owner of the effects
+ *
+ * This function erases all force-feedback effects associated with
+ * the given owner from specified device. Note that @file may be %NULL,
+ * in which case all effects will be erased.
  */
-static int flush_effects(struct input_dev *dev, struct file *file)
+int input_ff_flush(struct input_dev *dev, struct file *file)
 {
        struct ff_device *ff = dev->ff;
        int i;
@@ -255,6 +261,7 @@ static int flush_effects(struct input_dev *dev, struct file *file)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(input_ff_flush);
 
 /**
  * input_ff_event() - generic handler for force-feedback events
@@ -343,7 +350,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
        mutex_init(&ff->mutex);
 
        dev->ff = ff;
-       dev->flush = flush_effects;
+       dev->flush = input_ff_flush;
        dev->event = input_ff_event;
        __set_bit(EV_FF, dev->evbit);
 
index 022be0e22eba97b10b95e653f48cee44f1d4ba36..443151de90c6b506f6847b656a68d84577576ad1 100644 (file)
@@ -98,14 +98,15 @@ static int uinput_request_reserve_slot(struct uinput_device *udev,
                                        uinput_request_alloc_id(udev, request));
 }
 
-static void uinput_request_done(struct uinput_device *udev,
-                               struct uinput_request *request)
+static void uinput_request_release_slot(struct uinput_device *udev,
+                                       unsigned int id)
 {
        /* Mark slot as available */
-       udev->requests[request->id] = NULL;
-       wake_up(&udev->requests_waitq);
+       spin_lock(&udev->requests_lock);
+       udev->requests[id] = NULL;
+       spin_unlock(&udev->requests_lock);
 
-       complete(&request->done);
+       wake_up(&udev->requests_waitq);
 }
 
 static int uinput_request_send(struct uinput_device *udev,
@@ -138,20 +139,22 @@ static int uinput_request_send(struct uinput_device *udev,
 static int uinput_request_submit(struct uinput_device *udev,
                                 struct uinput_request *request)
 {
-       int error;
+       int retval;
 
-       error = uinput_request_reserve_slot(udev, request);
-       if (error)
-               return error;
+       retval = uinput_request_reserve_slot(udev, request);
+       if (retval)
+               return retval;
 
-       error = uinput_request_send(udev, request);
-       if (error) {
-               uinput_request_done(udev, request);
-               return error;
-       }
+       retval = uinput_request_send(udev, request);
+       if (retval)
+               goto out;
 
        wait_for_completion(&request->done);
-       return request->retval;
+       retval = request->retval;
+
+ out:
+       uinput_request_release_slot(udev, request->id);
+       return retval;
 }
 
 /*
@@ -169,7 +172,7 @@ static void uinput_flush_requests(struct uinput_device *udev)
                request = udev->requests[i];
                if (request) {
                        request->retval = -ENODEV;
-                       uinput_request_done(udev, request);
+                       complete(&request->done);
                }
        }
 
@@ -230,6 +233,18 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
        return uinput_request_submit(udev, &request);
 }
 
+static int uinput_dev_flush(struct input_dev *dev, struct file *file)
+{
+       /*
+        * If we are called with file == NULL that means we are tearing
+        * down the device, and therefore we can not handle FF erase
+        * requests: either we are handling UI_DEV_DESTROY (and holding
+        * the udev->mutex), or the file descriptor is closed and there is
+        * nobody on the other side anymore.
+        */
+       return file ? input_ff_flush(dev, file) : 0;
+}
+
 static void uinput_destroy_device(struct uinput_device *udev)
 {
        const char *name, *phys;
@@ -297,6 +312,12 @@ static int uinput_create_device(struct uinput_device *udev)
                dev->ff->playback = uinput_dev_playback;
                dev->ff->set_gain = uinput_dev_set_gain;
                dev->ff->set_autocenter = uinput_dev_set_autocenter;
+               /*
+                * The standard input_ff_flush() implementation does
+                * not quite work for uinput as we can't reasonably
+                * handle FF requests during device teardown.
+                */
+               dev->flush = uinput_dev_flush;
        }
 
        error = input_register_device(udev->dev);
@@ -939,7 +960,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
                        }
 
                        req->retval = ff_up.retval;
-                       uinput_request_done(udev, req);
+                       complete(&req->done);
                        goto out;
 
                case UI_END_FF_ERASE:
@@ -955,7 +976,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
                        }
 
                        req->retval = ff_erase.retval;
-                       uinput_request_done(udev, req);
+                       complete(&req->done);
                        goto out;
        }
 
index 15b1330606c1c3fcfc28cf109f89987d0425f75a..e19eb60b3d2f5adcdf0182673680de25ddd15483 100644 (file)
@@ -598,7 +598,7 @@ static int elan_i2c_write_fw_block(struct i2c_client *client,
        }
 
        /* Wait for F/W to update one page ROM data. */
-       msleep(20);
+       msleep(35);
 
        error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val);
        if (error) {
index 49bd2ab8c5075859bca8e2e90519e7da6cd6f48f..f3a21343e636a8f26066f206129d45924cdc9588 100644 (file)
@@ -278,7 +278,7 @@ config EXYNOS_IOMMU_DEBUG
 config IPMMU_VMSA
        bool "Renesas VMSA-compatible IPMMU"
        depends on ARM || IOMMU_DMA
-       depends on ARCH_RENESAS || COMPILE_TEST
+       depends on ARCH_RENESAS || (COMPILE_TEST && !GENERIC_ATOMIC64)
        select IOMMU_API
        select IOMMU_IO_PGTABLE_LPAE
        select ARM_DMA_USE_IOMMU
@@ -373,7 +373,8 @@ config MTK_IOMMU_V1
 config QCOM_IOMMU
        # Note: iommu drivers cannot (yet?) be built as modules
        bool "Qualcomm IOMMU Support"
-       depends on ARCH_QCOM || COMPILE_TEST
+       depends on ARCH_QCOM || (COMPILE_TEST && !GENERIC_ATOMIC64)
+       depends on HAS_DMA
        select IOMMU_API
        select IOMMU_IO_PGTABLE_LPAE
        select ARM_DMA_USE_IOMMU
index 382de42b835939e167604053060e9944e19131ba..6fe2d03460730cabe0aa78060114844ad1a2a3cf 100644 (file)
@@ -874,7 +874,7 @@ static bool copy_device_table(void)
                hi = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET + 4);
                entry = (((u64) hi) << 32) + lo;
                if (last_entry && last_entry != entry) {
-                       pr_err("IOMMU:%d should use the same dev table as others!/n",
+                       pr_err("IOMMU:%d should use the same dev table as others!\n",
                                iommu->index);
                        return false;
                }
@@ -882,7 +882,7 @@ static bool copy_device_table(void)
 
                old_devtb_size = ((entry & ~PAGE_MASK) + 1) << 12;
                if (old_devtb_size != dev_table_size) {
-                       pr_err("The device table size of IOMMU:%d is not expected!/n",
+                       pr_err("The device table size of IOMMU:%d is not expected!\n",
                                iommu->index);
                        return false;
                }
@@ -890,7 +890,7 @@ static bool copy_device_table(void)
 
        old_devtb_phys = entry & PAGE_MASK;
        if (old_devtb_phys >= 0x100000000ULL) {
-               pr_err("The address of old device table is above 4G, not trustworthy!/n");
+               pr_err("The address of old device table is above 4G, not trustworthy!\n");
                return false;
        }
        old_devtb = memremap(old_devtb_phys, dev_table_size, MEMREMAP_WB);
@@ -901,7 +901,7 @@ static bool copy_device_table(void)
        old_dev_tbl_cpy = (void *)__get_free_pages(gfp_flag,
                                get_order(dev_table_size));
        if (old_dev_tbl_cpy == NULL) {
-               pr_err("Failed to allocate memory for copying old device table!/n");
+               pr_err("Failed to allocate memory for copying old device table!\n");
                return false;
        }
 
index ca5ebaeafd6acee8d11033b34ba912eeebc04689..57c920c1372d09f927a7dcdeadc25375bf4164a8 100644 (file)
@@ -497,7 +497,7 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
 #define        dmar_parse_one_rhsa             dmar_res_noop
 #endif
 
-static void __init
+static void
 dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
 {
        struct acpi_dmar_hardware_unit *drhd;
index d665d0dc16e8f787813a6106d15bd83afacc4f34..6961fc393f0b25828f5981fad35ea744c7768b41 100644 (file)
@@ -245,7 +245,7 @@ static void __arm_v7s_free_table(void *table, int lvl,
 static void __arm_v7s_pte_sync(arm_v7s_iopte *ptep, int num_entries,
                               struct io_pgtable_cfg *cfg)
 {
-       if (!(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA))
+       if (cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA)
                return;
 
        dma_sync_single_for_device(cfg->iommu_dev, __arm_v7s_dma_addr(ptep),
index bd515be5b380e32ac224b55d5b9a2dfff26a15ef..16d33ac19db0f77837c30f44de044a3a46b9c558 100644 (file)
@@ -371,7 +371,8 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
        int ret;
 
        spin_lock_irqsave(&dom->pgtlock, flags);
-       ret = dom->iop->map(dom->iop, iova, paddr, size, prot);
+       ret = dom->iop->map(dom->iop, iova, paddr & DMA_BIT_MASK(32),
+                           size, prot);
        spin_unlock_irqrestore(&dom->pgtlock, flags);
 
        return ret;
index e60e3dba85a0d7c0457d9bdf650de2c350a5d11b..50947ebb6d1700e3f81acb5806c1b1a8b183c145 100644 (file)
@@ -157,10 +157,7 @@ static int of_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
 
        err = of_iommu_xlate(info->dev, &iommu_spec);
        of_node_put(iommu_spec.np);
-       if (err)
-               return err;
-
-       return info->np == pdev->bus->dev.of_node;
+       return err;
 }
 
 const struct iommu_ops *of_iommu_configure(struct device *dev,
index 519149ec905378d59e9abb931515542b91b133c6..b5df99c6f680f940a48223455a377a1ef8e07cb2 100644 (file)
@@ -1042,7 +1042,7 @@ static int get_cpu_number(struct device_node *dn)
 {
        const __be32 *cell;
        u64 hwid;
-       int i;
+       int cpu;
 
        cell = of_get_property(dn, "reg", NULL);
        if (!cell)
@@ -1056,9 +1056,9 @@ static int get_cpu_number(struct device_node *dn)
        if (hwid & ~MPIDR_HWID_BITMASK)
                return -1;
 
-       for (i = 0; i < num_possible_cpus(); i++)
-               if (cpu_logical_map(i) == hwid)
-                       return i;
+       for_each_possible_cpu(cpu)
+               if (cpu_logical_map(cpu) == hwid)
+                       return cpu;
 
        return -1;
 }
index 2370e6d9e603ad17a57016974608b8aade9f85a2..cd0bcc3b7e33709a472c1952c5ee7ccdf1ea0382 100644 (file)
@@ -173,7 +173,9 @@ int its_map_vlpi(int irq, struct its_vlpi_map *map)
 {
        struct its_cmd_info info = {
                .cmd_type = MAP_VLPI,
-               .map      = map,
+               {
+                       .map      = map,
+               },
        };
 
        /*
@@ -189,7 +191,9 @@ int its_get_vlpi(int irq, struct its_vlpi_map *map)
 {
        struct its_cmd_info info = {
                .cmd_type = GET_VLPI,
-               .map      = map,
+               {
+                       .map      = map,
+               },
        };
 
        return irq_set_vcpu_affinity(irq, &info);
@@ -205,7 +209,9 @@ int its_prop_update_vlpi(int irq, u8 config, bool inv)
 {
        struct its_cmd_info info = {
                .cmd_type = inv ? PROP_UPDATE_AND_INV_VLPI : PROP_UPDATE_VLPI,
-               .config   = config,
+               {
+                       .config   = config,
+               },
        };
 
        return irq_set_vcpu_affinity(irq, &info);
index 6e52a88bbd9e9cc7a832d67b13c717efe5cb039a..c90976d7e53ccc596b65a0864ef169f1aa1fafd8 100644 (file)
@@ -169,20 +169,19 @@ static void gic_mask_irq(struct irq_data *d)
 {
        unsigned int intr = GIC_HWIRQ_TO_SHARED(d->hwirq);
 
-       write_gic_rmask(BIT(intr));
+       write_gic_rmask(intr);
        gic_clear_pcpu_masks(intr);
 }
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-       struct cpumask *affinity = irq_data_get_affinity_mask(d);
        unsigned int intr = GIC_HWIRQ_TO_SHARED(d->hwirq);
        unsigned int cpu;
 
-       write_gic_smask(BIT(intr));
+       write_gic_smask(intr);
 
        gic_clear_pcpu_masks(intr);
-       cpu = cpumask_first_and(affinity, cpu_online_mask);
+       cpu = cpumask_first(irq_data_get_effective_affinity_mask(d));
        set_bit(intr, per_cpu_ptr(pcpu_masks, cpu));
 }
 
@@ -420,13 +419,17 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
                                     irq_hw_number_t hw, unsigned int cpu)
 {
        int intr = GIC_HWIRQ_TO_SHARED(hw);
+       struct irq_data *data;
        unsigned long flags;
 
+       data = irq_get_irq_data(virq);
+
        spin_lock_irqsave(&gic_lock, flags);
        write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
        write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
        gic_clear_pcpu_masks(intr);
        set_bit(intr, per_cpu_ptr(pcpu_masks, cpu));
+       irq_data_update_effective_affinity(data, cpumask_of(cpu));
        spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
@@ -645,7 +648,7 @@ static int __init gic_of_init(struct device_node *node,
 
        /* Find the first available CPU vector. */
        i = 0;
-       reserved = (C_SW0 | C_SW1) >> __fls(C_SW0);
+       reserved = (C_SW0 | C_SW1) >> __ffs(C_SW0);
        while (!of_property_read_u32_index(node, "mti,reserved-cpu-vectors",
                                           i++, &cpu_vec))
                reserved |= BIT(cpu_vec);
@@ -684,11 +687,11 @@ static int __init gic_of_init(struct device_node *node,
 
        gicconfig = read_gic_config();
        gic_shared_intrs = gicconfig & GIC_CONFIG_NUMINTERRUPTS;
-       gic_shared_intrs >>= __fls(GIC_CONFIG_NUMINTERRUPTS);
+       gic_shared_intrs >>= __ffs(GIC_CONFIG_NUMINTERRUPTS);
        gic_shared_intrs = (gic_shared_intrs + 1) * 8;
 
        gic_vpes = gicconfig & GIC_CONFIG_PVPS;
-       gic_vpes >>= __fls(GIC_CONFIG_PVPS);
+       gic_vpes >>= __ffs(GIC_CONFIG_PVPS);
        gic_vpes = gic_vpes + 1;
 
        if (cpu_has_veic) {
@@ -767,7 +770,7 @@ static int __init gic_of_init(struct device_node *node,
        for (i = 0; i < gic_shared_intrs; i++) {
                change_gic_pol(i, GIC_POL_ACTIVE_HIGH);
                change_gic_trig(i, GIC_TRIG_LEVEL);
-               write_gic_rmask(BIT(i));
+               write_gic_rmask(i);
        }
 
        for (i = 0; i < gic_vpes; i++) {
index 6c44609fd83a0f266df74b80bbe91f84b3bd4a67..cd2b3c69771a24b62a7952a8e7c626fde5459c6b 100644 (file)
@@ -825,7 +825,6 @@ isdn_ppp_write(int min, struct file *file, const char __user *buf, int count)
        isdn_net_local *lp;
        struct ippp_struct *is;
        int proto;
-       unsigned char protobuf[4];
 
        is = file->private_data;
 
@@ -839,24 +838,28 @@ isdn_ppp_write(int min, struct file *file, const char __user *buf, int count)
        if (!lp)
                printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
        else {
-               /*
-                * Don't reset huptimer for
-                * LCP packets. (Echo requests).
-                */
-               if (copy_from_user(protobuf, buf, 4))
-                       return -EFAULT;
-               proto = PPP_PROTOCOL(protobuf);
-               if (proto != PPP_LCP)
-                       lp->huptimer = 0;
+               if (lp->isdn_device < 0 || lp->isdn_channel < 0) {
+                       unsigned char protobuf[4];
+                       /*
+                        * Don't reset huptimer for
+                        * LCP packets. (Echo requests).
+                        */
+                       if (copy_from_user(protobuf, buf, 4))
+                               return -EFAULT;
+
+                       proto = PPP_PROTOCOL(protobuf);
+                       if (proto != PPP_LCP)
+                               lp->huptimer = 0;
 
-               if (lp->isdn_device < 0 || lp->isdn_channel < 0)
                        return 0;
+               }
 
                if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
                    lp->dialstate == 0 &&
                    (lp->flags & ISDN_NET_CONNECTED)) {
                        unsigned short hl;
                        struct sk_buff *skb;
+                       unsigned char *cpy_buf;
                        /*
                         * we need to reserve enough space in front of
                         * sk_buff. old call to dev_alloc_skb only reserved
@@ -869,11 +872,21 @@ isdn_ppp_write(int min, struct file *file, const char __user *buf, int count)
                                return count;
                        }
                        skb_reserve(skb, hl);
-                       if (copy_from_user(skb_put(skb, count), buf, count))
+                       cpy_buf = skb_put(skb, count);
+                       if (copy_from_user(cpy_buf, buf, count))
                        {
                                kfree_skb(skb);
                                return -EFAULT;
                        }
+
+                       /*
+                        * Don't reset huptimer for
+                        * LCP packets. (Echo requests).
+                        */
+                       proto = PPP_PROTOCOL(cpy_buf);
+                       if (proto != PPP_LCP)
+                               lp->huptimer = 0;
+
                        if (is->debug & 0x40) {
                                printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
                                isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
index bbbbe08982332a53fdad499cd5643f85b97e5898..9a257f9693009c7ec3a163dc83e7c0b2e5839dde 100644 (file)
 #define AS_PEAK_mA_TO_REG(a) \
        ((min_t(u32, AS_PEAK_mA_MAX, a) - 1250) / 250)
 
+/* LED numbers for Devicetree */
+#define AS_LED_FLASH                           0
+#define AS_LED_INDICATOR                       1
+
 enum as_mode {
        AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
        AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
@@ -491,10 +495,29 @@ static int as3645a_parse_node(struct as3645a *flash,
                              struct device_node *node)
 {
        struct as3645a_config *cfg = &flash->cfg;
+       struct device_node *child;
        const char *name;
        int rval;
 
-       flash->flash_node = of_get_child_by_name(node, "flash");
+       for_each_child_of_node(node, child) {
+               u32 id = 0;
+
+               of_property_read_u32(child, "reg", &id);
+
+               switch (id) {
+               case AS_LED_FLASH:
+                       flash->flash_node = of_node_get(child);
+                       break;
+               case AS_LED_INDICATOR:
+                       flash->indicator_node = of_node_get(child);
+                       break;
+               default:
+                       dev_warn(&flash->client->dev,
+                                "unknown LED %u encountered, ignoring\n", id);
+                       break;
+               }
+       }
+
        if (!flash->flash_node) {
                dev_err(&flash->client->dev, "can't find flash node\n");
                return -ENODEV;
@@ -534,11 +557,10 @@ static int as3645a_parse_node(struct as3645a *flash,
        of_property_read_u32(flash->flash_node, "voltage-reference",
                             &cfg->voltage_reference);
 
-       of_property_read_u32(flash->flash_node, "peak-current-limit",
+       of_property_read_u32(flash->flash_node, "ams,input-max-microamp",
                             &cfg->peak);
        cfg->peak = AS_PEAK_mA_TO_REG(cfg->peak);
 
-       flash->indicator_node = of_get_child_by_name(node, "indicator");
        if (!flash->indicator_node) {
                dev_warn(&flash->client->dev,
                         "can't find indicator node\n");
@@ -721,6 +743,7 @@ static int as3645a_remove(struct i2c_client *client)
        as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
 
        v4l2_flash_release(flash->vf);
+       v4l2_flash_release(flash->vfind);
 
        led_classdev_flash_unregister(&flash->fled);
        led_classdev_unregister(&flash->iled_cdev);
index 5bfe285ea9d1c815ae8014064a29e4a08566d374..1ac58c5651b7f8086ccba297547ff13823804706 100644 (file)
@@ -3238,7 +3238,7 @@ static int raid_map(struct dm_target *ti, struct bio *bio)
        if (unlikely(bio_end_sector(bio) > mddev->array_sectors))
                return DM_MAPIO_REQUEUE;
 
-       mddev->pers->make_request(mddev, bio);
+       md_handle_request(mddev, bio);
 
        return DM_MAPIO_SUBMITTED;
 }
index 08fcaebc61bdb52b92f8ba37ccd4d2b3dac41779..0ff1bbf6c90e5cebc782268313ce39f8c66f7270 100644 (file)
@@ -266,6 +266,37 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
  * call has finished, the bio has been linked into some internal structure
  * and so is visible to ->quiesce(), so we don't need the refcount any more.
  */
+void md_handle_request(struct mddev *mddev, struct bio *bio)
+{
+check_suspended:
+       rcu_read_lock();
+       if (mddev->suspended) {
+               DEFINE_WAIT(__wait);
+               for (;;) {
+                       prepare_to_wait(&mddev->sb_wait, &__wait,
+                                       TASK_UNINTERRUPTIBLE);
+                       if (!mddev->suspended)
+                               break;
+                       rcu_read_unlock();
+                       schedule();
+                       rcu_read_lock();
+               }
+               finish_wait(&mddev->sb_wait, &__wait);
+       }
+       atomic_inc(&mddev->active_io);
+       rcu_read_unlock();
+
+       if (!mddev->pers->make_request(mddev, bio)) {
+               atomic_dec(&mddev->active_io);
+               wake_up(&mddev->sb_wait);
+               goto check_suspended;
+       }
+
+       if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
+               wake_up(&mddev->sb_wait);
+}
+EXPORT_SYMBOL(md_handle_request);
+
 static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
 {
        const int rw = bio_data_dir(bio);
@@ -285,23 +316,6 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
                bio_endio(bio);
                return BLK_QC_T_NONE;
        }
-check_suspended:
-       rcu_read_lock();
-       if (mddev->suspended) {
-               DEFINE_WAIT(__wait);
-               for (;;) {
-                       prepare_to_wait(&mddev->sb_wait, &__wait,
-                                       TASK_UNINTERRUPTIBLE);
-                       if (!mddev->suspended)
-                               break;
-                       rcu_read_unlock();
-                       schedule();
-                       rcu_read_lock();
-               }
-               finish_wait(&mddev->sb_wait, &__wait);
-       }
-       atomic_inc(&mddev->active_io);
-       rcu_read_unlock();
 
        /*
         * save the sectors now since our bio can
@@ -310,20 +324,14 @@ check_suspended:
        sectors = bio_sectors(bio);
        /* bio could be mergeable after passing to underlayer */
        bio->bi_opf &= ~REQ_NOMERGE;
-       if (!mddev->pers->make_request(mddev, bio)) {
-               atomic_dec(&mddev->active_io);
-               wake_up(&mddev->sb_wait);
-               goto check_suspended;
-       }
+
+       md_handle_request(mddev, bio);
 
        cpu = part_stat_lock();
        part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
        part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors);
        part_stat_unlock();
 
-       if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
-               wake_up(&mddev->sb_wait);
-
        return BLK_QC_T_NONE;
 }
 
@@ -439,16 +447,22 @@ static void md_submit_flush_data(struct work_struct *ws)
        struct mddev *mddev = container_of(ws, struct mddev, flush_work);
        struct bio *bio = mddev->flush_bio;
 
+       /*
+        * must reset flush_bio before calling into md_handle_request to avoid a
+        * deadlock, because other bios passed md_handle_request suspend check
+        * could wait for this and below md_handle_request could wait for those
+        * bios because of suspend check
+        */
+       mddev->flush_bio = NULL;
+       wake_up(&mddev->sb_wait);
+
        if (bio->bi_iter.bi_size == 0)
                /* an empty barrier - all done */
                bio_endio(bio);
        else {
                bio->bi_opf &= ~REQ_PREFLUSH;
-               mddev->pers->make_request(mddev, bio);
+               md_handle_request(mddev, bio);
        }
-
-       mddev->flush_bio = NULL;
-       wake_up(&mddev->sb_wait);
 }
 
 void md_flush_request(struct mddev *mddev, struct bio *bio)
index 561d22b9a9a8acc9479cabc389948753ffe703eb..d8287d3cd1bf81b048e90166d91afe76566202b3 100644 (file)
@@ -692,6 +692,7 @@ extern void md_stop_writes(struct mddev *mddev);
 extern int md_rdev_init(struct md_rdev *rdev);
 extern void md_rdev_clear(struct md_rdev *rdev);
 
+extern void md_handle_request(struct mddev *mddev, struct bio *bio);
 extern void mddev_suspend(struct mddev *mddev);
 extern void mddev_resume(struct mddev *mddev);
 extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
index 4188a488114814aadf7df7b4c2ba07240b8e0408..928e24a071338ab6e1fe7668c8caa42b2803ccfe 100644 (file)
@@ -811,6 +811,14 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
                        spin_unlock(&head->batch_head->batch_lock);
                        goto unlock_out;
                }
+               /*
+                * We must assign batch_head of this stripe within the
+                * batch_lock, otherwise clear_batch_ready of batch head
+                * stripe could clear BATCH_READY bit of this stripe and
+                * this stripe->batch_head doesn't get assigned, which
+                * could confuse clear_batch_ready for this stripe
+                */
+               sh->batch_head = head->batch_head;
 
                /*
                 * at this point, head's BATCH_READY could be cleared, but we
@@ -818,8 +826,6 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
                 */
                list_add(&sh->batch_list, &head->batch_list);
                spin_unlock(&head->batch_head->batch_lock);
-
-               sh->batch_head = head->batch_head;
        } else {
                head->batch_head = head;
                sh->batch_head = head->batch_head;
@@ -4599,7 +4605,8 @@ static void break_stripe_batch_list(struct stripe_head *head_sh,
 
                set_mask_bits(&sh->state, ~(STRIPE_EXPAND_SYNC_FLAGS |
                                            (1 << STRIPE_PREREAD_ACTIVE) |
-                                           (1 << STRIPE_DEGRADED)),
+                                           (1 << STRIPE_DEGRADED) |
+                                           (1 << STRIPE_ON_UNPLUG_LIST)),
                              head_sh->state & (1 << STRIPE_INSYNC));
 
                sh->check_state = head_sh->check_state;
@@ -6568,14 +6575,17 @@ static ssize_t
 raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len)
 {
        struct r5conf *conf;
-       unsigned long new;
+       unsigned int new;
        int err;
        struct r5worker_group *new_groups, *old_groups;
        int group_cnt, worker_cnt_per_group;
 
        if (len >= PAGE_SIZE)
                return -EINVAL;
-       if (kstrtoul(page, 10, &new))
+       if (kstrtouint(page, 10, &new))
+               return -EINVAL;
+       /* 8192 should be big enough */
+       if (new > 8192)
                return -EINVAL;
 
        err = mddev_lock(mddev);
index affa7370ba827917a78cff55c4e503220ab1ebaa..74c663b1c0a7418c53ef0d7fa4ae27e2499d1ff7 100644 (file)
@@ -242,6 +242,12 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
                limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
 
+       /*
+        * mmc_init_request() depends on card->bouncesz so it must be calculated
+        * before blk_init_allocated_queue() starts allocating requests.
+        */
+       card->bouncesz = mmc_queue_calc_bouncesz(host);
+
        mq->card = card;
        mq->queue = blk_alloc_queue(GFP_KERNEL);
        if (!mq->queue)
@@ -265,7 +271,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        if (mmc_can_erase(card))
                mmc_queue_setup_discard(mq->queue, card);
 
-       card->bouncesz = mmc_queue_calc_bouncesz(host);
        if (card->bouncesz) {
                blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512);
                blk_queue_max_segments(mq->queue, card->bouncesz / 512);
index 02179ed2a40d7a87d0d1ae7ed43e95388ef36a72..8c15637178ff3cec73b637633710f84e4dd93a00 100644 (file)
@@ -5,7 +5,7 @@
 comment "MMC/SD/SDIO Host Controller Drivers"
 
 config MMC_DEBUG
-       bool "MMC host drivers debugginG"
+       bool "MMC host drivers debugging"
        depends on MMC != n
        help
          This is an option for use by developers; most people should
index b9cc9599879978972b4c8c96f9dbddc26caebb2f..eee08d81b24214c3ea0c5555fa1f1f419249f9d6 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright (C) 2016 Cavium Inc.
  */
+#include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/mmc/mmc.h>
@@ -149,8 +150,11 @@ error:
        for (i = 0; i < CAVIUM_MAX_MMC; i++) {
                if (host->slot[i])
                        cvm_mmc_of_slot_remove(host->slot[i]);
-               if (host->slot_pdev[i])
+               if (host->slot_pdev[i]) {
+                       get_device(&host->slot_pdev[i]->dev);
                        of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL);
+                       put_device(&host->slot_pdev[i]->dev);
+               }
        }
        clk_disable_unprepare(host->clk);
        return ret;
index bbaddf18a1b3c4022592f631878441ad19a1fca2..d0ccc6729fd29e734996b28538cd6e8e1745bf2b 100644 (file)
@@ -392,6 +392,7 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = {
 
 enum {
        INTEL_DSM_FNS           =  0,
+       INTEL_DSM_V18_SWITCH    =  3,
        INTEL_DSM_DRV_STRENGTH  =  9,
        INTEL_DSM_D3_RETUNE     = 10,
 };
@@ -557,6 +558,19 @@ static void intel_hs400_enhanced_strobe(struct mmc_host *mmc,
        sdhci_writel(host, val, INTEL_HS400_ES_REG);
 }
 
+static void sdhci_intel_voltage_switch(struct sdhci_host *host)
+{
+       struct sdhci_pci_slot *slot = sdhci_priv(host);
+       struct intel_host *intel_host = sdhci_pci_priv(slot);
+       struct device *dev = &slot->chip->pdev->dev;
+       u32 result = 0;
+       int err;
+
+       err = intel_dsm(intel_host, dev, INTEL_DSM_V18_SWITCH, &result);
+       pr_debug("%s: %s DSM error %d result %u\n",
+                mmc_hostname(host->mmc), __func__, err, result);
+}
+
 static const struct sdhci_ops sdhci_intel_byt_ops = {
        .set_clock              = sdhci_set_clock,
        .set_power              = sdhci_intel_set_power,
@@ -565,6 +579,7 @@ static const struct sdhci_ops sdhci_intel_byt_ops = {
        .reset                  = sdhci_reset,
        .set_uhs_signaling      = sdhci_set_uhs_signaling,
        .hw_reset               = sdhci_pci_hw_reset,
+       .voltage_switch         = sdhci_intel_voltage_switch,
 };
 
 static void byt_read_dsm(struct sdhci_pci_slot *slot)
index 12cf8288d6635eafef4677630d669c1a60238b45..a7293e186e03fc44ccb271405e99fbfaef06d770 100644 (file)
@@ -129,50 +129,6 @@ static int tmio_mmc_next_sg(struct tmio_mmc_host *host)
 
 #define CMDREQ_TIMEOUT 5000
 
-#ifdef CONFIG_MMC_DEBUG
-
-#define STATUS_TO_TEXT(a, status, i) \
-       do { \
-               if ((status) & TMIO_STAT_##a) { \
-                       if ((i)++) \
-                               printk(KERN_DEBUG " | "); \
-                       printk(KERN_DEBUG #a); \
-               } \
-       } while (0)
-
-static void pr_debug_status(u32 status)
-{
-       int i = 0;
-
-       pr_debug("status: %08x = ", status);
-       STATUS_TO_TEXT(CARD_REMOVE, status, i);
-       STATUS_TO_TEXT(CARD_INSERT, status, i);
-       STATUS_TO_TEXT(SIGSTATE, status, i);
-       STATUS_TO_TEXT(WRPROTECT, status, i);
-       STATUS_TO_TEXT(CARD_REMOVE_A, status, i);
-       STATUS_TO_TEXT(CARD_INSERT_A, status, i);
-       STATUS_TO_TEXT(SIGSTATE_A, status, i);
-       STATUS_TO_TEXT(CMD_IDX_ERR, status, i);
-       STATUS_TO_TEXT(STOPBIT_ERR, status, i);
-       STATUS_TO_TEXT(ILL_FUNC, status, i);
-       STATUS_TO_TEXT(CMD_BUSY, status, i);
-       STATUS_TO_TEXT(CMDRESPEND, status, i);
-       STATUS_TO_TEXT(DATAEND, status, i);
-       STATUS_TO_TEXT(CRCFAIL, status, i);
-       STATUS_TO_TEXT(DATATIMEOUT, status, i);
-       STATUS_TO_TEXT(CMDTIMEOUT, status, i);
-       STATUS_TO_TEXT(RXOVERFLOW, status, i);
-       STATUS_TO_TEXT(TXUNDERRUN, status, i);
-       STATUS_TO_TEXT(RXRDY, status, i);
-       STATUS_TO_TEXT(TXRQ, status, i);
-       STATUS_TO_TEXT(ILL_ACCESS, status, i);
-       printk("\n");
-}
-
-#else
-#define pr_debug_status(s)  do { } while (0)
-#endif
-
 static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 {
        struct tmio_mmc_host *host = mmc_priv(mmc);
@@ -762,9 +718,6 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
        status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS);
        ireg = status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask;
 
-       pr_debug_status(status);
-       pr_debug_status(ireg);
-
        /* Clear the status except the interrupt status */
        sd_ctrl_write32_as_16_and_16(host, CTL_STATUS, TMIO_MASK_IRQ);
 
index 5736b0c90b339b6bc3e8e1ae3189341910b958f2..a308e707392d595902b77a03e2078ffe8da97d9e 100644 (file)
@@ -581,6 +581,14 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent,
                slave->mtd.erasesize = parent->erasesize;
        }
 
+       /*
+        * Slave erasesize might differ from the master one if the master
+        * exposes several regions with different erasesize. Adjust
+        * wr_alignment accordingly.
+        */
+       if (!(slave->mtd.flags & MTD_NO_ERASE))
+               wr_alignment = slave->mtd.erasesize;
+
        tmp = slave->offset;
        remainder = do_div(tmp, wr_alignment);
        if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
index 146af82183145d9d5164665aeaccdf789c4cca98..8268636675efc8b3d81959f0f1911a145c42fcc1 100644 (file)
@@ -363,7 +363,7 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
        size += (req->ecc.strength + 1) * sizeof(u16);
        /* Reserve space for mu, dmu and delta. */
        size = ALIGN(size, sizeof(s32));
-       size += (req->ecc.strength + 1) * sizeof(s32);
+       size += (req->ecc.strength + 1) * sizeof(s32) * 3;
 
        user = kzalloc(size, GFP_KERNEL);
        if (!user)
index c3bb358ef01eee5b7c7dc0b0ad72b9a3e47f5220..5796468db653450494876bcf6c5da772f7f6bd3e 100644 (file)
@@ -707,7 +707,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        }
        res = clk_prepare_enable(host->clk);
        if (res)
-               goto err_exit1;
+               goto err_put_clk;
 
        nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl;
        nand_chip->dev_ready = lpc32xx_nand_device_ready;
@@ -814,6 +814,7 @@ err_exit3:
                dma_release_channel(host->dma_chan);
 err_exit2:
        clk_disable_unprepare(host->clk);
+err_put_clk:
        clk_put(host->clk);
 err_exit1:
        lpc32xx_wp_enable(host);
index bcc8cef1c615c5b0336f5310f56ee29a9c44e88a..12edaae17d81f2228eefcc50b9d5de7433119987 100644 (file)
@@ -2668,7 +2668,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
                             struct mtd_oob_ops *ops)
 {
-       int chipnr, realpage, page, blockmask, column;
+       int chipnr, realpage, page, column;
        struct nand_chip *chip = mtd_to_nand(mtd);
        uint32_t writelen = ops->len;
 
@@ -2704,7 +2704,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 
        realpage = (int)(to >> chip->page_shift);
        page = realpage & chip->pagemask;
-       blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
 
        /* Invalidate the page cache, when we write to the cached page */
        if (to <= ((loff_t)chip->pagebuf << chip->page_shift) &&
index cf1d4a15e10a63394b0410f4349e711f602c6c5d..19c000722cbc86f3246c0b84055eca92db331424 100644 (file)
@@ -1784,7 +1784,7 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
  * @nor:       pointer to a 'struct spi_nor'
  * @addr:      offset in the SFDP area to start reading data from
  * @len:       number of bytes to read
- * @buf:       buffer where the SFDP data are copied into
+ * @buf:       buffer where the SFDP data are copied into (dma-safe memory)
  *
  * Whatever the actual numbers of bytes for address and dummy cycles are
  * for (Fast) Read commands, the Read SFDP (5Ah) instruction is always
@@ -1829,6 +1829,36 @@ read_err:
        return ret;
 }
 
+/**
+ * spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters.
+ * @nor:       pointer to a 'struct spi_nor'
+ * @addr:      offset in the SFDP area to start reading data from
+ * @len:       number of bytes to read
+ * @buf:       buffer where the SFDP data are copied into
+ *
+ * Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not
+ * guaranteed to be dma-safe.
+ *
+ * Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp()
+ *          otherwise.
+ */
+static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr,
+                                       size_t len, void *buf)
+{
+       void *dma_safe_buf;
+       int ret;
+
+       dma_safe_buf = kmalloc(len, GFP_KERNEL);
+       if (!dma_safe_buf)
+               return -ENOMEM;
+
+       ret = spi_nor_read_sfdp(nor, addr, len, dma_safe_buf);
+       memcpy(buf, dma_safe_buf, len);
+       kfree(dma_safe_buf);
+
+       return ret;
+}
+
 struct sfdp_parameter_header {
        u8              id_lsb;
        u8              minor;
@@ -2101,7 +2131,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
                    bfpt_header->length * sizeof(u32));
        addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
        memset(&bfpt, 0, sizeof(bfpt));
-       err = spi_nor_read_sfdp(nor,  addr, len, &bfpt);
+       err = spi_nor_read_sfdp_dma_unsafe(nor,  addr, len, &bfpt);
        if (err < 0)
                return err;
 
@@ -2127,6 +2157,15 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
        params->size = bfpt.dwords[BFPT_DWORD(2)];
        if (params->size & BIT(31)) {
                params->size &= ~BIT(31);
+
+               /*
+                * Prevent overflows on params->size. Anyway, a NOR of 2^64
+                * bits is unlikely to exist so this error probably means
+                * the BFPT we are reading is corrupted/wrong.
+                */
+               if (params->size > 63)
+                       return -EINVAL;
+
                params->size = 1ULL << params->size;
        } else {
                params->size++;
@@ -2243,7 +2282,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
        int i, err;
 
        /* Get the SFDP header. */
-       err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header);
+       err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
        if (err < 0)
                return err;
 
index c3c53f6cd9e62cb6551533153f455a2cd7285954..83eec9a8c27511b40e39d18b072dc0afc9aacff4 100644 (file)
@@ -432,6 +432,27 @@ static void bcm_sysport_update_mib_counters(struct bcm_sysport_priv *priv)
        netif_dbg(priv, hw, priv->netdev, "updated MIB counters\n");
 }
 
+static void bcm_sysport_update_tx_stats(struct bcm_sysport_priv *priv,
+                                       u64 *tx_bytes, u64 *tx_packets)
+{
+       struct bcm_sysport_tx_ring *ring;
+       u64 bytes = 0, packets = 0;
+       unsigned int start;
+       unsigned int q;
+
+       for (q = 0; q < priv->netdev->num_tx_queues; q++) {
+               ring = &priv->tx_rings[q];
+               do {
+                       start = u64_stats_fetch_begin_irq(&priv->syncp);
+                       bytes = ring->bytes;
+                       packets = ring->packets;
+               } while (u64_stats_fetch_retry_irq(&priv->syncp, start));
+
+               *tx_bytes += bytes;
+               *tx_packets += packets;
+       }
+}
+
 static void bcm_sysport_get_stats(struct net_device *dev,
                                  struct ethtool_stats *stats, u64 *data)
 {
@@ -439,11 +460,16 @@ static void bcm_sysport_get_stats(struct net_device *dev,
        struct bcm_sysport_stats64 *stats64 = &priv->stats64;
        struct u64_stats_sync *syncp = &priv->syncp;
        struct bcm_sysport_tx_ring *ring;
+       u64 tx_bytes = 0, tx_packets = 0;
        unsigned int start;
        int i, j;
 
-       if (netif_running(dev))
+       if (netif_running(dev)) {
                bcm_sysport_update_mib_counters(priv);
+               bcm_sysport_update_tx_stats(priv, &tx_bytes, &tx_packets);
+               stats64->tx_bytes = tx_bytes;
+               stats64->tx_packets = tx_packets;
+       }
 
        for (i =  0, j = 0; i < BCM_SYSPORT_STATS_LEN; i++) {
                const struct bcm_sysport_stats *s;
@@ -461,12 +487,13 @@ static void bcm_sysport_get_stats(struct net_device *dev,
                        continue;
                p += s->stat_offset;
 
-               if (s->stat_sizeof == sizeof(u64))
+               if (s->stat_sizeof == sizeof(u64) &&
+                   s->type == BCM_SYSPORT_STAT_NETDEV64) {
                        do {
                                start = u64_stats_fetch_begin_irq(syncp);
                                data[i] = *(u64 *)p;
                        } while (u64_stats_fetch_retry_irq(syncp, start));
-               else
+               else
                        data[i] = *(u32 *)p;
                j++;
        }
@@ -1716,27 +1743,12 @@ static void bcm_sysport_get_stats64(struct net_device *dev,
 {
        struct bcm_sysport_priv *priv = netdev_priv(dev);
        struct bcm_sysport_stats64 *stats64 = &priv->stats64;
-       struct bcm_sysport_tx_ring *ring;
-       u64 tx_packets = 0, tx_bytes = 0;
        unsigned int start;
-       unsigned int q;
 
        netdev_stats_to_stats64(stats, &dev->stats);
 
-       for (q = 0; q < dev->num_tx_queues; q++) {
-               ring = &priv->tx_rings[q];
-               do {
-                       start = u64_stats_fetch_begin_irq(&priv->syncp);
-                       tx_bytes = ring->bytes;
-                       tx_packets = ring->packets;
-               } while (u64_stats_fetch_retry_irq(&priv->syncp, start));
-
-               stats->tx_bytes += tx_bytes;
-               stats->tx_packets += tx_packets;
-       }
-
-       stats64->tx_bytes = stats->tx_bytes;
-       stats64->tx_packets = stats->tx_packets;
+       bcm_sysport_update_tx_stats(priv, &stats->tx_bytes,
+                                   &stats->tx_packets);
 
        do {
                start = u64_stats_fetch_begin_irq(&priv->syncp);
index ccd699fb2d706ec51252998f7957ae875cd812ea..7dd3d131043a76ba4b83b43f755d2b782c07139e 100644 (file)
@@ -750,6 +750,10 @@ int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
 {
        int rc = 0;
 
+       if (!is_classid_clsact_ingress(cls_flower->common.classid) ||
+           cls_flower->common.chain_index)
+               return -EOPNOTSUPP;
+
        switch (cls_flower->command) {
        case TC_CLSFLOWER_REPLACE:
                rc = bnxt_tc_add_flow(bp, src_fid, cls_flower);
index 38c7b21e5d63faaeae25ad45715aecb5a3469578..ede1876a9a191c2c1a63ae5ff3f839deb826d54b 100644 (file)
@@ -374,8 +374,8 @@ struct bufdesc_ex {
 #define FEC_ENET_TS_AVAIL       ((uint)0x00010000)
 #define FEC_ENET_TS_TIMER       ((uint)0x00008000)
 
-#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | FEC_ENET_TS_TIMER)
-#define FEC_NAPI_IMASK (FEC_ENET_MII | FEC_ENET_TS_TIMER)
+#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
+#define FEC_NAPI_IMASK FEC_ENET_MII
 #define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
 
 /* ENET interrupt coalescing macro define */
index 56f56d6ada9cfdfa6f719eb6d9793efb3a614ccd..3dc2d771a222147c89a3814a34d736e0bcf0d5c4 100644 (file)
@@ -1559,14 +1559,14 @@ fec_enet_collect_events(struct fec_enet_private *fep, uint int_events)
        if (int_events == 0)
                return false;
 
-       if (int_events & FEC_ENET_RXF)
+       if (int_events & FEC_ENET_RXF_0)
                fep->work_rx |= (1 << 2);
        if (int_events & FEC_ENET_RXF_1)
                fep->work_rx |= (1 << 0);
        if (int_events & FEC_ENET_RXF_2)
                fep->work_rx |= (1 << 1);
 
-       if (int_events & FEC_ENET_TXF)
+       if (int_events & FEC_ENET_TXF_0)
                fep->work_tx |= (1 << 2);
        if (int_events & FEC_ENET_TXF_1)
                fep->work_tx |= (1 << 0);
@@ -1604,8 +1604,8 @@ fec_enet_interrupt(int irq, void *dev_id)
        }
 
        if (fep->ptp_clock)
-               fec_ptp_check_pps_event(fep);
-
+               if (fec_ptp_check_pps_event(fep))
+                       ret = IRQ_HANDLED;
        return ret;
 }
 
index 59efbd605416fd5eed5f7987e163b8cf92e6889a..5bcb2238acb2b11368635ee70042130b02f0d7ae 100644 (file)
@@ -37,20 +37,15 @@ static bool hnae3_client_match(enum hnae3_client_type client_type,
 }
 
 static int hnae3_match_n_instantiate(struct hnae3_client *client,
-                                    struct hnae3_ae_dev *ae_dev,
-                                    bool is_reg, bool *matched)
+                                    struct hnae3_ae_dev *ae_dev, bool is_reg)
 {
        int ret;
 
-       *matched = false;
-
        /* check if this client matches the type of ae_dev */
        if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
              hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
                return 0;
        }
-       /* there is a match of client and dev */
-       *matched = true;
 
        /* now, (un-)instantiate client by calling lower layer */
        if (is_reg) {
@@ -69,7 +64,6 @@ int hnae3_register_client(struct hnae3_client *client)
 {
        struct hnae3_client *client_tmp;
        struct hnae3_ae_dev *ae_dev;
-       bool matched;
        int ret = 0;
 
        mutex_lock(&hnae3_common_lock);
@@ -86,7 +80,7 @@ int hnae3_register_client(struct hnae3_client *client)
                /* if the client could not be initialized on current port, for
                 * any error reasons, move on to next available port
                 */
-               ret = hnae3_match_n_instantiate(client, ae_dev, true, &matched);
+               ret = hnae3_match_n_instantiate(client, ae_dev, true);
                if (ret)
                        dev_err(&ae_dev->pdev->dev,
                                "match and instantiation failed for port\n");
@@ -102,12 +96,11 @@ EXPORT_SYMBOL(hnae3_register_client);
 void hnae3_unregister_client(struct hnae3_client *client)
 {
        struct hnae3_ae_dev *ae_dev;
-       bool matched;
 
        mutex_lock(&hnae3_common_lock);
        /* un-initialize the client on every matched port */
        list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
-               hnae3_match_n_instantiate(client, ae_dev, false, &matched);
+               hnae3_match_n_instantiate(client, ae_dev, false);
        }
 
        list_del(&client->node);
@@ -124,7 +117,6 @@ int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
        const struct pci_device_id *id;
        struct hnae3_ae_dev *ae_dev;
        struct hnae3_client *client;
-       bool matched;
        int ret = 0;
 
        mutex_lock(&hnae3_common_lock);
@@ -151,13 +143,10 @@ int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
                 * initialize the figure out client instance
                 */
                list_for_each_entry(client, &hnae3_client_list, node) {
-                       ret = hnae3_match_n_instantiate(client, ae_dev, true,
-                                                       &matched);
+                       ret = hnae3_match_n_instantiate(client, ae_dev, true);
                        if (ret)
                                dev_err(&ae_dev->pdev->dev,
                                        "match and instantiation failed\n");
-                       if (matched)
-                               break;
                }
        }
 
@@ -175,7 +164,6 @@ void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
        const struct pci_device_id *id;
        struct hnae3_ae_dev *ae_dev;
        struct hnae3_client *client;
-       bool matched;
 
        mutex_lock(&hnae3_common_lock);
        /* Check if there are matched ae_dev */
@@ -187,12 +175,8 @@ void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
                /* check the client list for the match with this ae_dev type and
                 * un-initialize the figure out client instance
                 */
-               list_for_each_entry(client, &hnae3_client_list, node) {
-                       hnae3_match_n_instantiate(client, ae_dev, false,
-                                                 &matched);
-                       if (matched)
-                               break;
-               }
+               list_for_each_entry(client, &hnae3_client_list, node)
+                       hnae3_match_n_instantiate(client, ae_dev, false);
 
                ae_algo->ops->uninit_ae_dev(ae_dev);
                hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
@@ -212,7 +196,6 @@ int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
        const struct pci_device_id *id;
        struct hnae3_ae_algo *ae_algo;
        struct hnae3_client *client;
-       bool matched;
        int ret = 0;
 
        mutex_lock(&hnae3_common_lock);
@@ -246,13 +229,10 @@ int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
         * initialize the figure out client instance
         */
        list_for_each_entry(client, &hnae3_client_list, node) {
-               ret = hnae3_match_n_instantiate(client, ae_dev, true,
-                                               &matched);
+               ret = hnae3_match_n_instantiate(client, ae_dev, true);
                if (ret)
                        dev_err(&ae_dev->pdev->dev,
                                "match and instantiation failed\n");
-               if (matched)
-                       break;
        }
 
 out_err:
@@ -270,7 +250,6 @@ void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
        const struct pci_device_id *id;
        struct hnae3_ae_algo *ae_algo;
        struct hnae3_client *client;
-       bool matched;
 
        mutex_lock(&hnae3_common_lock);
        /* Check if there are matched ae_algo */
@@ -279,12 +258,8 @@ void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
                if (!id)
                        continue;
 
-               list_for_each_entry(client, &hnae3_client_list, node) {
-                       hnae3_match_n_instantiate(client, ae_dev, false,
-                                                 &matched);
-                       if (matched)
-                               break;
-               }
+               list_for_each_entry(client, &hnae3_client_list, node)
+                       hnae3_match_n_instantiate(client, ae_dev, false);
 
                ae_algo->ops->uninit_ae_dev(ae_dev);
                hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
index b2f28ae81273d71a6e31e3a70575570c0aae9ea2..1a01cadfe5f3035d21b35602ccf8c1c016854574 100644 (file)
 #define HNAE3_CLASS_NAME_SIZE 16
 
 #define HNAE3_DEV_INITED_B                     0x0
-#define HNAE_DEV_SUPPORT_ROCE_B                        0x1
+#define HNAE3_DEV_SUPPORT_ROCE_B               0x1
+#define HNAE3_DEV_SUPPORT_DCB_B                        0x2
+
+#define HNAE3_DEV_SUPPORT_ROCE_DCB_BITS (BIT(HNAE3_DEV_SUPPORT_DCB_B) |\
+               BIT(HNAE3_DEV_SUPPORT_ROCE_B))
+
+#define hnae3_dev_roce_supported(hdev) \
+       hnae_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B)
+
+#define hnae3_dev_dcb_supported(hdev) \
+       hnae_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_DCB_B)
 
 #define ring_ptr_move_fw(ring, p) \
        ((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
@@ -366,12 +376,12 @@ struct hnae3_ae_algo {
 struct hnae3_tc_info {
        u16     tqp_offset;     /* TQP offset from base TQP */
        u16     tqp_count;      /* Total TQPs */
-       u8      up;             /* user priority */
        u8      tc;             /* TC index */
        bool    enable;         /* If this TC is enable or not */
 };
 
 #define HNAE3_MAX_TC           8
+#define HNAE3_MAX_USER_PRIO    8
 struct hnae3_knic_private_info {
        struct net_device *netdev; /* Set by KNIC client when init instance */
        u16 rss_size;              /* Allocated RSS queues */
@@ -379,6 +389,7 @@ struct hnae3_knic_private_info {
        u16 num_desc;
 
        u8 num_tc;                 /* Total number of enabled TCs */
+       u8 prio_tc[HNAE3_MAX_USER_PRIO];  /* TC indexed by prio */
        struct hnae3_tc_info tc_info[HNAE3_MAX_TC]; /* Idx of array is HW TC */
 
        u16 num_tqps;             /* total number of TQPs in this handle */
index 91ae0135ee503848ec1ed8d3d691632485ad2170..758cf394813126450ce190b24d16af5e41f7b92b 100644 (file)
@@ -238,7 +238,7 @@ struct hclge_tqp_map {
        u8 rsv[18];
 };
 
-#define HCLGE_VECTOR_ELEMENTS_PER_CMD  11
+#define HCLGE_VECTOR_ELEMENTS_PER_CMD  10
 
 enum hclge_int_type {
        HCLGE_INT_TX,
@@ -252,8 +252,12 @@ struct hclge_ctrl_vector_chain {
 #define HCLGE_INT_TYPE_S       0
 #define HCLGE_INT_TYPE_M       0x3
 #define HCLGE_TQP_ID_S         2
-#define HCLGE_TQP_ID_M         (0x3fff << HCLGE_TQP_ID_S)
+#define HCLGE_TQP_ID_M         (0x7ff << HCLGE_TQP_ID_S)
+#define HCLGE_INT_GL_IDX_S     13
+#define HCLGE_INT_GL_IDX_M     (0x3 << HCLGE_INT_GL_IDX_S)
        __le16 tqp_type_and_id[HCLGE_VECTOR_ELEMENTS_PER_CMD];
+       u8 vfid;
+       u8 rsv;
 };
 
 #define HCLGE_TC_NUM           8
@@ -266,7 +270,8 @@ struct hclge_tx_buff_alloc {
 
 struct hclge_rx_priv_buff {
        __le16 buf_num[HCLGE_TC_NUM];
-       u8 rsv[8];
+       __le16 shared_buf;
+       u8 rsv[6];
 };
 
 struct hclge_query_version {
@@ -684,6 +689,7 @@ struct hclge_reset_tqp_queue {
 #define HCLGE_DEFAULT_TX_BUF           0x4000   /* 16k  bytes */
 #define HCLGE_TOTAL_PKT_BUF            0x108000 /* 1.03125M bytes */
 #define HCLGE_DEFAULT_DV               0xA000   /* 40k byte */
+#define HCLGE_DEFAULT_NON_DCB_DV       0x7800  /* 30K byte */
 
 #define HCLGE_TYPE_CRQ                 0
 #define HCLGE_TYPE_CSQ                 1
index bb45365fb817eb648dcaa160e2173257e027ad2a..e0685e630afec795db1e5f1d3221919cd2766ba8 100644 (file)
@@ -46,17 +46,7 @@ static const struct pci_device_id ae_algo_pci_tbl[] = {
        {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA), 0},
        {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA_MACSEC), 0},
        {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC), 0},
-       /* Required last entry */
-       {0, }
-};
-
-static const struct pci_device_id roce_pci_tbl[] = {
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA_MACSEC), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA_MACSEC), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC), 0},
-       /* Required last entry */
+       /* required last entry */
        {0, }
 };
 
@@ -894,7 +884,7 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev)
        hdev->num_tqps = __le16_to_cpu(req->tqp_num);
        hdev->pkt_buf_size = __le16_to_cpu(req->buf_size) << HCLGE_BUF_UNIT_S;
 
-       if (hnae_get_bit(hdev->ae_dev->flag, HNAE_DEV_SUPPORT_ROCE_B)) {
+       if (hnae3_dev_roce_supported(hdev)) {
                hdev->num_roce_msix =
                hnae_get_field(__le16_to_cpu(req->pf_intr_vector_number),
                               HCLGE_PF_VEC_NUM_M, HCLGE_PF_VEC_NUM_S);
@@ -1063,9 +1053,9 @@ static int hclge_configure(struct hclge_dev *hdev)
        hdev->base_tqp_pid = 0;
        hdev->rss_size_max = 1;
        hdev->rx_buf_len = cfg.rx_buf_len;
-       for (i = 0; i < ETH_ALEN; i++)
-               hdev->hw.mac.mac_addr[i] = cfg.mac_addr[i];
+       ether_addr_copy(hdev->hw.mac.mac_addr, cfg.mac_addr);
        hdev->hw.mac.media_type = cfg.media_type;
+       hdev->hw.mac.phy_addr = cfg.phy_addr;
        hdev->num_desc = cfg.tqp_desc_num;
        hdev->tm_info.num_pg = 1;
        hdev->tm_info.num_tc = cfg.tc_num;
@@ -1454,7 +1444,11 @@ static bool  hclge_is_rx_buf_ok(struct hclge_dev *hdev, u32 rx_all)
        tc_num = hclge_get_tc_num(hdev);
        pfc_enable_num = hclge_get_pfc_enalbe_num(hdev);
 
-       shared_buf_min = 2 * hdev->mps + HCLGE_DEFAULT_DV;
+       if (hnae3_dev_dcb_supported(hdev))
+               shared_buf_min = 2 * hdev->mps + HCLGE_DEFAULT_DV;
+       else
+               shared_buf_min = 2 * hdev->mps + HCLGE_DEFAULT_NON_DCB_DV;
+
        shared_buf_tc = pfc_enable_num * hdev->mps +
                        (tc_num - pfc_enable_num) * hdev->mps / 2 +
                        hdev->mps;
@@ -1495,6 +1489,16 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev, u32 tx_size)
        struct hclge_priv_buf *priv;
        int i;
 
+       /* When DCB is not supported, rx private
+        * buffer is not allocated.
+        */
+       if (!hnae3_dev_dcb_supported(hdev)) {
+               if (!hclge_is_rx_buf_ok(hdev, rx_all))
+                       return -ENOMEM;
+
+               return 0;
+       }
+
        /* step 1, try to alloc private buffer for all enabled tc */
        for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
                priv = &hdev->priv_buf[i];
@@ -1510,6 +1514,11 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev, u32 tx_size)
                                priv->wl.high = 2 * hdev->mps;
                                priv->buf_size = priv->wl.high;
                        }
+               } else {
+                       priv->enable = 0;
+                       priv->wl.low = 0;
+                       priv->wl.high = 0;
+                       priv->buf_size = 0;
                }
        }
 
@@ -1522,8 +1531,15 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev, u32 tx_size)
        for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
                priv = &hdev->priv_buf[i];
 
-               if (hdev->hw_tc_map & BIT(i))
-                       priv->enable = 1;
+               priv->enable = 0;
+               priv->wl.low = 0;
+               priv->wl.high = 0;
+               priv->buf_size = 0;
+
+               if (!(hdev->hw_tc_map & BIT(i)))
+                       continue;
+
+               priv->enable = 1;
 
                if (hdev->tm_info.hw_pfc_map & BIT(i)) {
                        priv->wl.low = 128;
@@ -1616,6 +1632,10 @@ static int hclge_rx_priv_buf_alloc(struct hclge_dev *hdev)
                        cpu_to_le16(true << HCLGE_TC0_PRI_BUF_EN_B);
        }
 
+       req->shared_buf =
+               cpu_to_le16((hdev->s_buf.buf_size >> HCLGE_BUF_UNIT_S) |
+                           (1 << HCLGE_TC0_PRI_BUF_EN_B));
+
        ret = hclge_cmd_send(&hdev->hw, &desc, 1);
        if (ret) {
                dev_err(&hdev->pdev->dev,
@@ -1782,18 +1802,22 @@ int hclge_buffer_alloc(struct hclge_dev *hdev)
                return ret;
        }
 
-       ret = hclge_rx_priv_wl_config(hdev);
-       if (ret) {
-               dev_err(&hdev->pdev->dev,
-                       "could not configure rx private waterline %d\n", ret);
-               return ret;
-       }
+       if (hnae3_dev_dcb_supported(hdev)) {
+               ret = hclge_rx_priv_wl_config(hdev);
+               if (ret) {
+                       dev_err(&hdev->pdev->dev,
+                               "could not configure rx private waterline %d\n",
+                               ret);
+                       return ret;
+               }
 
-       ret = hclge_common_thrd_config(hdev);
-       if (ret) {
-               dev_err(&hdev->pdev->dev,
-                       "could not configure common threshold %d\n", ret);
-               return ret;
+               ret = hclge_common_thrd_config(hdev);
+               if (ret) {
+                       dev_err(&hdev->pdev->dev,
+                               "could not configure common threshold %d\n",
+                               ret);
+                       return ret;
+               }
        }
 
        ret = hclge_common_wl_config(hdev);
@@ -2582,6 +2606,7 @@ static int hclge_rss_init_hw(struct hclge_dev *hdev)
        u16 tc_valid[HCLGE_MAX_TC_NUM];
        u16 tc_size[HCLGE_MAX_TC_NUM];
        u32 *rss_indir = NULL;
+       u16 rss_size = 0, roundup_size;
        const u8 *key;
        int i, ret, j;
 
@@ -2596,7 +2621,13 @@ static int hclge_rss_init_hw(struct hclge_dev *hdev)
        for (j = 0; j < hdev->num_vmdq_vport + 1; j++) {
                for (i = 0; i < HCLGE_RSS_IND_TBL_SIZE; i++) {
                        vport[j].rss_indirection_tbl[i] =
-                               i % hdev->rss_size_max;
+                               i % vport[j].alloc_rss_size;
+
+                       /* vport 0 is for PF */
+                       if (j != 0)
+                               continue;
+
+                       rss_size = vport[j].alloc_rss_size;
                        rss_indir[i] = vport[j].rss_indirection_tbl[i];
                }
        }
@@ -2613,42 +2644,31 @@ static int hclge_rss_init_hw(struct hclge_dev *hdev)
        if (ret)
                goto err;
 
+       /* Each TC have the same queue size, and tc_size set to hardware is
+        * the log2 of roundup power of two of rss_size, the acutal queue
+        * size is limited by indirection table.
+        */
+       if (rss_size > HCLGE_RSS_TC_SIZE_7 || rss_size == 0) {
+               dev_err(&hdev->pdev->dev,
+                       "Configure rss tc size failed, invalid TC_SIZE = %d\n",
+                       rss_size);
+               return -EINVAL;
+       }
+
+       roundup_size = roundup_pow_of_two(rss_size);
+       roundup_size = ilog2(roundup_size);
+
        for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
-               if (hdev->hw_tc_map & BIT(i))
-                       tc_valid[i] = 1;
-               else
-                       tc_valid[i] = 0;
+               tc_valid[i] = 0;
 
-               switch (hdev->rss_size_max) {
-               case HCLGE_RSS_TC_SIZE_0:
-                       tc_size[i] = 0;
-                       break;
-               case HCLGE_RSS_TC_SIZE_1:
-                       tc_size[i] = 1;
-                       break;
-               case HCLGE_RSS_TC_SIZE_2:
-                       tc_size[i] = 2;
-                       break;
-               case HCLGE_RSS_TC_SIZE_3:
-                       tc_size[i] = 3;
-                       break;
-               case HCLGE_RSS_TC_SIZE_4:
-                       tc_size[i] = 4;
-                       break;
-               case HCLGE_RSS_TC_SIZE_5:
-                       tc_size[i] = 5;
-                       break;
-               case HCLGE_RSS_TC_SIZE_6:
-                       tc_size[i] = 6;
-                       break;
-               case HCLGE_RSS_TC_SIZE_7:
-                       tc_size[i] = 7;
-                       break;
-               default:
-                       break;
-               }
-               tc_offset[i] = hdev->rss_size_max * i;
+               if (!(hdev->hw_tc_map & BIT(i)))
+                       continue;
+
+               tc_valid[i] = 1;
+               tc_size[i] = roundup_size;
+               tc_offset[i] = rss_size * i;
        }
+
        ret = hclge_set_rss_tc_mode(hdev, tc_valid, tc_size, tc_offset);
 
 err:
@@ -2679,7 +2699,11 @@ int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector_id,
                               hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
                hnae_set_field(req->tqp_type_and_id[i], HCLGE_TQP_ID_M,
                               HCLGE_TQP_ID_S,  node->tqp_index);
+               hnae_set_field(req->tqp_type_and_id[i], HCLGE_INT_GL_IDX_M,
+                              HCLGE_INT_GL_IDX_S,
+                              hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
                req->tqp_type_and_id[i] = cpu_to_le16(req->tqp_type_and_id[i]);
+               req->vfid = vport->vport_id;
 
                if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
                        req->int_cause_num = HCLGE_VECTOR_ELEMENTS_PER_CMD;
@@ -2763,8 +2787,12 @@ static int hclge_unmap_ring_from_vector(
                               hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
                hnae_set_field(req->tqp_type_and_id[i], HCLGE_TQP_ID_M,
                               HCLGE_TQP_ID_S,  node->tqp_index);
+               hnae_set_field(req->tqp_type_and_id[i], HCLGE_INT_GL_IDX_M,
+                              HCLGE_INT_GL_IDX_S,
+                              hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
 
                req->tqp_type_and_id[i] = cpu_to_le16(req->tqp_type_and_id[i]);
+               req->vfid = vport->vport_id;
 
                if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
                        req->int_cause_num = HCLGE_VECTOR_ELEMENTS_PER_CMD;
@@ -2778,7 +2806,7 @@ static int hclge_unmap_ring_from_vector(
                        }
                        i = 0;
                        hclge_cmd_setup_basic_desc(&desc,
-                                                  HCLGE_OPC_ADD_RING_TO_VECTOR,
+                                                  HCLGE_OPC_DEL_RING_TO_VECTOR,
                                                   false);
                        req->int_vector_id = vector_id;
                }
@@ -3665,6 +3693,7 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
 {
 #define HCLGE_VLAN_TYPE_VF_TABLE   0
 #define HCLGE_VLAN_TYPE_PORT_TABLE 1
+       struct hnae3_handle *handle;
        int ret;
 
        ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_VLAN_TYPE_VF_TABLE,
@@ -3674,8 +3703,11 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
 
        ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_VLAN_TYPE_PORT_TABLE,
                                         true);
+       if (ret)
+               return ret;
 
-       return ret;
+       handle = &hdev->vport[0].nic;
+       return hclge_set_port_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
 }
 
 static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu)
@@ -3920,8 +3952,7 @@ static int hclge_init_client_instance(struct hnae3_client *client,
                                goto err;
 
                        if (hdev->roce_client &&
-                           hnae_get_bit(hdev->ae_dev->flag,
-                                        HNAE_DEV_SUPPORT_ROCE_B)) {
+                           hnae3_dev_roce_supported(hdev)) {
                                struct hnae3_client *rc = hdev->roce_client;
 
                                ret = hclge_init_roce_base_info(vport);
@@ -3944,8 +3975,7 @@ static int hclge_init_client_instance(struct hnae3_client *client,
 
                        break;
                case HNAE3_CLIENT_ROCE:
-                       if (hnae_get_bit(hdev->ae_dev->flag,
-                                        HNAE_DEV_SUPPORT_ROCE_B)) {
+                       if (hnae3_dev_roce_supported(hdev)) {
                                hdev->roce_client = client;
                                vport->roce.client = client;
                        }
@@ -4057,7 +4087,6 @@ static void hclge_pci_uninit(struct hclge_dev *hdev)
 static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
 {
        struct pci_dev *pdev = ae_dev->pdev;
-       const struct pci_device_id *id;
        struct hclge_dev *hdev;
        int ret;
 
@@ -4072,10 +4101,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
        hdev->ae_dev = ae_dev;
        ae_dev->priv = hdev;
 
-       id = pci_match_id(roce_pci_tbl, ae_dev->pdev);
-       if (id)
-               hnae_set_bit(ae_dev->flag, HNAE_DEV_SUPPORT_ROCE_B, 1);
-
        ret = hclge_pci_init(hdev);
        if (ret) {
                dev_err(&pdev->dev, "PCI init failed\n");
@@ -4138,12 +4163,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
                return ret;
        }
 
-       ret = hclge_rss_init_hw(hdev);
-       if (ret) {
-               dev_err(&pdev->dev, "Rss init fail, ret =%d\n", ret);
-               return  ret;
-       }
-
        ret = hclge_init_vlan_config(hdev);
        if (ret) {
                dev_err(&pdev->dev, "VLAN init fail, ret =%d\n", ret);
@@ -4156,6 +4175,12 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
                return ret;
        }
 
+       ret = hclge_rss_init_hw(hdev);
+       if (ret) {
+               dev_err(&pdev->dev, "Rss init fail, ret =%d\n", ret);
+               return ret;
+       }
+
        setup_timer(&hdev->service_timer, hclge_service_timer,
                    (unsigned long)hdev);
        INIT_WORK(&hdev->service_task, hclge_service_task);
index edb10ad075eb2520a3f671d8062f043ddb1c8280..9fcfd9395424538870f4b837ad9ade21476867ae 100644 (file)
@@ -176,7 +176,6 @@ struct hclge_pg_info {
 struct hclge_tc_info {
        u8 tc_id;
        u8 tc_sch_mode;         /* 0: sp; 1: dwrr */
-       u8 up;
        u8 pgid;
        u32 bw_limit;
 };
@@ -197,6 +196,7 @@ struct hclge_tm_info {
        u8 num_tc;
        u8 num_pg;      /* It must be 1 if vNET-Base schd */
        u8 pg_dwrr[HCLGE_PG_NUM];
+       u8 prio_tc[HNAE3_MAX_USER_PRIO];
        struct hclge_pg_info pg_info[HCLGE_PG_NUM];
        struct hclge_tc_info tc_info[HNAE3_MAX_TC];
        enum hclge_fc_mode fc_mode;
@@ -477,6 +477,7 @@ struct hclge_vport {
        u8  rss_hash_key[HCLGE_RSS_KEY_SIZE]; /* User configured hash keys */
        /* User configured lookup table entries */
        u8  rss_indirection_tbl[HCLGE_RSS_IND_TBL_SIZE];
+       u16 alloc_rss_size;
 
        u16 qs_offset;
        u16 bw_limit;           /* VSI BW Limit (0 = disabled) */
index 1c577d268f008b4d39b35164b9205ba35eaefdaa..73a75d7cc5517819b8135324dbc481a0aa993423 100644 (file)
@@ -128,9 +128,7 @@ static int hclge_fill_pri_array(struct hclge_dev *hdev, u8 *pri, u8 pri_id)
 {
        u8 tc;
 
-       for (tc = 0; tc < hdev->tm_info.num_tc; tc++)
-               if (hdev->tm_info.tc_info[tc].up == pri_id)
-                       break;
+       tc = hdev->tm_info.prio_tc[pri_id];
 
        if (tc >= hdev->tm_info.num_tc)
                return -EINVAL;
@@ -158,7 +156,7 @@ static int hclge_up_to_tc_map(struct hclge_dev *hdev)
 
        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PRI_TO_TC_MAPPING, false);
 
-       for (pri_id = 0; pri_id < hdev->tm_info.num_tc; pri_id++) {
+       for (pri_id = 0; pri_id < HNAE3_MAX_USER_PRIO; pri_id++) {
                ret = hclge_fill_pri_array(hdev, pri, pri_id);
                if (ret)
                        return ret;
@@ -280,11 +278,11 @@ static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev,
 
        shap_cfg_cmd->pg_id = pg_id;
 
-       hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_B, ir_b);
-       hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_U, ir_u);
-       hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, IR_S, ir_s);
-       hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, BS_B, bs_b);
-       hclge_tm_set_feild(shap_cfg_cmd->pg_shapping_para, BS_S, bs_s);
+       hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, IR_B, ir_b);
+       hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, IR_U, ir_u);
+       hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, IR_S, ir_s);
+       hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, BS_B, bs_b);
+       hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, BS_S, bs_s);
 
        return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
@@ -307,11 +305,11 @@ static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev,
 
        shap_cfg_cmd->pri_id = pri_id;
 
-       hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_B, ir_b);
-       hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_U, ir_u);
-       hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, IR_S, ir_s);
-       hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, BS_B, bs_b);
-       hclge_tm_set_feild(shap_cfg_cmd->pri_shapping_para, BS_S, bs_s);
+       hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, IR_B, ir_b);
+       hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, IR_U, ir_u);
+       hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, IR_S, ir_s);
+       hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, BS_B, bs_b);
+       hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, BS_S, bs_s);
 
        return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
@@ -397,6 +395,7 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
                        kinfo->num_tqps / kinfo->num_tc);
        vport->qs_offset = hdev->tm_info.num_tc * vport->vport_id;
        vport->dwrr = 100;  /* 100 percent as init */
+       vport->alloc_rss_size = kinfo->rss_size;
 
        for (i = 0; i < kinfo->num_tc; i++) {
                if (hdev->hw_tc_map & BIT(i)) {
@@ -404,16 +403,17 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
                        kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size;
                        kinfo->tc_info[i].tqp_count = kinfo->rss_size;
                        kinfo->tc_info[i].tc = i;
-                       kinfo->tc_info[i].up = hdev->tm_info.tc_info[i].up;
                } else {
                        /* Set to default queue if TC is disable */
                        kinfo->tc_info[i].enable = false;
                        kinfo->tc_info[i].tqp_offset = 0;
                        kinfo->tc_info[i].tqp_count = 1;
                        kinfo->tc_info[i].tc = 0;
-                       kinfo->tc_info[i].up = 0;
                }
        }
+
+       memcpy(kinfo->prio_tc, hdev->tm_info.prio_tc,
+              FIELD_SIZEOF(struct hnae3_knic_private_info, prio_tc));
 }
 
 static void hclge_tm_vport_info_update(struct hclge_dev *hdev)
@@ -435,12 +435,15 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
        for (i = 0; i < hdev->tm_info.num_tc; i++) {
                hdev->tm_info.tc_info[i].tc_id = i;
                hdev->tm_info.tc_info[i].tc_sch_mode = HCLGE_SCH_MODE_DWRR;
-               hdev->tm_info.tc_info[i].up = i;
                hdev->tm_info.tc_info[i].pgid = 0;
                hdev->tm_info.tc_info[i].bw_limit =
                        hdev->tm_info.pg_info[0].bw_limit;
        }
 
+       for (i = 0; i < HNAE3_MAX_USER_PRIO; i++)
+               hdev->tm_info.prio_tc[i] =
+                       (i >= hdev->tm_info.num_tc) ? 0 : i;
+
        hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
 }
 
@@ -976,6 +979,10 @@ int hclge_pause_setup_hw(struct hclge_dev *hdev)
        if (ret)
                return ret;
 
+       /* Only DCB-supported dev supports qset back pressure setting */
+       if (!hnae3_dev_dcb_supported(hdev))
+               return 0;
+
        for (i = 0; i < hdev->tm_info.num_tc; i++) {
                ret = hclge_tm_qs_bp_cfg(hdev, i);
                if (ret)
index 7e67337dfaf2c36e8c0ecc79f68aaa3f7bc7a32c..85158b0d73fe395ffa90de916c789e5afca5d15a 100644 (file)
@@ -94,10 +94,10 @@ struct hclge_bp_to_qs_map_cmd {
        u32 rsvd1;
 };
 
-#define hclge_tm_set_feild(dest, string, val) \
+#define hclge_tm_set_field(dest, string, val) \
                        hnae_set_field((dest), (HCLGE_TM_SHAP_##string##_MSK), \
                                       (HCLGE_TM_SHAP_##string##_LSH), val)
-#define hclge_tm_get_feild(src, string) \
+#define hclge_tm_get_field(src, string) \
                        hnae_get_field((src), (HCLGE_TM_SHAP_##string##_MSK), \
                                       (HCLGE_TM_SHAP_##string##_LSH))
 
index 1c3e29447891644f48214aee3edceb9efd0ba1ef..35369e1c8036f3abbade76b63eed2a103170b4c7 100644 (file)
@@ -41,11 +41,16 @@ static struct hnae3_client client;
 static const struct pci_device_id hns3_pci_tbl[] = {
        {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_GE), 0},
        {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA_MACSEC), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA_MACSEC), 0},
-       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC), 0},
+       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA),
+        HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
+       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE_RDMA_MACSEC),
+        HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
+       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA),
+        HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
+       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_50GE_RDMA_MACSEC),
+        HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
+       {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC),
+        HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
        /* required last entry */
        {0, }
 };
@@ -1348,6 +1353,7 @@ static int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        ae_dev->pdev = pdev;
+       ae_dev->flag = ent->driver_data;
        ae_dev->dev_type = HNAE3_DEV_KNIC;
        pci_set_drvdata(pdev, ae_dev);
 
@@ -2705,10 +2711,11 @@ static void hns3_init_mac_addr(struct net_device *netdev)
                eth_hw_addr_random(netdev);
                dev_warn(priv->dev, "using random MAC address %pM\n",
                         netdev->dev_addr);
-               /* Also copy this new MAC address into hdev */
-               if (h->ae_algo->ops->set_mac_addr)
-                       h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr);
        }
+
+       if (h->ae_algo->ops->set_mac_addr)
+               h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr);
+
 }
 
 static void hns3_nic_set_priv_ops(struct net_device *netdev)
index 2c74baa2398a016fb9468f8a1b4b3aa5d0dc2a05..fff09dcf9e3463f8b10800d2754a4631770d2d63 100644 (file)
@@ -402,7 +402,7 @@ static int mal_poll(struct napi_struct *napi, int budget)
        unsigned long flags;
 
        MAL_DBG2(mal, "poll(%d)" NL, budget);
- again:
+
        /* Process TX skbs */
        list_for_each(l, &mal->poll_list) {
                struct mal_commac *mc =
@@ -451,7 +451,6 @@ static int mal_poll(struct napi_struct *napi, int budget)
                        spin_lock_irqsave(&mal->lock, flags);
                        mal_disable_eob_irq(mal);
                        spin_unlock_irqrestore(&mal->lock, flags);
-                       goto again;
                }
                mc->ops->poll_tx(mc->dev);
        }
index bbe24639aa5a6a85d2c96130eb89bf9a599be635..c8c6231b87f3305ae570d6c5277d91415ff696e8 100644 (file)
@@ -88,6 +88,8 @@ static void emac_set_msglevel(struct net_device *netdev, u32 data)
 static int emac_get_sset_count(struct net_device *netdev, int sset)
 {
        switch (sset) {
+       case ETH_SS_PRIV_FLAGS:
+               return 1;
        case ETH_SS_STATS:
                return EMAC_STATS_LEN;
        default:
@@ -100,6 +102,10 @@ static void emac_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
        unsigned int i;
 
        switch (stringset) {
+       case ETH_SS_PRIV_FLAGS:
+               strcpy(data, "single-pause-mode");
+               break;
+
        case ETH_SS_STATS:
                for (i = 0; i < EMAC_STATS_LEN; i++) {
                        strlcpy(data, emac_ethtool_stat_strings[i],
@@ -230,6 +236,27 @@ static int emac_get_regs_len(struct net_device *netdev)
        return EMAC_MAX_REG_SIZE * sizeof(u32);
 }
 
+#define EMAC_PRIV_ENABLE_SINGLE_PAUSE  BIT(0)
+
+static int emac_set_priv_flags(struct net_device *netdev, u32 flags)
+{
+       struct emac_adapter *adpt = netdev_priv(netdev);
+
+       adpt->single_pause_mode = !!(flags & EMAC_PRIV_ENABLE_SINGLE_PAUSE);
+
+       if (netif_running(netdev))
+               return emac_reinit_locked(adpt);
+
+       return 0;
+}
+
+static u32 emac_get_priv_flags(struct net_device *netdev)
+{
+       struct emac_adapter *adpt = netdev_priv(netdev);
+
+       return adpt->single_pause_mode ? EMAC_PRIV_ENABLE_SINGLE_PAUSE : 0;
+}
+
 static const struct ethtool_ops emac_ethtool_ops = {
        .get_link_ksettings = phy_ethtool_get_link_ksettings,
        .set_link_ksettings = phy_ethtool_set_link_ksettings,
@@ -253,6 +280,9 @@ static const struct ethtool_ops emac_ethtool_ops = {
 
        .get_regs_len    = emac_get_regs_len,
        .get_regs        = emac_get_regs,
+
+       .set_priv_flags = emac_set_priv_flags,
+       .get_priv_flags = emac_get_priv_flags,
 };
 
 void emac_set_ethtool_ops(struct net_device *netdev)
index bcd4708b374574fb06faf28d9b0a6cc90bc9c56d..0ea3ca09c68980bd2624102f3e40cc257e23e174 100644 (file)
@@ -551,6 +551,28 @@ static void emac_mac_start(struct emac_adapter *adpt)
        mac &= ~(HUGEN | VLAN_STRIP | TPAUSE | SIMR | HUGE | MULTI_ALL |
                 DEBUG_MODE | SINGLE_PAUSE_MODE);
 
+       /* Enable single-pause-frame mode if requested.
+        *
+        * If enabled, the EMAC will send a single pause frame when the RX
+        * queue is full.  This normally leads to packet loss because
+        * the pause frame disables the remote MAC only for 33ms (the quanta),
+        * and then the remote MAC continues sending packets even though
+        * the RX queue is still full.
+        *
+        * If disabled, the EMAC sends a pause frame every 31ms until the RX
+        * queue is no longer full.  Normally, this is the preferred
+        * method of operation.  However, when the system is hung (e.g.
+        * cores are halted), the EMAC interrupt handler is never called
+        * and so the RX queue fills up quickly and stays full.  The resuling
+        * non-stop "flood" of pause frames sometimes has the effect of
+        * disabling nearby switches.  In some cases, other nearby switches
+        * are also affected, shutting down the entire network.
+        *
+        * The user can enable or disable single-pause-frame mode
+        * via ethtool.
+        */
+       mac |= adpt->single_pause_mode ? SINGLE_PAUSE_MODE : 0;
+
        writel_relaxed(csr1, adpt->csr + EMAC_EMAC_WRAPPER_CSR1);
 
        writel_relaxed(mac, adpt->base + EMAC_MAC_CTRL);
index 60850bfa3d32e5d574bddacda871cb75da2076fd..759543512117cbfcc628697a54dd7af4ab600c61 100644 (file)
@@ -443,6 +443,9 @@ static void emac_init_adapter(struct emac_adapter *adpt)
 
        /* default to automatic flow control */
        adpt->automatic = true;
+
+       /* Disable single-pause-frame mode by default */
+       adpt->single_pause_mode = false;
 }
 
 /* Get the clock */
index 8ee4ec6aef2e4379060f0726a75ab8fd8ad1690c..d7c9f44209d499cbd4f7ee7be32ca692f580b12c 100644 (file)
@@ -363,6 +363,9 @@ struct emac_adapter {
        bool                            tx_flow_control;
        bool                            rx_flow_control;
 
+       /* True == use single-pause-frame mode. */
+       bool                            single_pause_mode;
+
        /* Ring parameter */
        u8                              tpd_burst;
        u8                              rfd_burst;
index ca22f2898664617656f7fa6e4e98df1e7aa3bc26..d24b47b8e0b27e0f44243f5a1011779c0ebd09f9 100644 (file)
@@ -2135,11 +2135,12 @@ static int rtl8139_poll(struct napi_struct *napi, int budget)
        if (likely(RTL_R16(IntrStatus) & RxAckBits))
                work_done += rtl8139_rx(dev, tp, budget);
 
-       if (work_done < budget && napi_complete_done(napi, work_done)) {
+       if (work_done < budget) {
                unsigned long flags;
 
                spin_lock_irqsave(&tp->lock, flags);
-               RTL_W16_F(IntrMask, rtl8139_intr_mask);
+               if (napi_complete_done(napi, work_done))
+                       RTL_W16_F(IntrMask, rtl8139_intr_mask);
                spin_unlock_irqrestore(&tp->lock, flags);
        }
        spin_unlock(&tp->rx_lock);
index a366b3747eeb58aebf730fde9c44c0a94af70491..8a280b48e3a9fd0c7ada914f2ceea3618e9e34cf 100644 (file)
@@ -315,6 +315,7 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
                { .compatible = "allwinner,sun8i-h3-emac" },
                { .compatible = "allwinner,sun8i-v3s-emac" },
                { .compatible = "allwinner,sun50i-a64-emac" },
+               {},
        };
 
        /* If phy-handle property is passed from DT, use it as the PHY */
index d98cdfb1536b5600c0b2e962a2e5e003496ad129..5176be76ca7d57771d82829f8bd08b64dbdc7773 100644 (file)
@@ -150,6 +150,8 @@ struct netvsc_device_info {
        u32  num_chn;
        u32  send_sections;
        u32  recv_sections;
+       u32  send_section_size;
+       u32  recv_section_size;
 };
 
 enum rndis_device_state {
index a5511b7326af646618658060c8d289b60fb4883b..8d5077fb04929cb362e7266b45b04c1369ed1284 100644 (file)
@@ -76,9 +76,6 @@ static struct netvsc_device *alloc_net_device(void)
        net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT;
        net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT;
 
-       net_device->recv_section_size = NETVSC_RECV_SECTION_SIZE;
-       net_device->send_section_size = NETVSC_SEND_SECTION_SIZE;
-
        init_completion(&net_device->channel_init_wait);
        init_waitqueue_head(&net_device->subchan_open);
        INIT_WORK(&net_device->subchan_work, rndis_set_subchannel);
@@ -262,7 +259,7 @@ static int netvsc_init_buf(struct hv_device *device,
        int ret = 0;
 
        /* Get receive buffer area. */
-       buf_size = device_info->recv_sections * net_device->recv_section_size;
+       buf_size = device_info->recv_sections * device_info->recv_section_size;
        buf_size = roundup(buf_size, PAGE_SIZE);
 
        net_device->recv_buf = vzalloc(buf_size);
@@ -344,7 +341,7 @@ static int netvsc_init_buf(struct hv_device *device,
                goto cleanup;
 
        /* Now setup the send buffer. */
-       buf_size = device_info->send_sections * net_device->send_section_size;
+       buf_size = device_info->send_sections * device_info->send_section_size;
        buf_size = round_up(buf_size, PAGE_SIZE);
 
        net_device->send_buf = vzalloc(buf_size);
index d4902ee5f260f2df2fa03d680c3c7ea0d79e5dc8..a32ae02e1b6cb6fc2975b0e124aacb42370c0c5d 100644 (file)
@@ -848,7 +848,9 @@ static int netvsc_set_channels(struct net_device *net,
        device_info.num_chn = count;
        device_info.ring_size = ring_size;
        device_info.send_sections = nvdev->send_section_cnt;
+       device_info.send_section_size = nvdev->send_section_size;
        device_info.recv_sections = nvdev->recv_section_cnt;
+       device_info.recv_section_size = nvdev->recv_section_size;
 
        rndis_filter_device_remove(dev, nvdev);
 
@@ -963,7 +965,9 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
        device_info.ring_size = ring_size;
        device_info.num_chn = nvdev->num_chn;
        device_info.send_sections = nvdev->send_section_cnt;
+       device_info.send_section_size = nvdev->send_section_size;
        device_info.recv_sections = nvdev->recv_section_cnt;
+       device_info.recv_section_size = nvdev->recv_section_size;
 
        rndis_filter_device_remove(hdev, nvdev);
 
@@ -1485,7 +1489,9 @@ static int netvsc_set_ringparam(struct net_device *ndev,
        device_info.num_chn = nvdev->num_chn;
        device_info.ring_size = ring_size;
        device_info.send_sections = new_tx;
+       device_info.send_section_size = nvdev->send_section_size;
        device_info.recv_sections = new_rx;
+       device_info.recv_section_size = nvdev->recv_section_size;
 
        netif_device_detach(ndev);
        was_opened = rndis_filter_opened(nvdev);
@@ -1934,7 +1940,9 @@ static int netvsc_probe(struct hv_device *dev,
        device_info.ring_size = ring_size;
        device_info.num_chn = VRSS_CHANNEL_DEFAULT;
        device_info.send_sections = NETVSC_DEFAULT_TX;
+       device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
        device_info.recv_sections = NETVSC_DEFAULT_RX;
+       device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE;
 
        nvdev = rndis_filter_device_add(dev, &device_info);
        if (IS_ERR(nvdev)) {
index a9d16a3af514ead8f96a34db3d05478785cdf6d6..cd931cf9dcc262d3a1ccb4d03b5022b2180f1266 100644 (file)
@@ -160,15 +160,6 @@ config MDIO_XGENE
 
 endif
 
-menuconfig PHYLIB
-       tristate "PHY Device support and infrastructure"
-       depends on NETDEVICES
-       select MDIO_DEVICE
-       help
-         Ethernet controllers are usually attached to PHY
-         devices.  This option provides infrastructure for
-         managing PHY devices.
-
 config PHYLINK
        tristate
        depends on NETDEVICES
@@ -179,6 +170,15 @@ config PHYLINK
          configuration links, PHYs, and Serdes links with MAC level
          autonegotiation modes.
 
+menuconfig PHYLIB
+       tristate "PHY Device support and infrastructure"
+       depends on NETDEVICES
+       select MDIO_DEVICE
+       help
+         Ethernet controllers are usually attached to PHY
+         devices.  This option provides infrastructure for
+         managing PHY devices.
+
 if PHYLIB
 
 config SWPHY
index e842d2cd1ee750f8930028370c1c7fac5a52dc77..2b1e67bc1e736ceb33f7afa8462f5a4858b522df 100644 (file)
@@ -373,7 +373,8 @@ void phy_ethtool_ksettings_get(struct phy_device *phydev,
                cmd->base.port = PORT_BNC;
        else
                cmd->base.port = PORT_MII;
-
+       cmd->base.transceiver = phy_is_internal(phydev) ?
+                               XCVR_INTERNAL : XCVR_EXTERNAL;
        cmd->base.phy_address = phydev->mdio.addr;
        cmd->base.autoneg = phydev->autoneg;
        cmd->base.eth_tp_mdix_ctrl = phydev->mdix_ctrl;
index 8cf0c5901f95870fc613edba0289594a5d40640a..67f25ac29025c53903cc724fac62efdd94828510 100644 (file)
@@ -879,7 +879,7 @@ void phy_attached_print(struct phy_device *phydev, const char *fmt, ...)
 {
        const char *drv_name = phydev->drv ? phydev->drv->name : "unbound";
        char *irq_str;
-       char irq_num[4];
+       char irq_num[8];
 
        switch(phydev->irq) {
        case PHY_POLL:
index d15dd3938ba82624fd693b5a6f77301bb6d26bde..2e5150b0b8d52c5dd784a3df1818962d64972898 100644 (file)
@@ -44,7 +44,7 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev)
        priv->phy_drv->read_status(phydev);
 
        val = mdiobus_read(phydev->mdio.bus, priv->addr, XILINX_GMII2RGMII_REG);
-       val &= XILINX_GMII2RGMII_SPEED_MASK;
+       val &= ~XILINX_GMII2RGMII_SPEED_MASK;
 
        if (phydev->speed == SPEED_1000)
                val |= BMCR_SPEED1000;
index b99a7fb09f8e31827a725151b415967699cdfa27..0161f77641fac8eafc1284a5457a7ccb273efc39 100644 (file)
@@ -1265,30 +1265,45 @@ static int lan78xx_ethtool_get_eeprom(struct net_device *netdev,
                                      struct ethtool_eeprom *ee, u8 *data)
 {
        struct lan78xx_net *dev = netdev_priv(netdev);
+       int ret;
+
+       ret = usb_autopm_get_interface(dev->intf);
+       if (ret)
+               return ret;
 
        ee->magic = LAN78XX_EEPROM_MAGIC;
 
-       return lan78xx_read_raw_eeprom(dev, ee->offset, ee->len, data);
+       ret = lan78xx_read_raw_eeprom(dev, ee->offset, ee->len, data);
+
+       usb_autopm_put_interface(dev->intf);
+
+       return ret;
 }
 
 static int lan78xx_ethtool_set_eeprom(struct net_device *netdev,
                                      struct ethtool_eeprom *ee, u8 *data)
 {
        struct lan78xx_net *dev = netdev_priv(netdev);
+       int ret;
+
+       ret = usb_autopm_get_interface(dev->intf);
+       if (ret)
+               return ret;
 
-       /* Allow entire eeprom update only */
-       if ((ee->magic == LAN78XX_EEPROM_MAGIC) &&
-           (ee->offset == 0) &&
-           (ee->len == 512) &&
-           (data[0] == EEPROM_INDICATOR))
-               return lan78xx_write_raw_eeprom(dev, ee->offset, ee->len, data);
+       /* Invalid EEPROM_INDICATOR at offset zero will result in a failure
+        * to load data from EEPROM
+        */
+       if (ee->magic == LAN78XX_EEPROM_MAGIC)
+               ret = lan78xx_write_raw_eeprom(dev, ee->offset, ee->len, data);
        else if ((ee->magic == LAN78XX_OTP_MAGIC) &&
                 (ee->offset == 0) &&
                 (ee->len == 512) &&
                 (data[0] == OTP_INDICATOR_1))
-               return lan78xx_write_raw_otp(dev, ee->offset, ee->len, data);
+               ret = lan78xx_write_raw_otp(dev, ee->offset, ee->len, data);
+
+       usb_autopm_put_interface(dev->intf);
 
-       return -EINVAL;
+       return ret;
 }
 
 static void lan78xx_get_strings(struct net_device *netdev, u32 stringset,
@@ -2434,7 +2449,6 @@ static int lan78xx_reset(struct lan78xx_net *dev)
        /* LAN7801 only has RGMII mode */
        if (dev->chipid == ID_REV_CHIP_ID_7801_)
                buf &= ~MAC_CR_GMII_EN_;
-       buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_;
        ret = lan78xx_write_reg(dev, MAC_CR, buf);
 
        ret = lan78xx_read_reg(dev, MAC_TX, &buf);
index 1427a386a033e72f1f8ec7b4fe02471e9d5d92fb..3e4d1e7998dacb13df8638763eb4fa0181e73357 100644 (file)
@@ -1417,6 +1417,15 @@ static int btt_claim_class(struct device *dev)
                struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
                struct nd_namespace_index *nsindex;
 
+               /*
+                * If any of the DIMMs do not support labels the only
+                * possible BTT format is v1.
+                */
+               if (!ndd) {
+                       loop_bitmask = 0;
+                       break;
+               }
+
                nsindex = to_namespace_index(ndd, ndd->ns_current);
                if (nsindex == NULL)
                        loop_bitmask |= 1;
index acc816b67582f30524ad19f66843b071dfcef6ae..bb2aad07863736c44adbcad9f43f0efb14d17bb7 100644 (file)
@@ -134,8 +134,6 @@ static inline bool nvme_req_needs_retry(struct request *req)
                return false;
        if (nvme_req(req)->status & NVME_SC_DNR)
                return false;
-       if (jiffies - req->start_time >= req->timeout)
-               return false;
        if (nvme_req(req)->retries >= nvme_max_retries)
                return false;
        return true;
@@ -2590,7 +2588,7 @@ static void nvme_async_event_work(struct work_struct *work)
                container_of(work, struct nvme_ctrl, async_event_work);
 
        spin_lock_irq(&ctrl->lock);
-       while (ctrl->event_limit > 0) {
+       while (ctrl->state == NVME_CTRL_LIVE && ctrl->event_limit > 0) {
                int aer_idx = --ctrl->event_limit;
 
                spin_unlock_irq(&ctrl->lock);
@@ -2677,7 +2675,8 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
                /*FALLTHRU*/
        case NVME_SC_ABORT_REQ:
                ++ctrl->event_limit;
-               queue_work(nvme_wq, &ctrl->async_event_work);
+               if (ctrl->state == NVME_CTRL_LIVE)
+                       queue_work(nvme_wq, &ctrl->async_event_work);
                break;
        default:
                break;
@@ -2692,7 +2691,7 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
                nvme_queue_scan(ctrl);
                break;
        case NVME_AER_NOTICE_FW_ACT_STARTING:
-               schedule_work(&ctrl->fw_act_work);
+               queue_work(nvme_wq, &ctrl->fw_act_work);
                break;
        default:
                dev_warn(ctrl->device, "async event result %08x\n", result);
index 47307752dc65d3b9e78f7ab736cfc33831c6522b..555c976cc2ee7aae729c6465003b5cdffa11d594 100644 (file)
@@ -565,6 +565,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
        opts->queue_size = NVMF_DEF_QUEUE_SIZE;
        opts->nr_io_queues = num_online_cpus();
        opts->reconnect_delay = NVMF_DEF_RECONNECT_DELAY;
+       opts->kato = NVME_DEFAULT_KATO;
 
        options = o = kstrdup(buf, GFP_KERNEL);
        if (!options)
@@ -655,21 +656,22 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
                                goto out;
                        }
 
-                       if (opts->discovery_nqn) {
-                               pr_err("Discovery controllers cannot accept keep_alive_tmo != 0\n");
-                               ret = -EINVAL;
-                               goto out;
-                       }
-
                        if (token < 0) {
                                pr_err("Invalid keep_alive_tmo %d\n", token);
                                ret = -EINVAL;
                                goto out;
-                       } else if (token == 0) {
+                       } else if (token == 0 && !opts->discovery_nqn) {
                                /* Allowed for debug */
                                pr_warn("keep_alive_tmo 0 won't execute keep alives!!!\n");
                        }
                        opts->kato = token;
+
+                       if (opts->discovery_nqn && opts->kato) {
+                               pr_err("Discovery controllers cannot accept KATO != 0\n");
+                               ret = -EINVAL;
+                               goto out;
+                       }
+
                        break;
                case NVMF_OPT_CTRL_LOSS_TMO:
                        if (match_int(args, &token)) {
@@ -762,8 +764,6 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
        uuid_copy(&opts->host->id, &hostid);
 
 out:
-       if (!opts->discovery_nqn && !opts->kato)
-               opts->kato = NVME_DEFAULT_KATO;
        kfree(options);
        return ret;
 }
index d2e882c0f4968e40eb256a3b0f08c8c200611810..af075e9989449e97d7b32038d8e30a1cf0875ad6 100644 (file)
@@ -1376,7 +1376,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
        if (atomic_read(&op->state) == FCPOP_STATE_ABORTED)
                status = cpu_to_le16((NVME_SC_ABORT_REQ | NVME_SC_DNR) << 1);
        else if (freq->status)
-               status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1);
+               status = cpu_to_le16(NVME_SC_INTERNAL << 1);
 
        /*
         * For the linux implementation, if we have an unsuccesful
@@ -1404,7 +1404,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
                 */
                if (freq->transferred_length !=
                        be32_to_cpu(op->cmd_iu.data_len)) {
-                       status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1);
+                       status = cpu_to_le16(NVME_SC_INTERNAL << 1);
                        goto done;
                }
                result.u64 = 0;
@@ -1421,7 +1421,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
                                        freq->transferred_length ||
                             op->rsp_iu.status_code ||
                             sqe->common.command_id != cqe->command_id)) {
-                       status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1);
+                       status = cpu_to_le16(NVME_SC_INTERNAL << 1);
                        goto done;
                }
                result = cqe->result;
@@ -1429,7 +1429,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
                break;
 
        default:
-               status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1);
+               status = cpu_to_le16(NVME_SC_INTERNAL << 1);
                goto done;
        }
 
@@ -1989,16 +1989,17 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
         * as well as those by FC-NVME spec.
         */
        WARN_ON_ONCE(sqe->common.metadata);
-       WARN_ON_ONCE(sqe->common.dptr.prp1);
-       WARN_ON_ONCE(sqe->common.dptr.prp2);
        sqe->common.flags |= NVME_CMD_SGL_METABUF;
 
        /*
-        * format SQE DPTR field per FC-NVME rules
-        *    type=data block descr; subtype=offset;
-        *    offset is currently 0.
+        * format SQE DPTR field per FC-NVME rules:
+        *    type=0x5     Transport SGL Data Block Descriptor
+        *    subtype=0xA  Transport-specific value
+        *    address=0
+        *    length=length of the data series
         */
-       sqe->rw.dptr.sgl.type = NVME_SGL_FMT_OFFSET;
+       sqe->rw.dptr.sgl.type = (NVME_TRANSPORT_SGL_DATA_DESC << 4) |
+                                       NVME_SGL_FMT_TRANSPORT_A;
        sqe->rw.dptr.sgl.length = cpu_to_le32(data_len);
        sqe->rw.dptr.sgl.addr = 0;
 
index 4a2121335f48a0b4af31b413e04af8f9a6a52a2e..cb73bc8cad3bd2c332bdf3c7c4903e1b0c0f035c 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/once.h>
 #include <linux/pci.h>
 #include <linux/poison.h>
 #include <linux/t10-pi.h>
@@ -540,6 +541,20 @@ static void nvme_dif_complete(u32 p, u32 v, struct t10_pi_tuple *pi)
 }
 #endif
 
+static void nvme_print_sgl(struct scatterlist *sgl, int nents)
+{
+       int i;
+       struct scatterlist *sg;
+
+       for_each_sg(sgl, sg, nents, i) {
+               dma_addr_t phys = sg_phys(sg);
+               pr_warn("sg[%d] phys_addr:%pad offset:%d length:%d "
+                       "dma_address:%pad dma_length:%d\n",
+                       i, &phys, sg->offset, sg->length, &sg_dma_address(sg),
+                       sg_dma_len(sg));
+       }
+}
+
 static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req)
 {
        struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
@@ -622,19 +637,10 @@ static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req)
        return BLK_STS_OK;
 
  bad_sgl:
-       if (WARN_ONCE(1, "Invalid SGL for payload:%d nents:%d\n",
-                               blk_rq_payload_bytes(req), iod->nents)) {
-               for_each_sg(iod->sg, sg, iod->nents, i) {
-                       dma_addr_t phys = sg_phys(sg);
-                       pr_warn("sg[%d] phys_addr:%pad offset:%d length:%d "
-                              "dma_address:%pad dma_length:%d\n", i, &phys,
-                                       sg->offset, sg->length,
-                                       &sg_dma_address(sg),
-                                       sg_dma_len(sg));
-               }
-       }
+       WARN(DO_ONCE(nvme_print_sgl, iod->sg, iod->nents),
+                       "Invalid SGL for payload:%d nents:%d\n",
+                       blk_rq_payload_bytes(req), iod->nents);
        return BLK_STS_IOERR;
-
 }
 
 static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
@@ -1313,11 +1319,11 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
        if (result < 0)
                goto release_cq;
 
+       nvme_init_queue(nvmeq, qid);
        result = queue_request_irq(nvmeq);
        if (result < 0)
                goto release_sq;
 
-       nvme_init_queue(nvmeq, qid);
        return result;
 
  release_sq:
@@ -1464,6 +1470,7 @@ static int nvme_pci_configure_admin_queue(struct nvme_dev *dev)
                return result;
 
        nvmeq->cq_vector = 0;
+       nvme_init_queue(nvmeq, 0);
        result = queue_request_irq(nvmeq);
        if (result) {
                nvmeq->cq_vector = -1;
@@ -2156,7 +2163,6 @@ static void nvme_reset_work(struct work_struct *work)
        if (result)
                goto out;
 
-       nvme_init_queue(dev->queues[0], 0);
        result = nvme_alloc_admin_tags(dev);
        if (result)
                goto out;
index 58983000964be4c2ce3280ca9f4dda768979ed76..92a03ff5fb4d4392c8726a8cd556d9476fc5c0a1 100644 (file)
@@ -942,7 +942,12 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
        }
 
        changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
-       WARN_ON_ONCE(!changed);
+       if (!changed) {
+               /* state change failure is ok if we're in DELETING state */
+               WARN_ON_ONCE(ctrl->ctrl.state != NVME_CTRL_DELETING);
+               return;
+       }
+
        ctrl->ctrl.nr_reconnects = 0;
 
        nvme_start_ctrl(&ctrl->ctrl);
@@ -962,7 +967,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
        struct nvme_rdma_ctrl *ctrl = container_of(work,
                        struct nvme_rdma_ctrl, err_work);
 
-       nvme_stop_ctrl(&ctrl->ctrl);
+       nvme_stop_keep_alive(&ctrl->ctrl);
 
        if (ctrl->ctrl.queue_count > 1) {
                nvme_stop_queues(&ctrl->ctrl);
index 7c23eaf8e5639c14b5824fad26bdd4d6642e45b1..1b208beeef5097c6e4a2bd38e112543b8818af19 100644 (file)
@@ -390,10 +390,10 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
        if (status)
                nvmet_set_status(req, status);
 
-       /* XXX: need to fill in something useful for sq_head */
-       req->rsp->sq_head = 0;
-       if (likely(req->sq)) /* may happen during early failure */
-               req->rsp->sq_id = cpu_to_le16(req->sq->qid);
+       if (req->sq->size)
+               req->sq->sqhd = (req->sq->sqhd + 1) % req->sq->size;
+       req->rsp->sq_head = cpu_to_le16(req->sq->sqhd);
+       req->rsp->sq_id = cpu_to_le16(req->sq->qid);
        req->rsp->command_id = req->cmd->common.command_id;
 
        if (req->ns)
@@ -420,6 +420,7 @@ void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq,
 void nvmet_sq_setup(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq,
                u16 qid, u16 size)
 {
+       sq->sqhd = 0;
        sq->qid = qid;
        sq->size = size;
 
index 859a66725291d62bbf6f12a06b8486a9c5edbcc2..db3bf6b8bf9ee63581661310aa98820a7341445b 100644 (file)
@@ -109,9 +109,14 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
                pr_warn("queue already connected!\n");
                return NVME_SC_CONNECT_CTRL_BUSY | NVME_SC_DNR;
        }
+       if (!sqsize) {
+               pr_warn("queue size zero!\n");
+               return NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+       }
 
-       nvmet_cq_setup(ctrl, req->cq, qid, sqsize);
-       nvmet_sq_setup(ctrl, req->sq, qid, sqsize);
+       /* note: convert queue size from 0's-based value to 1's-based value */
+       nvmet_cq_setup(ctrl, req->cq, qid, sqsize + 1);
+       nvmet_sq_setup(ctrl, req->sq, qid, sqsize + 1);
        return 0;
 }
 
index 421e43bf1dd78f5d15f1ffb7cf88d36575ec3503..58e010bdda3ea5c155da5c268f542a6939e5c786 100644 (file)
@@ -148,7 +148,7 @@ struct nvmet_fc_tgt_assoc {
        u32                             a_id;
        struct nvmet_fc_tgtport         *tgtport;
        struct list_head                a_list;
-       struct nvmet_fc_tgt_queue       *queues[NVMET_NR_QUEUES];
+       struct nvmet_fc_tgt_queue       *queues[NVMET_NR_QUEUES + 1];
        struct kref                     ref;
 };
 
@@ -608,7 +608,7 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc,
        unsigned long flags;
        int ret;
 
-       if (qid >= NVMET_NR_QUEUES)
+       if (qid > NVMET_NR_QUEUES)
                return NULL;
 
        queue = kzalloc((sizeof(*queue) +
@@ -783,6 +783,9 @@ nvmet_fc_find_target_queue(struct nvmet_fc_tgtport *tgtport,
        u16 qid = nvmet_fc_getqueueid(connection_id);
        unsigned long flags;
 
+       if (qid > NVMET_NR_QUEUES)
+               return NULL;
+
        spin_lock_irqsave(&tgtport->lock, flags);
        list_for_each_entry(assoc, &tgtport->assoc_list, a_list) {
                if (association_id == assoc->association_id) {
@@ -888,7 +891,7 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc)
        int i;
 
        spin_lock_irqsave(&tgtport->lock, flags);
-       for (i = NVMET_NR_QUEUES - 1; i >= 0; i--) {
+       for (i = NVMET_NR_QUEUES; i >= 0; i--) {
                queue = assoc->queues[i];
                if (queue) {
                        if (!nvmet_fc_tgt_q_get(queue))
@@ -1910,8 +1913,7 @@ nvmet_fc_transfer_fcp_data(struct nvmet_fc_tgtport *tgtport,
                        spin_lock_irqsave(&fod->flock, flags);
                        fod->writedataactive = false;
                        spin_unlock_irqrestore(&fod->flock, flags);
-                       nvmet_req_complete(&fod->req,
-                                       NVME_SC_FC_TRANSPORT_ERROR);
+                       nvmet_req_complete(&fod->req, NVME_SC_INTERNAL);
                } else /* NVMET_FCOP_READDATA or NVMET_FCOP_READDATA_RSP */ {
                        fcpreq->fcp_error = ret;
                        fcpreq->transferred_length = 0;
@@ -1929,8 +1931,7 @@ __nvmet_fc_fod_op_abort(struct nvmet_fc_fcp_iod *fod, bool abort)
        /* if in the middle of an io and we need to tear down */
        if (abort) {
                if (fcpreq->op == NVMET_FCOP_WRITEDATA) {
-                       nvmet_req_complete(&fod->req,
-                                       NVME_SC_FC_TRANSPORT_ERROR);
+                       nvmet_req_complete(&fod->req, NVME_SC_INTERNAL);
                        return true;
                }
 
@@ -1968,8 +1969,7 @@ nvmet_fc_fod_op_done(struct nvmet_fc_fcp_iod *fod)
                        fod->abort = true;
                        spin_unlock(&fod->flock);
 
-                       nvmet_req_complete(&fod->req,
-                                       NVME_SC_FC_TRANSPORT_ERROR);
+                       nvmet_req_complete(&fod->req, NVME_SC_INTERNAL);
                        return;
                }
 
@@ -2533,13 +2533,17 @@ nvmet_fc_remove_port(struct nvmet_port *port)
 {
        struct nvmet_fc_tgtport *tgtport = port->priv;
        unsigned long flags;
+       bool matched = false;
 
        spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
        if (tgtport->port == port) {
-               nvmet_fc_tgtport_put(tgtport);
+               matched = true;
                tgtport->port = NULL;
        }
        spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
+
+       if (matched)
+               nvmet_fc_tgtport_put(tgtport);
 }
 
 static struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops = {
index 1cb9847ec261182dd5fdc6da836d14fa1503ad9b..7b75d9de55ab0d33939bf314a81ee01e26a6d1b1 100644 (file)
@@ -224,8 +224,6 @@ struct fcloop_nport {
        struct fcloop_lport *lport;
        struct list_head nport_list;
        struct kref ref;
-       struct completion rport_unreg_done;
-       struct completion tport_unreg_done;
        u64 node_name;
        u64 port_name;
        u32 port_role;
@@ -576,7 +574,7 @@ fcloop_tgt_fcp_abort(struct nvmet_fc_target_port *tgtport,
        tfcp_req->aborted = true;
        spin_unlock(&tfcp_req->reqlock);
 
-       tfcp_req->status = NVME_SC_FC_TRANSPORT_ABORTED;
+       tfcp_req->status = NVME_SC_INTERNAL;
 
        /*
         * nothing more to do. If io wasn't active, the transport should
@@ -630,6 +628,32 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
        schedule_work(&inireq->iniwork);
 }
 
+static void
+fcloop_nport_free(struct kref *ref)
+{
+       struct fcloop_nport *nport =
+               container_of(ref, struct fcloop_nport, ref);
+       unsigned long flags;
+
+       spin_lock_irqsave(&fcloop_lock, flags);
+       list_del(&nport->nport_list);
+       spin_unlock_irqrestore(&fcloop_lock, flags);
+
+       kfree(nport);
+}
+
+static void
+fcloop_nport_put(struct fcloop_nport *nport)
+{
+       kref_put(&nport->ref, fcloop_nport_free);
+}
+
+static int
+fcloop_nport_get(struct fcloop_nport *nport)
+{
+       return kref_get_unless_zero(&nport->ref);
+}
+
 static void
 fcloop_localport_delete(struct nvme_fc_local_port *localport)
 {
@@ -644,8 +668,7 @@ fcloop_remoteport_delete(struct nvme_fc_remote_port *remoteport)
 {
        struct fcloop_rport *rport = remoteport->private;
 
-       /* release any threads waiting for the unreg to complete */
-       complete(&rport->nport->rport_unreg_done);
+       fcloop_nport_put(rport->nport);
 }
 
 static void
@@ -653,8 +676,7 @@ fcloop_targetport_delete(struct nvmet_fc_target_port *targetport)
 {
        struct fcloop_tport *tport = targetport->private;
 
-       /* release any threads waiting for the unreg to complete */
-       complete(&tport->nport->tport_unreg_done);
+       fcloop_nport_put(tport->nport);
 }
 
 #define        FCLOOP_HW_QUEUES                4
@@ -722,6 +744,7 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
                goto out_free_opts;
        }
 
+       memset(&pinfo, 0, sizeof(pinfo));
        pinfo.node_name = opts->wwnn;
        pinfo.port_name = opts->wwpn;
        pinfo.port_role = opts->roles;
@@ -804,32 +827,6 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
        return ret ? ret : count;
 }
 
-static void
-fcloop_nport_free(struct kref *ref)
-{
-       struct fcloop_nport *nport =
-               container_of(ref, struct fcloop_nport, ref);
-       unsigned long flags;
-
-       spin_lock_irqsave(&fcloop_lock, flags);
-       list_del(&nport->nport_list);
-       spin_unlock_irqrestore(&fcloop_lock, flags);
-
-       kfree(nport);
-}
-
-static void
-fcloop_nport_put(struct fcloop_nport *nport)
-{
-       kref_put(&nport->ref, fcloop_nport_free);
-}
-
-static int
-fcloop_nport_get(struct fcloop_nport *nport)
-{
-       return kref_get_unless_zero(&nport->ref);
-}
-
 static struct fcloop_nport *
 fcloop_alloc_nport(const char *buf, size_t count, bool remoteport)
 {
@@ -938,6 +935,7 @@ fcloop_create_remote_port(struct device *dev, struct device_attribute *attr,
        if (!nport)
                return -EIO;
 
+       memset(&pinfo, 0, sizeof(pinfo));
        pinfo.node_name = nport->node_name;
        pinfo.port_name = nport->port_name;
        pinfo.port_role = nport->port_role;
@@ -979,24 +977,12 @@ __unlink_remote_port(struct fcloop_nport *nport)
 }
 
 static int
-__wait_remoteport_unreg(struct fcloop_nport *nport, struct fcloop_rport *rport)
+__remoteport_unreg(struct fcloop_nport *nport, struct fcloop_rport *rport)
 {
-       int ret;
-
        if (!rport)
                return -EALREADY;
 
-       init_completion(&nport->rport_unreg_done);
-
-       ret = nvme_fc_unregister_remoteport(rport->remoteport);
-       if (ret)
-               return ret;
-
-       wait_for_completion(&nport->rport_unreg_done);
-
-       fcloop_nport_put(nport);
-
-       return ret;
+       return nvme_fc_unregister_remoteport(rport->remoteport);
 }
 
 static ssize_t
@@ -1029,7 +1015,7 @@ fcloop_delete_remote_port(struct device *dev, struct device_attribute *attr,
        if (!nport)
                return -ENOENT;
 
-       ret = __wait_remoteport_unreg(nport, rport);
+       ret = __remoteport_unreg(nport, rport);
 
        return ret ? ret : count;
 }
@@ -1086,24 +1072,12 @@ __unlink_target_port(struct fcloop_nport *nport)
 }
 
 static int
-__wait_targetport_unreg(struct fcloop_nport *nport, struct fcloop_tport *tport)
+__targetport_unreg(struct fcloop_nport *nport, struct fcloop_tport *tport)
 {
-       int ret;
-
        if (!tport)
                return -EALREADY;
 
-       init_completion(&nport->tport_unreg_done);
-
-       ret = nvmet_fc_unregister_targetport(tport->targetport);
-       if (ret)
-               return ret;
-
-       wait_for_completion(&nport->tport_unreg_done);
-
-       fcloop_nport_put(nport);
-
-       return ret;
+       return nvmet_fc_unregister_targetport(tport->targetport);
 }
 
 static ssize_t
@@ -1136,7 +1110,7 @@ fcloop_delete_target_port(struct device *dev, struct device_attribute *attr,
        if (!nport)
                return -ENOENT;
 
-       ret = __wait_targetport_unreg(nport, tport);
+       ret = __targetport_unreg(nport, tport);
 
        return ret ? ret : count;
 }
@@ -1223,11 +1197,11 @@ static void __exit fcloop_exit(void)
 
                spin_unlock_irqrestore(&fcloop_lock, flags);
 
-               ret = __wait_targetport_unreg(nport, tport);
+               ret = __targetport_unreg(nport, tport);
                if (ret)
                        pr_warn("%s: Failed deleting target port\n", __func__);
 
-               ret = __wait_remoteport_unreg(nport, rport);
+               ret = __remoteport_unreg(nport, rport);
                if (ret)
                        pr_warn("%s: Failed deleting remote port\n", __func__);
 
index 7d261ab894f47b56addb93fe95beee8fda37b8d3..7b8e20adf76029f293569688e8a5c71013c6393d 100644 (file)
@@ -74,6 +74,7 @@ struct nvmet_sq {
        struct percpu_ref       ref;
        u16                     qid;
        u16                     size;
+       u16                     sqhd;
        struct completion       free_done;
        struct completion       confirm_done;
 };
index 4ddc6e8f9fe7431ae24b7a2068ca2eb8a90e0b0e..f9308c2f22e6754d0b50fc627c11a96cf44af8f4 100644 (file)
@@ -251,9 +251,8 @@ err:
        return ret;
 }
 
-static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test)
+static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq)
 {
-       u8 irq;
        u8 msi_count;
        struct pci_epf *epf = epf_test->epf;
        struct pci_epc *epc = epf->epc;
@@ -262,7 +261,6 @@ static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test)
 
        reg->status |= STATUS_IRQ_RAISED;
        msi_count = pci_epc_get_msi(epc);
-       irq = (reg->command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT;
        if (irq > msi_count || msi_count <= 0)
                pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY, 0);
        else
@@ -289,6 +287,8 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
        reg->command = 0;
        reg->status = 0;
 
+       irq = (command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT;
+
        if (command & COMMAND_RAISE_LEGACY_IRQ) {
                reg->status = STATUS_IRQ_RAISED;
                pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY, 0);
@@ -301,7 +301,7 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
                        reg->status |= STATUS_WRITE_FAIL;
                else
                        reg->status |= STATUS_WRITE_SUCCESS;
-               pci_epf_test_raise_irq(epf_test);
+               pci_epf_test_raise_irq(epf_test, irq);
                goto reset_handler;
        }
 
@@ -311,7 +311,7 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
                        reg->status |= STATUS_READ_SUCCESS;
                else
                        reg->status |= STATUS_READ_FAIL;
-               pci_epf_test_raise_irq(epf_test);
+               pci_epf_test_raise_irq(epf_test, irq);
                goto reset_handler;
        }
 
@@ -321,13 +321,12 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
                        reg->status |= STATUS_COPY_SUCCESS;
                else
                        reg->status |= STATUS_COPY_FAIL;
-               pci_epf_test_raise_irq(epf_test);
+               pci_epf_test_raise_irq(epf_test, irq);
                goto reset_handler;
        }
 
        if (command & COMMAND_RAISE_MSI_IRQ) {
                msi_count = pci_epc_get_msi(epc);
-               irq = (command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT;
                if (irq > msi_count || msi_count <= 0)
                        goto reset_handler;
                reg->status = STATUS_IRQ_RAISED;
index 1eecfa301f7fb2efbfd025f70d39b7d159a42dde..8e075ea2743ef41b4ed08065f502527cbe804c82 100644 (file)
@@ -686,7 +686,7 @@ static ssize_t driver_override_store(struct device *dev,
                                     const char *buf, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       char *driver_override, *old = pdev->driver_override, *cp;
+       char *driver_override, *old, *cp;
 
        /* We need to keep extra room for a newline */
        if (count >= (PAGE_SIZE - 1))
@@ -700,12 +700,15 @@ static ssize_t driver_override_store(struct device *dev,
        if (cp)
                *cp = '\0';
 
+       device_lock(dev);
+       old = pdev->driver_override;
        if (strlen(driver_override)) {
                pdev->driver_override = driver_override;
        } else {
                kfree(driver_override);
                pdev->driver_override = NULL;
        }
+       device_unlock(dev);
 
        kfree(old);
 
@@ -716,8 +719,12 @@ static ssize_t driver_override_show(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
+       ssize_t len;
 
-       return snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override);
+       device_lock(dev);
+       len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override);
+       device_unlock(dev);
+       return len;
 }
 static DEVICE_ATTR_RW(driver_override);
 
index 0a9b78705ee810c9e18c6fa1f46551fc27374287..3303dd8d8eb5718f96de5326949ba89a60e9f32e 100644 (file)
@@ -235,6 +235,7 @@ int arm_pmu_acpi_probe(armpmu_init_fn init_fn)
                ret = armpmu_register(pmu);
                if (ret) {
                        pr_warn("Failed to register PMU for CPU%d\n", cpu);
+                       kfree(pmu->name);
                        return ret;
                }
        }
index 85de30f93a9cc45c1fe0d634c7f687947e1a39bb..56a8195096a229c6975d3f78746ecbc4c6169660 100644 (file)
@@ -254,10 +254,12 @@ static int bl_update_status(struct backlight_device *b)
 {
        struct acpi_device *device = bl_get_data(b);
 
-       if (b->props.power == FB_BLANK_POWERDOWN)
-               call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
-       else
-               call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
+       if (fext) {
+               if (b->props.power == FB_BLANK_POWERDOWN)
+                       call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
+               else
+                       call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
+       }
 
        return set_lcd_level(device, b->props.brightness);
 }
index ea19b4ff87a2f00837abd83c8e22a9e21016ff21..29f35e29d4801f83aa74b0a590bdb4412a9caa7c 100644 (file)
@@ -1644,7 +1644,9 @@ void dasd_generic_handle_state_change(struct dasd_device *device)
        dasd_schedule_device_bh(device);
        if (device->block) {
                dasd_schedule_block_bh(device->block);
-               blk_mq_run_hw_queues(device->block->request_queue, true);
+               if (device->block->request_queue)
+                       blk_mq_run_hw_queues(device->block->request_queue,
+                                            true);
        }
 }
 EXPORT_SYMBOL_GPL(dasd_generic_handle_state_change);
@@ -3759,7 +3761,9 @@ int dasd_generic_path_operational(struct dasd_device *device)
        dasd_schedule_device_bh(device);
        if (device->block) {
                dasd_schedule_block_bh(device->block);
-               blk_mq_run_hw_queues(device->block->request_queue, true);
+               if (device->block->request_queue)
+                       blk_mq_run_hw_queues(device->block->request_queue,
+                                            true);
                }
 
        if (!device->stopped)
@@ -4025,7 +4029,9 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
 
        if (device->block) {
                dasd_schedule_block_bh(device->block);
-               blk_mq_run_hw_queues(device->block->request_queue, true);
+               if (device->block->request_queue)
+                       blk_mq_run_hw_queues(device->block->request_queue,
+                                            true);
        }
 
        clear_bit(DASD_FLAG_SUSPENDED, &device->flags);
index 2e7fd966c515107714a4e612aaec5f36a57747b8..eb51893c74a4ba4053fe8d15e064fbf42bed9845 100644 (file)
@@ -249,7 +249,7 @@ static void scm_request_requeue(struct scm_request *scmrq)
 static void scm_request_finish(struct scm_request *scmrq)
 {
        struct scm_blk_dev *bdev = scmrq->bdev;
-       int *error;
+       blk_status_t *error;
        int i;
 
        for (i = 0; i < nr_requests_per_io && scmrq->request[i]; i++) {
@@ -415,7 +415,7 @@ void scm_blk_irq(struct scm_device *scmdev, void *data, blk_status_t error)
 
 static void scm_blk_request_done(struct request *req)
 {
-       int *error = blk_mq_rq_to_pdu(req);
+       blk_status_t *error = blk_mq_rq_to_pdu(req);
 
        blk_mq_end_request(req, *error);
 }
@@ -450,7 +450,7 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
        atomic_set(&bdev->queued_reqs, 0);
 
        bdev->tag_set.ops = &scm_mq_ops;
-       bdev->tag_set.cmd_size = sizeof(int);
+       bdev->tag_set.cmd_size = sizeof(blk_status_t);
        bdev->tag_set.nr_hw_queues = nr_requests;
        bdev->tag_set.queue_depth = nr_requests_per_io * nr_requests;
        bdev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
index 489b583f263d2806db03a909b1c5d92002e7b848..e5c32f4b5287ebc4da569d403475d5624bac43ef 100644 (file)
@@ -1225,10 +1225,16 @@ static int device_is_disconnected(struct ccw_device *cdev)
 static int recovery_check(struct device *dev, void *data)
 {
        struct ccw_device *cdev = to_ccwdev(dev);
+       struct subchannel *sch;
        int *redo = data;
 
        spin_lock_irq(cdev->ccwlock);
        switch (cdev->private->state) {
+       case DEV_STATE_ONLINE:
+               sch = to_subchannel(cdev->dev.parent);
+               if ((sch->schib.pmcw.pam & sch->opm) == sch->vpm)
+                       break;
+               /* fall through */
        case DEV_STATE_DISCONNECTED:
                CIO_MSG_EVENT(3, "recovery: trigger 0.%x.%04x\n",
                              cdev->private->dev_id.ssid,
@@ -1260,7 +1266,7 @@ static void recovery_work_func(struct work_struct *unused)
                }
                spin_unlock_irq(&recovery_lock);
        } else
-               CIO_MSG_EVENT(4, "recovery: end\n");
+               CIO_MSG_EVENT(3, "recovery: end\n");
 }
 
 static DECLARE_WORK(recovery_work, recovery_work_func);
@@ -1274,11 +1280,11 @@ static void recovery_func(unsigned long data)
        schedule_work(&recovery_work);
 }
 
-static void ccw_device_schedule_recovery(void)
+void ccw_device_schedule_recovery(void)
 {
        unsigned long flags;
 
-       CIO_MSG_EVENT(4, "recovery: schedule\n");
+       CIO_MSG_EVENT(3, "recovery: schedule\n");
        spin_lock_irqsave(&recovery_lock, flags);
        if (!timer_pending(&recovery_timer) || (recovery_phase != 0)) {
                recovery_phase = 0;
index ec497af99dd8acfb74c388f990201214ee02713e..69cb70f080a59a46d0c71dbd06a003b527e850d4 100644 (file)
@@ -134,6 +134,7 @@ void ccw_device_set_disconnected(struct ccw_device *cdev);
 void ccw_device_set_notoper(struct ccw_device *cdev);
 
 void ccw_device_set_timeout(struct ccw_device *, int);
+void ccw_device_schedule_recovery(void);
 
 /* Channel measurement facility related */
 void retry_set_schib(struct ccw_device *cdev);
index 12016e32e5193796b471eb5430281bea5b6423f7..f98ea674c3d8054390a5486802fedd482f0dbe16 100644 (file)
@@ -476,6 +476,17 @@ static void create_fake_irb(struct irb *irb, int type)
        }
 }
 
+static void ccw_device_handle_broken_paths(struct ccw_device *cdev)
+{
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
+       u8 broken_paths = (sch->schib.pmcw.pam & sch->opm) ^ sch->vpm;
+
+       if (broken_paths && (cdev->private->path_broken_mask != broken_paths))
+               ccw_device_schedule_recovery();
+
+       cdev->private->path_broken_mask = broken_paths;
+}
+
 void ccw_device_verify_done(struct ccw_device *cdev, int err)
 {
        struct subchannel *sch;
@@ -508,6 +519,7 @@ callback:
                        memset(&cdev->private->irb, 0, sizeof(struct irb));
                }
                ccw_device_report_path_events(cdev);
+               ccw_device_handle_broken_paths(cdev);
                break;
        case -ETIME:
        case -EUSERS:
index 220f49145b2f9bf48e29f92dc06f94ab7a9a0ef2..9a1b56b2df3e5e3eac8e2ad35b5def3bb149b44c 100644 (file)
@@ -131,6 +131,8 @@ struct ccw_device_private {
                                   not operable */
        u8 path_gone_mask;      /* mask of paths, that became unavailable */
        u8 path_new_mask;       /* mask of paths, that became available */
+       u8 path_broken_mask;    /* mask of paths, which were found to be
+                                  unusable */
        struct {
                unsigned int fast:1;    /* post with "channel end" */
                unsigned int repall:1;  /* report every interrupt status */
index a64285ab0728f14c870db3d72b19190d516d44f3..af3e4d3f9735fdc3430eea0ea05cc1a78e2fa306 100644 (file)
@@ -699,13 +699,13 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
        int status;
 
        dresp = (struct aac_mount *) fib_data(fibptr);
-       if (!(fibptr->dev->supplement_adapter_info.supported_options2 &
-           AAC_OPTION_VARIABLE_BLOCK_SIZE))
+       if (!aac_supports_2T(fibptr->dev)) {
                dresp->mnt[0].capacityhigh = 0;
-       if ((le32_to_cpu(dresp->status) != ST_OK) ||
-           (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
-               _aac_probe_container2(context, fibptr);
-               return;
+               if ((le32_to_cpu(dresp->status) == ST_OK) &&
+                       (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
+                       _aac_probe_container2(context, fibptr);
+                       return;
+               }
        }
        scsicmd = (struct scsi_cmnd *) context;
 
index 92fabf2b0c24c4c24f79ae8626d80ef09853816d..403a639574e5ea10c5c8500141204ebc513bd7c1 100644 (file)
@@ -2701,6 +2701,11 @@ static inline int aac_is_src(struct aac_dev *dev)
        return 0;
 }
 
+static inline int aac_supports_2T(struct aac_dev *dev)
+{
+       return (dev->adapter_info.options & AAC_OPT_NEW_COMM_64);
+}
+
 char * get_container_type(unsigned type);
 extern int numacb;
 extern char aac_driver_version[];
index 87cc4a93e637e6db517c12b0c01bb212eb2e8445..62beb259646692c26ea9a05a72cfe26019d24eed 100644 (file)
@@ -906,12 +906,14 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd)
 
        bus = aac_logical_to_phys(scmd_channel(cmd));
        cid = scmd_id(cmd);
-       info = &aac->hba_map[bus][cid];
-       if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS ||
-           info->devtype != AAC_DEVTYPE_NATIVE_RAW)
+
+       if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS)
                return FAILED;
 
-       if (info->reset_state > 0)
+       info = &aac->hba_map[bus][cid];
+
+       if (info->devtype != AAC_DEVTYPE_NATIVE_RAW &&
+           info->reset_state > 0)
                return FAILED;
 
        pr_err("%s: Host adapter reset request. SCSI hang ?\n",
@@ -962,12 +964,14 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd)
 
        bus = aac_logical_to_phys(scmd_channel(cmd));
        cid = scmd_id(cmd);
-       info = &aac->hba_map[bus][cid];
-       if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS ||
-           info->devtype != AAC_DEVTYPE_NATIVE_RAW)
+
+       if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS)
                return FAILED;
 
-       if (info->reset_state > 0)
+       info = &aac->hba_map[bus][cid];
+
+       if (info->devtype != AAC_DEVTYPE_NATIVE_RAW &&
+           info->reset_state > 0)
                return FAILED;
 
        pr_err("%s: Host adapter reset request. SCSI hang ?\n",
index 48c2b2b34b7222ae656ab4f0c9113d59a0d58d24..0c9361c87ec8de8b853f6ccaa6132663a4b982bd 100644 (file)
@@ -740,6 +740,8 @@ static void aac_send_iop_reset(struct aac_dev *dev)
        aac_set_intx_mode(dev);
 
        src_writel(dev, MUnit.IDR, IOP_SRC_RESET_MASK);
+
+       msleep(5000);
 }
 
 static void aac_send_hardware_soft_reset(struct aac_dev *dev)
index 690816f3c6af9a67ff38e801a4e9c440b763f114..421fe869a11ef0cbdb8130aa7b8ebdffbc775236 100644 (file)
@@ -2725,9 +2725,9 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt)
  * Params   : SCpnt  - command causing reset
  * Returns  : one of SCSI_RESET_ macros
  */
-int acornscsi_host_reset(struct Scsi_Host *shpnt)
+int acornscsi_host_reset(struct scsi_cmnd *SCpnt)
 {
-       AS_Host *host = (AS_Host *)shpnt->hostdata;
+       AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata;
        struct scsi_cmnd *SCptr;
     
     host->stats.resets += 1;
@@ -2741,7 +2741,7 @@ int acornscsi_host_reset(struct Scsi_Host *shpnt)
 
        printk(KERN_WARNING "acornscsi_reset: ");
        print_sbic_status(asr, ssr, host->scsi.phase);
-       for (devidx = 0; devidx < 9; devidx ++) {
+       for (devidx = 0; devidx < 9; devidx++)
            acornscsi_dumplog(host, devidx);
     }
 #endif
index 7e7ae786121b6e8458f7a7aa8954141c77e223a5..100bc4c8798d76852adb9224edc763f70f0741ff 100644 (file)
@@ -6131,6 +6131,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                                "Extents and RPI headers enabled.\n");
                }
                mempool_free(mboxq, phba->mbox_mem_pool);
+               rc = -EIO;
                goto out_free_bsmbx;
        }
 
index 79ba3ce063a4f847ce8187d3290ecf5a309f62b9..23bdb1ca106e459355aed0fa7627d2665a7312a3 100644 (file)
@@ -884,7 +884,7 @@ out_err:
                                         wcqe->total_data_placed);
                        nCmd->transferred_length = 0;
                        nCmd->rcv_rsplen = 0;
-                       nCmd->status = NVME_SC_FC_TRANSPORT_ERROR;
+                       nCmd->status = NVME_SC_INTERNAL;
                }
        }
 
index 1f59e7a74c7b7b9dc7db660e6114420bc90ce8b7..6b33a1f24f56169a3a17803e5a6952da2e6445a6 100644 (file)
@@ -180,7 +180,7 @@ static void qla_nvme_sp_done(void *ptr, int res)
                goto rel;
 
        if (unlikely(res == QLA_FUNCTION_FAILED))
-               fd->status = NVME_SC_FC_TRANSPORT_ERROR;
+               fd->status = NVME_SC_INTERNAL;
        else
                fd->status = 0;
 
index 38942050b2656bd104abb465a79b29c4e7039d43..dab876c6547392c0ccb75047c4cb767640407834 100644 (file)
@@ -580,7 +580,8 @@ int scsi_check_sense(struct scsi_cmnd *scmd)
                if (sshdr.asc == 0x20 || /* Invalid command operation code */
                    sshdr.asc == 0x21 || /* Logical block address out of range */
                    sshdr.asc == 0x24 || /* Invalid field in cdb */
-                   sshdr.asc == 0x26) { /* Parameter value invalid */
+                   sshdr.asc == 0x26 || /* Parameter value invalid */
+                   sshdr.asc == 0x27) { /* Write protected */
                        set_host_byte(scmd, DID_TARGET_FAILURE);
                }
                return SUCCESS;
index 3c6bc0081fcbe34afcfc5c398a5637a2d31ae3ab..cbd4495d0ff9dedb92852d029845418e1a173072 100644 (file)
@@ -2739,7 +2739,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
 
        list_for_each_entry(rport, &fc_host->rports, peers) {
 
-               if ((rport->port_state == FC_PORTSTATE_BLOCKED) &&
+               if ((rport->port_state == FC_PORTSTATE_BLOCKED ||
+                    rport->port_state == FC_PORTSTATE_NOTPRESENT) &&
                        (rport->channel == channel)) {
 
                        switch (fc_host->tgtid_bind_type) {
@@ -2876,7 +2877,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
                        memcpy(&rport->port_name, &ids->port_name,
                                sizeof(rport->port_name));
                        rport->port_id = ids->port_id;
-                       rport->roles = ids->roles;
                        rport->port_state = FC_PORTSTATE_ONLINE;
                        rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;
 
@@ -2885,15 +2885,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
                                                fci->f->dd_fcrport_size);
                        spin_unlock_irqrestore(shost->host_lock, flags);
 
-                       if (ids->roles & FC_PORT_ROLE_FCP_TARGET) {
-                               scsi_target_unblock(&rport->dev, SDEV_RUNNING);
-
-                               /* initiate a scan of the target */
-                               spin_lock_irqsave(shost->host_lock, flags);
-                               rport->flags |= FC_RPORT_SCAN_PENDING;
-                               scsi_queue_work(shost, &rport->scan_work);
-                               spin_unlock_irqrestore(shost->host_lock, flags);
-                       }
+                       fc_remote_port_rolechg(rport, ids->roles);
                        return rport;
                }
        }
@@ -3571,7 +3563,7 @@ fc_vport_sched_delete(struct work_struct *work)
 static enum blk_eh_timer_return
 fc_bsg_job_timeout(struct request *req)
 {
-       struct bsg_job *job = (void *) req->special;
+       struct bsg_job *job = blk_mq_rq_to_pdu(req);
        struct Scsi_Host *shost = fc_bsg_to_shost(job);
        struct fc_rport *rport = fc_bsg_to_rport(job);
        struct fc_internal *i = to_fc_internal(shost->transportt);
index 8934f19bce8ea815d696189e7bb075c43cffaa5c..0190aeff5f7fde124da9e5d621a8e20d1f0b3eae 100644 (file)
@@ -3689,7 +3689,7 @@ iscsi_if_rx(struct sk_buff *skb)
                uint32_t group;
 
                nlh = nlmsg_hdr(skb);
-               if (nlh->nlmsg_len < sizeof(*nlh) ||
+               if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) ||
                    skb->len < nlh->nlmsg_len) {
                        break;
                }
index 11c1738c21000862718ec4f60a663409a11c0b6a..fb9f8b5f4673c0883eefbd91242441e37d3d7189 100644 (file)
@@ -2915,8 +2915,6 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
                                sd_config_discard(sdkp, SD_LBP_WS16);
                        else if (sdkp->lbpws10)
                                sd_config_discard(sdkp, SD_LBP_WS10);
-                       else if (sdkp->lbpu && sdkp->max_unmap_blocks)
-                               sd_config_discard(sdkp, SD_LBP_UNMAP);
                        else
                                sd_config_discard(sdkp, SD_LBP_DISABLE);
                }
index cf0e71db9e5146068294ab46fb1db1fa69addbc9..0419c2298eabdb8f80897357a04be66e85e9a4ac 100644 (file)
@@ -828,6 +828,39 @@ static int max_sectors_bytes(struct request_queue *q)
        return max_sectors << 9;
 }
 
+static void
+sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo)
+{
+       Sg_request *srp;
+       int val;
+       unsigned int ms;
+
+       val = 0;
+       list_for_each_entry(srp, &sfp->rq_list, entry) {
+               if (val > SG_MAX_QUEUE)
+                       break;
+               rinfo[val].req_state = srp->done + 1;
+               rinfo[val].problem =
+                       srp->header.masked_status &
+                       srp->header.host_status &
+                       srp->header.driver_status;
+               if (srp->done)
+                       rinfo[val].duration =
+                               srp->header.duration;
+               else {
+                       ms = jiffies_to_msecs(jiffies);
+                       rinfo[val].duration =
+                               (ms > srp->header.duration) ?
+                               (ms - srp->header.duration) : 0;
+               }
+               rinfo[val].orphan = srp->orphan;
+               rinfo[val].sg_io_owned = srp->sg_io_owned;
+               rinfo[val].pack_id = srp->header.pack_id;
+               rinfo[val].usr_ptr = srp->header.usr_ptr;
+               val++;
+       }
+}
+
 static long
 sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
 {
@@ -1012,38 +1045,13 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
                        return -EFAULT;
                else {
                        sg_req_info_t *rinfo;
-                       unsigned int ms;
 
-                       rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
-                                                               GFP_KERNEL);
+                       rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
+                                       GFP_KERNEL);
                        if (!rinfo)
                                return -ENOMEM;
                        read_lock_irqsave(&sfp->rq_list_lock, iflags);
-                       val = 0;
-                       list_for_each_entry(srp, &sfp->rq_list, entry) {
-                               if (val >= SG_MAX_QUEUE)
-                                       break;
-                               memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
-                               rinfo[val].req_state = srp->done + 1;
-                               rinfo[val].problem =
-                                       srp->header.masked_status &
-                                       srp->header.host_status &
-                                       srp->header.driver_status;
-                               if (srp->done)
-                                       rinfo[val].duration =
-                                               srp->header.duration;
-                               else {
-                                       ms = jiffies_to_msecs(jiffies);
-                                       rinfo[val].duration =
-                                               (ms > srp->header.duration) ?
-                                               (ms - srp->header.duration) : 0;
-                               }
-                               rinfo[val].orphan = srp->orphan;
-                               rinfo[val].sg_io_owned = srp->sg_io_owned;
-                               rinfo[val].pack_id = srp->header.pack_id;
-                               rinfo[val].usr_ptr = srp->header.usr_ptr;
-                               val++;
-                       }
+                       sg_fill_request_table(sfp, rinfo);
                        read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
                        result = __copy_to_user(p, rinfo,
                                                SZ_SG_REQ_INFO * SG_MAX_QUEUE);
index 5fbfd9cfb6d63e61c1c89e6a9deb071ce6de2d32..5b3d57fc82d39bc8fdbcfb89582589a2be854357 100644 (file)
@@ -169,6 +169,9 @@ static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
 static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
 {
        struct pci_bar_info *bar = data;
+       unsigned int pos = (offset - PCI_BASE_ADDRESS_0) / 4;
+       const struct resource *res = dev->resource;
+       u32 mask;
 
        if (unlikely(!bar)) {
                pr_warn(DRV_NAME ": driver data not found for %s\n",
@@ -179,7 +182,13 @@ static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
        /* A write to obtain the length must happen as a 32-bit write.
         * This does not (yet) support writing individual bytes
         */
-       if (value == ~0)
+       if (res[pos].flags & IORESOURCE_IO)
+               mask = ~PCI_BASE_ADDRESS_IO_MASK;
+       else if (pos && (res[pos - 1].flags & IORESOURCE_MEM_64))
+               mask = 0;
+       else
+               mask = ~PCI_BASE_ADDRESS_MEM_MASK;
+       if ((value | mask) == ~0U)
                bar->which = 1;
        else {
                u32 tmpval;
index 82a8866758ee0d5ac235430059f74a7bb56b09f8..a1c17000129ba1cb4465df0bc679a0756f8937a3 100644 (file)
@@ -519,64 +519,6 @@ static int __xenbus_map_ring(struct xenbus_device *dev,
        return err;
 }
 
-static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
-                                    grant_ref_t *gnt_refs,
-                                    unsigned int nr_grefs,
-                                    void **vaddr)
-{
-       struct xenbus_map_node *node;
-       struct vm_struct *area;
-       pte_t *ptes[XENBUS_MAX_RING_GRANTS];
-       phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
-       int err = GNTST_okay;
-       int i;
-       bool leaked;
-
-       *vaddr = NULL;
-
-       if (nr_grefs > XENBUS_MAX_RING_GRANTS)
-               return -EINVAL;
-
-       node = kzalloc(sizeof(*node), GFP_KERNEL);
-       if (!node)
-               return -ENOMEM;
-
-       area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, ptes);
-       if (!area) {
-               kfree(node);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < nr_grefs; i++)
-               phys_addrs[i] = arbitrary_virt_to_machine(ptes[i]).maddr;
-
-       err = __xenbus_map_ring(dev, gnt_refs, nr_grefs, node->handles,
-                               phys_addrs,
-                               GNTMAP_host_map | GNTMAP_contains_pte,
-                               &leaked);
-       if (err)
-               goto failed;
-
-       node->nr_handles = nr_grefs;
-       node->pv.area = area;
-
-       spin_lock(&xenbus_valloc_lock);
-       list_add(&node->next, &xenbus_valloc_pages);
-       spin_unlock(&xenbus_valloc_lock);
-
-       *vaddr = area->addr;
-       return 0;
-
-failed:
-       if (!leaked)
-               free_vm_area(area);
-       else
-               pr_alert("leaking VM area %p size %u page(s)", area, nr_grefs);
-
-       kfree(node);
-       return err;
-}
-
 struct map_ring_valloc_hvm
 {
        unsigned int idx;
@@ -725,6 +667,65 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
 }
 EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
 
+#ifdef CONFIG_XEN_PV
+static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev,
+                                    grant_ref_t *gnt_refs,
+                                    unsigned int nr_grefs,
+                                    void **vaddr)
+{
+       struct xenbus_map_node *node;
+       struct vm_struct *area;
+       pte_t *ptes[XENBUS_MAX_RING_GRANTS];
+       phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS];
+       int err = GNTST_okay;
+       int i;
+       bool leaked;
+
+       *vaddr = NULL;
+
+       if (nr_grefs > XENBUS_MAX_RING_GRANTS)
+               return -EINVAL;
+
+       node = kzalloc(sizeof(*node), GFP_KERNEL);
+       if (!node)
+               return -ENOMEM;
+
+       area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, ptes);
+       if (!area) {
+               kfree(node);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < nr_grefs; i++)
+               phys_addrs[i] = arbitrary_virt_to_machine(ptes[i]).maddr;
+
+       err = __xenbus_map_ring(dev, gnt_refs, nr_grefs, node->handles,
+                               phys_addrs,
+                               GNTMAP_host_map | GNTMAP_contains_pte,
+                               &leaked);
+       if (err)
+               goto failed;
+
+       node->nr_handles = nr_grefs;
+       node->pv.area = area;
+
+       spin_lock(&xenbus_valloc_lock);
+       list_add(&node->next, &xenbus_valloc_pages);
+       spin_unlock(&xenbus_valloc_lock);
+
+       *vaddr = area->addr;
+       return 0;
+
+failed:
+       if (!leaked)
+               free_vm_area(area);
+       else
+               pr_alert("leaking VM area %p size %u page(s)", area, nr_grefs);
+
+       kfree(node);
+       return err;
+}
+
 static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
 {
        struct xenbus_map_node *node;
@@ -788,6 +789,12 @@ static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr)
        return err;
 }
 
+static const struct xenbus_ring_ops ring_ops_pv = {
+       .map = xenbus_map_ring_valloc_pv,
+       .unmap = xenbus_unmap_ring_vfree_pv,
+};
+#endif
+
 struct unmap_ring_vfree_hvm
 {
        unsigned int idx;
@@ -916,11 +923,6 @@ enum xenbus_state xenbus_read_driver_state(const char *path)
 }
 EXPORT_SYMBOL_GPL(xenbus_read_driver_state);
 
-static const struct xenbus_ring_ops ring_ops_pv = {
-       .map = xenbus_map_ring_valloc_pv,
-       .unmap = xenbus_unmap_ring_vfree_pv,
-};
-
 static const struct xenbus_ring_ops ring_ops_hvm = {
        .map = xenbus_map_ring_valloc_hvm,
        .unmap = xenbus_unmap_ring_vfree_hvm,
@@ -928,8 +930,10 @@ static const struct xenbus_ring_ops ring_ops_hvm = {
 
 void __init xenbus_ring_ops_init(void)
 {
+#ifdef CONFIG_XEN_PV
        if (!xen_feature(XENFEAT_auto_translated_physmap))
                ring_ops = &ring_ops_pv;
        else
+#endif
                ring_ops = &ring_ops_hvm;
 }
index b51d23f5cafa9eff1cfc9b1936817095a1b3b5e0..280384bf34f13b20b7a0817a36fe49a53d618285 100644 (file)
@@ -107,7 +107,8 @@ static void end_compressed_bio_read(struct bio *bio)
        struct inode *inode;
        struct page *page;
        unsigned long index;
-       int ret;
+       unsigned int mirror = btrfs_io_bio(bio)->mirror_num;
+       int ret = 0;
 
        if (bio->bi_status)
                cb->errors = 1;
@@ -118,6 +119,21 @@ static void end_compressed_bio_read(struct bio *bio)
        if (!refcount_dec_and_test(&cb->pending_bios))
                goto out;
 
+       /*
+        * Record the correct mirror_num in cb->orig_bio so that
+        * read-repair can work properly.
+        */
+       ASSERT(btrfs_io_bio(cb->orig_bio));
+       btrfs_io_bio(cb->orig_bio)->mirror_num = mirror;
+       cb->mirror_num = mirror;
+
+       /*
+        * Some IO in this cb have failed, just skip checksum as there
+        * is no way it could be correct.
+        */
+       if (cb->errors == 1)
+               goto csum_failed;
+
        inode = cb->inode;
        ret = check_compressed_csum(BTRFS_I(inode), cb,
                                    (u64)bio->bi_iter.bi_sector << 9);
index 5a8933da39a75f504c5bb0329a2b62508be40042..899ddaeeacec8dcf1bf280e6c3b30c30eaa8c8c2 100644 (file)
@@ -709,7 +709,6 @@ struct btrfs_delayed_root;
 #define BTRFS_FS_OPEN                          5
 #define BTRFS_FS_QUOTA_ENABLED                 6
 #define BTRFS_FS_QUOTA_ENABLING                        7
-#define BTRFS_FS_QUOTA_DISABLING               8
 #define BTRFS_FS_UPDATE_UUID_TREE_GEN          9
 #define BTRFS_FS_CREATING_FREE_SPACE_TREE      10
 #define BTRFS_FS_BTREE_ERR                     11
index 487bbe4fb3c6e7a92156aec7060dd84e3c2525a0..dfdab849037b70887e9a61d5b1044a313658d437 100644 (file)
@@ -3643,7 +3643,14 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
        u64 flags;
 
        do_barriers = !btrfs_test_opt(fs_info, NOBARRIER);
-       backup_super_roots(fs_info);
+
+       /*
+        * max_mirrors == 0 indicates we're from commit_transaction,
+        * not from fsync where the tree roots in fs_info have not
+        * been consistent on disk.
+        */
+       if (max_mirrors == 0)
+               backup_super_roots(fs_info);
 
        sb = fs_info->super_for_commit;
        dev_item = &sb->dev_item;
index 3e5bb0cdd3cdd46dbc92273d370d9593963820e7..12ab19a4b93e16167d3c58f3a4991ed979fe46e5 100644 (file)
@@ -3471,8 +3471,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
        unsigned int write_flags = 0;
        unsigned long nr_written = 0;
 
-       if (wbc->sync_mode == WB_SYNC_ALL)
-               write_flags = REQ_SYNC;
+       write_flags = wbc_to_write_flags(wbc);
 
        trace___extent_writepage(page, inode, wbc);
 
@@ -3718,7 +3717,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
        unsigned long i, num_pages;
        unsigned long bio_flags = 0;
        unsigned long start, end;
-       unsigned int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META;
+       unsigned int write_flags = wbc_to_write_flags(wbc) | REQ_META;
        int ret = 0;
 
        clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags);
@@ -4063,9 +4062,6 @@ static void flush_epd_write_bio(struct extent_page_data *epd)
        if (epd->bio) {
                int ret;
 
-               bio_set_op_attrs(epd->bio, REQ_OP_WRITE,
-                                epd->sync_io ? REQ_SYNC : 0);
-
                ret = submit_one_bio(epd->bio, 0, epd->bio_flags);
                BUG_ON(ret < 0); /* -ENOMEM */
                epd->bio = NULL;
index 128f3e58634f4a6821b4cf18547db075cfbe03d5..d94e3f68b9b134f8e3027dec70f1952c42e8ce52 100644 (file)
@@ -135,6 +135,18 @@ static inline void btrfs_cleanup_ordered_extents(struct inode *inode,
                                                 const u64 offset,
                                                 const u64 bytes)
 {
+       unsigned long index = offset >> PAGE_SHIFT;
+       unsigned long end_index = (offset + bytes - 1) >> PAGE_SHIFT;
+       struct page *page;
+
+       while (index <= end_index) {
+               page = find_get_page(inode->i_mapping, index);
+               index++;
+               if (!page)
+                       continue;
+               ClearPagePrivate2(page);
+               put_page(page);
+       }
        return __endio_write_update_ordered(inode, offset + PAGE_SIZE,
                                            bytes - PAGE_SIZE, false);
 }
@@ -8357,11 +8369,8 @@ static void btrfs_endio_direct_read(struct bio *bio)
        struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
        blk_status_t err = bio->bi_status;
 
-       if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED) {
+       if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)
                err = btrfs_subio_endio_read(inode, io_bio, err);
-               if (!err)
-                       bio->bi_status = 0;
-       }
 
        unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
                      dip->logical_offset + dip->bytes - 1);
@@ -8369,7 +8378,7 @@ static void btrfs_endio_direct_read(struct bio *bio)
 
        kfree(dip);
 
-       dio_bio->bi_status = bio->bi_status;
+       dio_bio->bi_status = err;
        dio_end_io(dio_bio);
 
        if (io_bio->end_io)
@@ -8387,6 +8396,7 @@ static void __endio_write_update_ordered(struct inode *inode,
        btrfs_work_func_t func;
        u64 ordered_offset = offset;
        u64 ordered_bytes = bytes;
+       u64 last_offset;
        int ret;
 
        if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
@@ -8398,6 +8408,7 @@ static void __endio_write_update_ordered(struct inode *inode,
        }
 
 again:
+       last_offset = ordered_offset;
        ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
                                                   &ordered_offset,
                                                   ordered_bytes,
@@ -8408,6 +8419,12 @@ again:
        btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL);
        btrfs_queue_work(wq, &ordered->work);
 out_test:
+       /*
+        * If btrfs_dec_test_ordered_pending does not find any ordered extent
+        * in the range, we can exit.
+        */
+       if (ordered_offset == last_offset)
+               return;
        /*
         * our bio might span multiple ordered extents.  If we haven't
         * completed the accounting for the whole dio, go back and try again
index d6715c2bcdc472d567bab9fd617e808fbcbd480f..6c7a49faf4e0636e67c9f818893975dc48d7436a 100644 (file)
@@ -2773,9 +2773,9 @@ static long btrfs_ioctl_fs_info(struct btrfs_fs_info *fs_info,
        }
        mutex_unlock(&fs_devices->device_list_mutex);
 
-       fi_args->nodesize = fs_info->super_copy->nodesize;
-       fi_args->sectorsize = fs_info->super_copy->sectorsize;
-       fi_args->clone_alignment = fs_info->super_copy->sectorsize;
+       fi_args->nodesize = fs_info->nodesize;
+       fi_args->sectorsize = fs_info->sectorsize;
+       fi_args->clone_alignment = fs_info->sectorsize;
 
        if (copy_to_user(arg, fi_args, sizeof(*fi_args)))
                ret = -EFAULT;
@@ -3032,7 +3032,7 @@ static int btrfs_cmp_data_prepare(struct inode *src, u64 loff,
 out:
        if (ret)
                btrfs_cmp_data_free(cmp);
-       return 0;
+       return ret;
 }
 
 static int btrfs_cmp_data(u64 len, struct cmp_pages *cmp)
@@ -4061,6 +4061,10 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
                ret = PTR_ERR(new_root);
                goto out;
        }
+       if (!is_fstree(new_root->objectid)) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        path = btrfs_alloc_path();
        if (!path) {
index 5c8b61c86e61f9ed5445f5022a3b20f1134068bf..e172d4843eae2d8eb6f0d29dce38fb7f693f4ed0 100644 (file)
@@ -807,7 +807,6 @@ static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans,
        }
        ret = 0;
 out:
-       set_bit(BTRFS_FS_QUOTA_DISABLING, &root->fs_info->flags);
        btrfs_free_path(path);
        return ret;
 }
@@ -953,7 +952,6 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
        if (!fs_info->quota_root)
                goto out;
        clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
-       set_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags);
        btrfs_qgroup_wait_for_completion(fs_info, false);
        spin_lock(&fs_info->qgroup_lock);
        quota_root = fs_info->quota_root;
@@ -1307,6 +1305,8 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
                }
        }
        ret = del_qgroup_item(trans, quota_root, qgroupid);
+       if (ret && ret != -ENOENT)
+               goto out;
 
        while (!list_empty(&qgroup->groups)) {
                list = list_first_entry(&qgroup->groups,
@@ -2086,8 +2086,6 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
 
        if (test_and_clear_bit(BTRFS_FS_QUOTA_ENABLING, &fs_info->flags))
                set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
-       if (test_and_clear_bit(BTRFS_FS_QUOTA_DISABLING, &fs_info->flags))
-               clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
 
        spin_lock(&fs_info->qgroup_lock);
        while (!list_empty(&fs_info->dirty_qgroups)) {
index 3a49a3c2fca4549a8e6fd19cf4ec9de119aa0a5d..9841faef08ea72d0b50aa3ad3c881bd27bd7fc76 100644 (file)
@@ -2400,11 +2400,11 @@ void free_reloc_roots(struct list_head *list)
        while (!list_empty(list)) {
                reloc_root = list_entry(list->next, struct btrfs_root,
                                        root_list);
+               __del_reloc_root(reloc_root);
                free_extent_buffer(reloc_root->node);
                free_extent_buffer(reloc_root->commit_root);
                reloc_root->node = NULL;
                reloc_root->commit_root = NULL;
-               __del_reloc_root(reloc_root);
        }
 }
 
index 32b043ef8ac9a3e25f492e99cd4fe4ef347205cf..8fd195cfe81b97b92412b95ac645188eb9a5a693 100644 (file)
@@ -2630,7 +2630,7 @@ static int send_create_inode(struct send_ctx *sctx, u64 ino)
        } else {
                btrfs_warn(sctx->send_root->fs_info, "unexpected inode type %o",
                                (int)(mode & S_IFMT));
-               ret = -ENOTSUPP;
+               ret = -EOPNOTSUPP;
                goto out;
        }
 
index ad7f4bab640be36d9f43b8b2f3371a7bd871738f..c800d067fcbf0c8eec90c479eefe5df13e2dc945 100644 (file)
@@ -4181,6 +4181,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
        struct extent_map *em, *n;
        struct list_head extents;
        struct extent_map_tree *tree = &inode->extent_tree;
+       u64 logged_start, logged_end;
        u64 test_gen;
        int ret = 0;
        int num = 0;
@@ -4190,10 +4191,11 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
        down_write(&inode->dio_sem);
        write_lock(&tree->lock);
        test_gen = root->fs_info->last_trans_committed;
+       logged_start = start;
+       logged_end = end;
 
        list_for_each_entry_safe(em, n, &tree->modified_extents, list) {
                list_del_init(&em->list);
-
                /*
                 * Just an arbitrary number, this can be really CPU intensive
                 * once we start getting a lot of extents, and really once we
@@ -4208,6 +4210,12 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
 
                if (em->generation <= test_gen)
                        continue;
+
+               if (em->start < logged_start)
+                       logged_start = em->start;
+               if ((em->start + em->len - 1) > logged_end)
+                       logged_end = em->start + em->len - 1;
+
                /* Need a ref to keep it from getting evicted from cache */
                refcount_inc(&em->refs);
                set_bit(EXTENT_FLAG_LOGGING, &em->flags);
@@ -4216,7 +4224,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
        }
 
        list_sort(NULL, &extents, extent_cmp);
-       btrfs_get_logged_extents(inode, logged_list, start, end);
+       btrfs_get_logged_extents(inode, logged_list, logged_start, logged_end);
        /*
         * Some ordered extents started by fsync might have completed
         * before we could collect them into the list logged_list, which
index 0e8f16c305df192b412b86be4a69acb1a2236243..b39737568c223c208d92b2f4ab73ac0263ad3ff4 100644 (file)
@@ -6166,7 +6166,7 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
        map_length = length;
 
        btrfs_bio_counter_inc_blocked(fs_info);
-       ret = __btrfs_map_block(fs_info, bio_op(bio), logical,
+       ret = __btrfs_map_block(fs_info, btrfs_op(bio), logical,
                                &map_length, &bbio, mirror_num, 1);
        if (ret) {
                btrfs_bio_counter_dec(fs_info);
index 9dd6b836ac9e5b91d60a439995695d72c06c97e5..84edfc60d87a898c810205b912a5eeb8dae9f446 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/sched.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
-#include <linux/utsname.h>
 #include <linux/ratelimit.h>
 
 #include "super.h"
@@ -884,8 +883,8 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
        void *p;
 
        const char* metadata[][2] = {
-               {"hostname", utsname()->nodename},
-               {"kernel_version", utsname()->release},
+               {"hostname", mdsc->nodename},
+               {"kernel_version", init_utsname()->release},
                {"entity_id", opt->name ? : ""},
                {"root", fsopt->server_path ? : "/"},
                {NULL, NULL}
@@ -3539,6 +3538,8 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        init_rwsem(&mdsc->pool_perm_rwsem);
        mdsc->pool_perm_tree = RB_ROOT;
 
+       strncpy(mdsc->nodename, utsname()->nodename,
+               sizeof(mdsc->nodename) - 1);
        return 0;
 }
 
index db57ae98ed345e280358a2ac65e75ac6c71e7c2b..636d6b2ec49cbab44954dc8e3e7fb93616e6756d 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 #include <linux/refcount.h>
+#include <linux/utsname.h>
 
 #include <linux/ceph/types.h>
 #include <linux/ceph/messenger.h>
@@ -368,6 +369,8 @@ struct ceph_mds_client {
 
        struct rw_semaphore     pool_perm_rwsem;
        struct rb_root          pool_perm_tree;
+
+       char nodename[__NEW_UTS_LEN + 1];
 };
 
 extern const char *ceph_mds_op_name(int op);
index 9727e1dcacd558a89e5fa0c206e82b6f0941a99c..cbb9534b89b40bc3f3cc3be31254485b976d2bcb 100644 (file)
@@ -160,8 +160,13 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
                        if ((ses->serverDomain == NULL) ||
                                (ses->serverOS == NULL) ||
                                (ses->serverNOS == NULL)) {
-                               seq_printf(m, "\n%d) entry for %s not fully "
-                                          "displayed\n\t", i, ses->serverName);
+                               seq_printf(m, "\n%d) Name: %s Uses: %d Capability: 0x%x\tSession Status: %d\t",
+                                       i, ses->serverName, ses->ses_count,
+                                       ses->capabilities, ses->status);
+                               if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
+                                       seq_printf(m, "Guest\t");
+                               else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
+                                       seq_printf(m, "Anonymous\t");
                        } else {
                                seq_printf(m,
                                    "\n%d) Name: %s  Domain: %s Uses: %d OS:"
index 180b3356ff8612dfc7f3cd702e350bb284ca1a0d..8c8b75d33f310ce5e258042ff489f942379cdd27 100644 (file)
@@ -461,6 +461,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
                seq_puts(s, ",nocase");
        if (tcon->retry)
                seq_puts(s, ",hard");
+       else
+               seq_puts(s, ",soft");
        if (tcon->use_persistent)
                seq_puts(s, ",persistenthandles");
        else if (tcon->use_resilient)
@@ -1447,7 +1449,7 @@ exit_cifs(void)
        exit_cifs_idmap();
 #endif
 #ifdef CONFIG_CIFS_UPCALL
-       unregister_key_type(&cifs_spnego_key_type);
+       exit_cifs_spnego();
 #endif
        cifs_destroy_request_bufs();
        cifs_destroy_mids();
index 30bf89b1fd9a789ec02070f534d9d9f68b593650..5a10e566f0e610fcaadf0d949e307087f01ecc90 100644 (file)
@@ -149,5 +149,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "2.09"
+#define CIFS_VERSION   "2.10"
 #endif                         /* _CIFSFS_H */
index 808486c29f0dcb40dbda7a86e626d77908d82001..de5b2e1fcce5f35153a84c9cb1c191911b48a728 100644 (file)
@@ -188,6 +188,8 @@ enum smb_version {
 #ifdef CONFIG_CIFS_SMB311
        Smb_311,
 #endif /* SMB311 */
+       Smb_3any,
+       Smb_default,
        Smb_version_err
 };
 
@@ -1701,6 +1703,10 @@ extern struct smb_version_values smb20_values;
 #define SMB21_VERSION_STRING   "2.1"
 extern struct smb_version_operations smb21_operations;
 extern struct smb_version_values smb21_values;
+#define SMBDEFAULT_VERSION_STRING "default"
+extern struct smb_version_values smbdefault_values;
+#define SMB3ANY_VERSION_STRING "3"
+extern struct smb_version_values smb3any_values;
 #define SMB30_VERSION_STRING   "3.0"
 extern struct smb_version_operations smb30_operations;
 extern struct smb_version_values smb30_values;
index 5aa2d278ca841f7aa7d4de0bb892dbdfc7a48645..0bfc2280436df86c7414288b5cb4afefb401127d 100644 (file)
@@ -301,6 +301,8 @@ static const match_table_t cifs_smb_version_tokens = {
        { Smb_311, SMB311_VERSION_STRING },
        { Smb_311, ALT_SMB311_VERSION_STRING },
 #endif /* SMB311 */
+       { Smb_3any, SMB3ANY_VERSION_STRING },
+       { Smb_default, SMBDEFAULT_VERSION_STRING },
        { Smb_version_err, NULL }
 };
 
@@ -1148,6 +1150,14 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
                vol->vals = &smb311_values;
                break;
 #endif /* SMB311 */
+       case Smb_3any:
+               vol->ops = &smb30_operations; /* currently identical with 3.0 */
+               vol->vals = &smb3any_values;
+               break;
+       case Smb_default:
+               vol->ops = &smb30_operations; /* currently identical with 3.0 */
+               vol->vals = &smbdefault_values;
+               break;
        default:
                cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
                return 1;
@@ -1274,9 +1284,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 
        vol->actimeo = CIFS_DEF_ACTIMEO;
 
-       /* FIXME: add autonegotiation for SMB3 or later rather than just SMB3 */
-       vol->ops = &smb30_operations; /* both secure and accepted widely */
-       vol->vals = &smb30_values;
+       /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
+       vol->ops = &smb30_operations;
+       vol->vals = &smbdefault_values;
 
        vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
 
@@ -1988,11 +1998,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 
        if (got_version == false)
                pr_warn("No dialect specified on mount. Default has changed to "
-                       "a more secure dialect, SMB3 (vers=3.0), from CIFS "
+                       "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
                        "(SMB1). To use the less secure SMB1 dialect to access "
-                       "old servers which do not support SMB3 specify vers=1.0"
-                       " on mount. For somewhat newer servers such as Windows "
-                       "7 try vers=2.1.\n");
+                       "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
+                       " on mount.\n");
 
        kfree(mountdata_copy);
        return 0;
@@ -2133,6 +2142,7 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
        if (vol->nosharesock)
                return 0;
 
+       /* BB update this for smb3any and default case */
        if ((server->vals != vol->vals) || (server->ops != vol->ops))
                return 0;
 
@@ -4144,6 +4154,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
        cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
                 server->sec_mode, server->capabilities, server->timeAdj);
 
+       if (ses->auth_key.response) {
+               cifs_dbg(VFS, "Free previous auth_key.response = %p\n",
+                        ses->auth_key.response);
+               kfree(ses->auth_key.response);
+               ses->auth_key.response = NULL;
+               ses->auth_key.len = 0;
+       }
+
        if (server->ops->sess_setup)
                rc = server->ops->sess_setup(xid, ses, nls_info);
 
index 0786f19d288f8e5e5defe2c7a97a26a88c646e87..92fdf9c35de2153fd6f008c4d1306ead6d806c89 100644 (file)
@@ -224,6 +224,13 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
        if (backup_cred(cifs_sb))
                create_options |= CREATE_OPEN_BACKUP_INTENT;
 
+       /* O_SYNC also has bit for O_DSYNC so following check picks up either */
+       if (f_flags & O_SYNC)
+               create_options |= CREATE_WRITE_THROUGH;
+
+       if (f_flags & O_DIRECT)
+               create_options |= CREATE_NO_BUFFER;
+
        oparms.tcon = tcon;
        oparms.cifs_sb = cifs_sb;
        oparms.desired_access = desired_access;
@@ -1102,8 +1109,10 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
        struct cifs_tcon *tcon;
        unsigned int num, max_num, max_buf;
        LOCKING_ANDX_RANGE *buf, *cur;
-       int types[] = {LOCKING_ANDX_LARGE_FILES,
-                      LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
+       static const int types[] = {
+               LOCKING_ANDX_LARGE_FILES,
+               LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES
+       };
        int i;
 
        xid = get_xid();
@@ -1434,8 +1443,10 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
                  unsigned int xid)
 {
        int rc = 0, stored_rc;
-       int types[] = {LOCKING_ANDX_LARGE_FILES,
-                      LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
+       static const int types[] = {
+               LOCKING_ANDX_LARGE_FILES,
+               LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES
+       };
        unsigned int i;
        unsigned int max_num, num, max_buf;
        LOCKING_ANDX_RANGE *buf, *cur;
index a8693632235f02b349db28e8d77aa45e30d4c783..7c732cb4416411e597f2e1a4af96fd8bf7e49beb 100644 (file)
@@ -234,6 +234,8 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
        fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
        fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
        fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
+       /* old POSIX extensions don't get create time */
+
        fattr->cf_mode = le64_to_cpu(info->Permissions);
 
        /*
@@ -2024,6 +2026,19 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
        stat->blksize = CIFS_MAX_MSGSIZE;
        stat->ino = CIFS_I(inode)->uniqueid;
 
+       /* old CIFS Unix Extensions doesn't return create time */
+       if (CIFS_I(inode)->createtime) {
+               stat->result_mask |= STATX_BTIME;
+               stat->btime =
+                     cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
+       }
+
+       stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
+       if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
+               stat->attributes |= STATX_ATTR_COMPRESSED;
+       if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
+               stat->attributes |= STATX_ATTR_ENCRYPTED;
+
        /*
         * If on a multiuser mount without unix extensions or cifsacl being
         * enabled, and the admin hasn't overridden them, set the ownership
index fb2934b9b97cf56f16359702a7bcb81cd6624252..0dafdbae1f8cb35539a138e73330a214f7f72da3 100644 (file)
@@ -426,6 +426,7 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
        return rc;
 }
 
+#ifdef CONFIG_CIFS_XATTR
 static ssize_t
 move_smb2_ea_to_cifs(char *dst, size_t dst_size,
                     struct smb2_file_full_ea_info *src, size_t src_size,
@@ -613,6 +614,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
 
        return rc;
 }
+#endif
 
 static bool
 smb2_can_echo(struct TCP_Server_Info *server)
@@ -3110,6 +3112,46 @@ struct smb_version_values smb21_values = {
        .create_lease_size = sizeof(struct create_lease),
 };
 
+struct smb_version_values smb3any_values = {
+       .version_string = SMB3ANY_VERSION_STRING,
+       .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
+       .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
+       .large_lock_type = 0,
+       .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
+       .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
+       .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+       .header_size = sizeof(struct smb2_hdr),
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+       .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+       .cap_large_files = SMB2_LARGE_FILES,
+       .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+       .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+       .create_lease_size = sizeof(struct create_lease_v2),
+};
+
+struct smb_version_values smbdefault_values = {
+       .version_string = SMBDEFAULT_VERSION_STRING,
+       .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
+       .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
+       .large_lock_type = 0,
+       .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
+       .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
+       .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
+       .header_size = sizeof(struct smb2_hdr),
+       .max_header_size = MAX_SMB2_HDR_SIZE,
+       .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
+       .lock_cmd = SMB2_LOCK,
+       .cap_unix = 0,
+       .cap_nt_find = SMB2_NT_FIND,
+       .cap_large_files = SMB2_LARGE_FILES,
+       .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
+       .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
+       .create_lease_size = sizeof(struct create_lease_v2),
+};
+
 struct smb_version_values smb30_values = {
        .version_string = SMB30_VERSION_STRING,
        .protocol_id = SMB30_PROT_ID,
index 5531e7ee1210eba48915a6a0d4d01b348b386cde..6f0e6343c15e7e329e6de896220c693f337d9829 100644 (file)
@@ -439,7 +439,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req)
        build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt);
        req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
        req->NegotiateContextCount = cpu_to_le16(2);
-       inc_rfc1001_len(req, 4 + sizeof(struct smb2_preauth_neg_context) + 2
+       inc_rfc1001_len(req, 4 + sizeof(struct smb2_preauth_neg_context)
                        + sizeof(struct smb2_encryption_neg_context)); /* calculate hash */
 }
 #else
@@ -491,10 +491,25 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 
        req->hdr.sync_hdr.SessionId = 0;
 
-       req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id);
-
-       req->DialectCount = cpu_to_le16(1); /* One vers= at a time for now */
-       inc_rfc1001_len(req, 2);
+       if (strcmp(ses->server->vals->version_string,
+                  SMB3ANY_VERSION_STRING) == 0) {
+               req->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
+               req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
+               req->DialectCount = cpu_to_le16(2);
+               inc_rfc1001_len(req, 4);
+       } else if (strcmp(ses->server->vals->version_string,
+                  SMBDEFAULT_VERSION_STRING) == 0) {
+               req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
+               req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
+               req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
+               req->DialectCount = cpu_to_le16(3);
+               inc_rfc1001_len(req, 6);
+       } else {
+               /* otherwise send specific dialect */
+               req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id);
+               req->DialectCount = cpu_to_le16(1);
+               inc_rfc1001_len(req, 2);
+       }
 
        /* only one of SMB2 signing flags may be set in SMB2 request */
        if (ses->sign)
@@ -528,16 +543,43 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
         */
        if (rc == -EOPNOTSUPP) {
                cifs_dbg(VFS, "Dialect not supported by server. Consider "
-                       "specifying vers=1.0 or vers=2.1 on mount for accessing"
+                       "specifying vers=1.0 or vers=2.0 on mount for accessing"
                        " older servers\n");
                goto neg_exit;
        } else if (rc != 0)
                goto neg_exit;
 
+       if (strcmp(ses->server->vals->version_string,
+                  SMB3ANY_VERSION_STRING) == 0) {
+               if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
+                       cifs_dbg(VFS,
+                               "SMB2 dialect returned but not requested\n");
+                       return -EIO;
+               } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
+                       cifs_dbg(VFS,
+                               "SMB2.1 dialect returned but not requested\n");
+                       return -EIO;
+               }
+       } else if (strcmp(ses->server->vals->version_string,
+                  SMBDEFAULT_VERSION_STRING) == 0) {
+               if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
+                       cifs_dbg(VFS,
+                               "SMB2 dialect returned but not requested\n");
+                       return -EIO;
+               } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
+                       /* ops set to 3.0 by default for default so update */
+                       ses->server->ops = &smb21_operations;
+               }
+       } else if (le16_to_cpu(rsp->DialectRevision) !=
+                               ses->server->vals->protocol_id) {
+               /* if requested single dialect ensure returned dialect matched */
+               cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n",
+                       le16_to_cpu(rsp->DialectRevision));
+               return -EIO;
+       }
+
        cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
 
-       /* BB we may eventually want to match the negotiated vs. requested
-          dialect, even though we are only requesting one at a time */
        if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID))
                cifs_dbg(FYI, "negotiated smb2.0 dialect\n");
        else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID))
@@ -558,6 +600,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
        }
        server->dialect = le16_to_cpu(rsp->DialectRevision);
 
+       /* BB: add check that dialect was valid given dialect(s) we asked for */
+
        /* SMB2 only has an extended negflavor */
        server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
        /* set it to the maximum buffer size value we can send with 1 credit */
@@ -606,20 +650,28 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
        struct validate_negotiate_info_req vneg_inbuf;
        struct validate_negotiate_info_rsp *pneg_rsp;
        u32 rsplen;
+       u32 inbuflen; /* max of 4 dialects */
 
        cifs_dbg(FYI, "validate negotiate\n");
 
        /*
         * validation ioctl must be signed, so no point sending this if we
-        * can not sign it.  We could eventually change this to selectively
+        * can not sign it (ie are not known user).  Even if signing is not
+        * required (enabled but not negotiated), in those cases we selectively
         * sign just this, the first and only signed request on a connection.
-        * This is good enough for now since a user who wants better security
-        * would also enable signing on the mount. Having validation of
-        * negotiate info for signed connections helps reduce attack vectors
+        * Having validation of negotiate info  helps reduce attack vectors.
         */
-       if (tcon->ses->server->sign == false)
+       if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
                return 0; /* validation requires signing */
 
+       if (tcon->ses->user_name == NULL) {
+               cifs_dbg(FYI, "Can't validate negotiate: null user mount\n");
+               return 0; /* validation requires signing */
+       }
+
+       if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
+               cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n");
+
        vneg_inbuf.Capabilities =
                        cpu_to_le32(tcon->ses->server->vals->req_capabilities);
        memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid,
@@ -634,9 +686,30 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
        else
                vneg_inbuf.SecurityMode = 0;
 
-       vneg_inbuf.DialectCount = cpu_to_le16(1);
-       vneg_inbuf.Dialects[0] =
-               cpu_to_le16(tcon->ses->server->vals->protocol_id);
+
+       if (strcmp(tcon->ses->server->vals->version_string,
+               SMB3ANY_VERSION_STRING) == 0) {
+               vneg_inbuf.Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
+               vneg_inbuf.Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
+               vneg_inbuf.DialectCount = cpu_to_le16(2);
+               /* structure is big enough for 3 dialects, sending only 2 */
+               inbuflen = sizeof(struct validate_negotiate_info_req) - 2;
+       } else if (strcmp(tcon->ses->server->vals->version_string,
+               SMBDEFAULT_VERSION_STRING) == 0) {
+               vneg_inbuf.Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
+               vneg_inbuf.Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
+               vneg_inbuf.Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
+               vneg_inbuf.DialectCount = cpu_to_le16(3);
+               /* structure is big enough for 3 dialects */
+               inbuflen = sizeof(struct validate_negotiate_info_req);
+       } else {
+               /* otherwise specific dialect was requested */
+               vneg_inbuf.Dialects[0] =
+                       cpu_to_le16(tcon->ses->server->vals->protocol_id);
+               vneg_inbuf.DialectCount = cpu_to_le16(1);
+               /* structure is big enough for 3 dialects, sending only 1 */
+               inbuflen = sizeof(struct validate_negotiate_info_req) - 4;
+       }
 
        rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
                FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
@@ -1110,6 +1183,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
        while (sess_data->func)
                sess_data->func(sess_data);
 
+       if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign))
+               cifs_dbg(VFS, "signing requested but authenticated as guest\n");
        rc = sess_data->result;
 out:
        kfree(sess_data);
@@ -1634,7 +1709,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
        struct cifs_tcon *tcon = oparms->tcon;
        struct cifs_ses *ses = tcon->ses;
        struct kvec iov[4];
-       struct kvec rsp_iov;
+       struct kvec rsp_iov = {NULL, 0};
        int resp_buftype;
        int uni_path_len;
        __le16 *copy_path = NULL;
@@ -1763,7 +1838,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
 
        if (rc != 0) {
                cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
-               if (err_buf)
+               if (err_buf && rsp)
                        *err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4,
                                           GFP_KERNEL);
                goto creat_exit;
index 393ed5f4e1b6516b40f30f64890a385a43b44c9a..6c9653a130c8bf38f5c38d6965cea32d105e708d 100644 (file)
@@ -716,7 +716,7 @@ struct validate_negotiate_info_req {
        __u8   Guid[SMB2_CLIENT_GUID_SIZE];
        __le16 SecurityMode;
        __le16 DialectCount;
-       __le16 Dialects[1]; /* dialect (someday maybe list) client asked for */
+       __le16 Dialects[3]; /* BB expand this if autonegotiate > 3 dialects */
 } __packed;
 
 struct validate_negotiate_info_rsp {
index 5fa2211e49aee2186546d8db7a70c5295c7591f0..62cf812ed0e5803ac9148a9ea8a27f00efca7f2a 100644 (file)
@@ -229,6 +229,7 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
 {
        loff_t offset = dio->iocb->ki_pos;
        ssize_t transferred = 0;
+       int err;
 
        /*
         * AIO submission can race with bio completion to get here while
@@ -258,8 +259,22 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
        if (ret == 0)
                ret = transferred;
 
+       /*
+        * Try again to invalidate clean pages which might have been cached by
+        * non-direct readahead, or faulted in by get_user_pages() if the source
+        * of the write was an mmap'ed region of the file we're writing.  Either
+        * one is a pretty crazy thing to do, so we don't support it 100%.  If
+        * this invalidation fails, tough, the write still worked...
+        */
+       if (ret > 0 && dio->op == REQ_OP_WRITE &&
+           dio->inode->i_mapping->nrpages) {
+               err = invalidate_inode_pages2_range(dio->inode->i_mapping,
+                                       offset >> PAGE_SHIFT,
+                                       (offset + ret - 1) >> PAGE_SHIFT);
+               WARN_ON_ONCE(err);
+       }
+
        if (dio->end_io) {
-               int err;
 
                // XXX: ki_pos??
                err = dio->end_io(dio->iocb, offset, ret, dio->private);
@@ -304,6 +319,7 @@ static void dio_bio_end_aio(struct bio *bio)
        struct dio *dio = bio->bi_private;
        unsigned long remaining;
        unsigned long flags;
+       bool defer_completion = false;
 
        /* cleanup the bio */
        dio_bio_complete(dio, bio);
@@ -315,7 +331,19 @@ static void dio_bio_end_aio(struct bio *bio)
        spin_unlock_irqrestore(&dio->bio_lock, flags);
 
        if (remaining == 0) {
-               if (dio->result && dio->defer_completion) {
+               /*
+                * Defer completion when defer_completion is set or
+                * when the inode has pages mapped and this is AIO write.
+                * We need to invalidate those pages because there is a
+                * chance they contain stale data in the case buffered IO
+                * went in between AIO submission and completion into the
+                * same region.
+                */
+               if (dio->result)
+                       defer_completion = dio->defer_completion ||
+                                          (dio->op == REQ_OP_WRITE &&
+                                           dio->inode->i_mapping->nrpages);
+               if (defer_completion) {
                        INIT_WORK(&dio->complete_work, dio_aio_complete_work);
                        queue_work(dio->inode->i_sb->s_dio_done_wq,
                                   &dio->complete_work);
@@ -1210,10 +1238,19 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
         * For AIO O_(D)SYNC writes we need to defer completions to a workqueue
         * so that we can call ->fsync.
         */
-       if (dio->is_async && iov_iter_rw(iter) == WRITE &&
-           ((iocb->ki_filp->f_flags & O_DSYNC) ||
-            IS_SYNC(iocb->ki_filp->f_mapping->host))) {
-               retval = dio_set_defer_completion(dio);
+       if (dio->is_async && iov_iter_rw(iter) == WRITE) {
+               retval = 0;
+               if ((iocb->ki_filp->f_flags & O_DSYNC) ||
+                   IS_SYNC(iocb->ki_filp->f_mapping->host))
+                       retval = dio_set_defer_completion(dio);
+               else if (!dio->inode->i_sb->s_dio_done_wq) {
+                       /*
+                        * In case of AIO write racing with buffered read we
+                        * need to defer completion. We can't decide this now,
+                        * however the workqueue needs to be initialized here.
+                        */
+                       retval = sb_init_dio_done_wq(dio->inode->i_sb);
+               }
                if (retval) {
                        /*
                         * We grab i_mutex only for reads so we don't have
index 0491da3b28c36bbf786f1f1303d3bb44f6bfdb98..448a1119f0becff3d871a98d8e6cee9b673b2652 100644 (file)
@@ -749,7 +749,7 @@ static void send_sigio_to_task(struct task_struct *p,
                         * specific si_codes.  In that case use SI_SIGIO instead
                         * to remove the ambiguity.
                         */
-                       if (sig_specific_sicodes(signum))
+                       if ((signum != SIGPOLL) && sig_specific_sicodes(signum))
                                si.si_code = SI_SIGIO;
 
                        /* Make sure we are called with one of the POLL_*
index 98e845b7841bda81b4bd9000f4ba027639861d27..11066d8647d29320dcb30d063536aa4f218cf5ec 100644 (file)
@@ -1945,13 +1945,9 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
 {
        struct gfs2_glock_iter *gi = seq->private;
        loff_t n = *pos;
-       int ret;
-
-       if (gi->last_pos <= *pos)
-               n = (*pos - gi->last_pos);
 
-       ret = rhashtable_walk_start(&gi->hti);
-       if (ret)
+       rhashtable_walk_enter(&gl_hash_table, &gi->hti);
+       if (rhashtable_walk_start(&gi->hti) != 0)
                return NULL;
 
        do {
@@ -1959,6 +1955,7 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
        } while (gi->gl && n--);
 
        gi->last_pos = *pos;
+
        return gi->gl;
 }
 
@@ -1970,6 +1967,7 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
        (*pos)++;
        gi->last_pos = *pos;
        gfs2_glock_iter_next(gi);
+
        return gi->gl;
 }
 
@@ -1980,6 +1978,7 @@ static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
 
        gi->gl = NULL;
        rhashtable_walk_stop(&gi->hti);
+       rhashtable_walk_exit(&gi->hti);
 }
 
 static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
@@ -2042,12 +2041,10 @@ static int __gfs2_glocks_open(struct inode *inode, struct file *file,
                struct gfs2_glock_iter *gi = seq->private;
 
                gi->sdp = inode->i_private;
-               gi->last_pos = 0;
                seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
                if (seq->buf)
                        seq->size = GFS2_SEQ_GOODSIZE;
                gi->gl = NULL;
-               rhashtable_walk_enter(&gl_hash_table, &gi->hti);
        }
        return ret;
 }
@@ -2063,7 +2060,6 @@ static int gfs2_glocks_release(struct inode *inode, struct file *file)
        struct gfs2_glock_iter *gi = seq->private;
 
        gi->gl = NULL;
-       rhashtable_walk_exit(&gi->hti);
        return seq_release_private(inode, file);
 }
 
index 269b24a01f3218ff9cdb9c1ef5254f3e5a64c3b1..be61cf742b5ed1d0d201ff415e9355fa2684508c 100644 (file)
@@ -713,8 +713,24 @@ struct iomap_dio {
 static ssize_t iomap_dio_complete(struct iomap_dio *dio)
 {
        struct kiocb *iocb = dio->iocb;
+       struct inode *inode = file_inode(iocb->ki_filp);
        ssize_t ret;
 
+       /*
+        * Try again to invalidate clean pages which might have been cached by
+        * non-direct readahead, or faulted in by get_user_pages() if the source
+        * of the write was an mmap'ed region of the file we're writing.  Either
+        * one is a pretty crazy thing to do, so we don't support it 100%.  If
+        * this invalidation fails, tough, the write still worked...
+        */
+       if (!dio->error &&
+           (dio->flags & IOMAP_DIO_WRITE) && inode->i_mapping->nrpages) {
+               ret = invalidate_inode_pages2_range(inode->i_mapping,
+                               iocb->ki_pos >> PAGE_SHIFT,
+                               (iocb->ki_pos + dio->size - 1) >> PAGE_SHIFT);
+               WARN_ON_ONCE(ret);
+       }
+
        if (dio->end_io) {
                ret = dio->end_io(iocb,
                                dio->error ? dio->error : dio->size,
@@ -993,6 +1009,13 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        WARN_ON_ONCE(ret);
        ret = 0;
 
+       if (iov_iter_rw(iter) == WRITE && !is_sync_kiocb(iocb) &&
+           !inode->i_sb->s_dio_done_wq) {
+               ret = sb_init_dio_done_wq(inode->i_sb);
+               if (ret < 0)
+                       goto out_free_dio;
+       }
+
        inode_dio_begin(inode);
 
        blk_start_plug(&plug);
@@ -1015,13 +1038,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        if (ret < 0)
                iomap_dio_set_error(dio, ret);
 
-       if (ret >= 0 && iov_iter_rw(iter) == WRITE && !is_sync_kiocb(iocb) &&
-                       !inode->i_sb->s_dio_done_wq) {
-               ret = sb_init_dio_done_wq(inode->i_sb);
-               if (ret < 0)
-                       iomap_dio_set_error(dio, ret);
-       }
-
        if (!atomic_dec_and_test(&dio->ref)) {
                if (!is_sync_kiocb(iocb))
                        return -EIOCBQUEUED;
@@ -1042,19 +1058,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 
        ret = iomap_dio_complete(dio);
 
-       /*
-        * Try again to invalidate clean pages which might have been cached by
-        * non-direct readahead, or faulted in by get_user_pages() if the source
-        * of the write was an mmap'ed region of the file we're writing.  Either
-        * one is a pretty crazy thing to do, so we don't support it 100%.  If
-        * this invalidation fails, tough, the write still worked...
-        */
-       if (iov_iter_rw(iter) == WRITE) {
-               int err = invalidate_inode_pages2_range(mapping,
-                               start >> PAGE_SHIFT, end >> PAGE_SHIFT);
-               WARN_ON_ONCE(err);
-       }
-
        return ret;
 
 out_free_dio:
index db692f554158854d4fa683d116827594d6ffd978..447a24d77b894ef733412ba201cadcaa9a226f7e 100644 (file)
@@ -514,9 +514,11 @@ static int isofs_show_options(struct seq_file *m, struct dentry *root)
        if (sbi->s_fmode != ISOFS_INVALID_MODE)
                seq_printf(m, ",fmode=%o", sbi->s_fmode);
 
+#ifdef CONFIG_JOLIET
        if (sbi->s_nls_iocharset &&
            strcmp(sbi->s_nls_iocharset->charset, CONFIG_NLS_DEFAULT) != 0)
                seq_printf(m, ",iocharset=%s", sbi->s_nls_iocharset->charset);
+#endif
        return 0;
 }
 
index 88c355574aa0afe3b1a62b371b048af8d948070e..77a8eacbe032f22d5bd9514738341a55dcc46b34 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/mman.h>
 #include <linux/sched/mm.h>
 #include <linux/sched/numa_balancing.h>
+#include <linux/sched/task_stack.h>
 #include <linux/sched/task.h>
 #include <linux/sched/cputime.h>
 #include <linux/proc_fs.h>
@@ -118,30 +119,25 @@ static inline void task_name(struct seq_file *m, struct task_struct *p)
  * simple bit tests.
  */
 static const char * const task_state_array[] = {
-       "R (running)",          /*   0 */
-       "S (sleeping)",         /*   1 */
-       "D (disk sleep)",       /*   2 */
-       "T (stopped)",          /*   4 */
-       "t (tracing stop)",     /*   8 */
-       "X (dead)",             /*  16 */
-       "Z (zombie)",           /*  32 */
+
+       /* states in TASK_REPORT: */
+       "R (running)",          /* 0x00 */
+       "S (sleeping)",         /* 0x01 */
+       "D (disk sleep)",       /* 0x02 */
+       "T (stopped)",          /* 0x04 */
+       "t (tracing stop)",     /* 0x08 */
+       "X (dead)",             /* 0x10 */
+       "Z (zombie)",           /* 0x20 */
+       "P (parked)",           /* 0x40 */
+
+       /* states beyond TASK_REPORT: */
+       "I (idle)",             /* 0x80 */
 };
 
 static inline const char *get_task_state(struct task_struct *tsk)
 {
-       unsigned int state = (tsk->state | tsk->exit_state) & TASK_REPORT;
-
-       /*
-        * Parked tasks do not run; they sit in __kthread_parkme().
-        * Without this check, we would report them as running, which is
-        * clearly wrong, so we report them as sleeping instead.
-        */
-       if (tsk->state == TASK_PARKED)
-               state = TASK_INTERRUPTIBLE;
-
-       BUILD_BUG_ON(1 + ilog2(TASK_REPORT) != ARRAY_SIZE(task_state_array)-1);
-
-       return task_state_array[fls(state)];
+       BUILD_BUG_ON(1 + ilog2(TASK_REPORT_MAX) != ARRAY_SIZE(task_state_array));
+       return task_state_array[__get_task_state(tsk)];
 }
 
 static inline int get_task_umask(struct task_struct *tsk)
@@ -421,7 +417,15 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
                 * esp and eip are intentionally zeroed out.  There is no
                 * non-racy way to read them without freezing the task.
                 * Programs that need reliable values can use ptrace(2).
+                *
+                * The only exception is if the task is core dumping because
+                * a program is not able to use ptrace(2) in that case. It is
+                * safe because the task has stopped executing permanently.
                 */
+               if (permitted && (task->flags & PF_DUMPCORE)) {
+                       eip = KSTK_EIP(task);
+                       esp = KSTK_ESP(task);
+               }
        }
 
        get_task_comm(tcomm, task);
index 8381db9db6d9bcc3acfa645bf9f73cbb5933c564..50b0556a124f2508531ce9e6fc61721aeb179cc8 100644 (file)
@@ -1980,7 +1980,9 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
                ret = dquot_add_space(transfer_to[cnt], cur_space, rsv_space, 0,
                                      &warn_to[cnt]);
                if (ret) {
+                       spin_lock(&transfer_to[cnt]->dq_dqb_lock);
                        dquot_decr_inodes(transfer_to[cnt], inode_usage);
+                       spin_unlock(&transfer_to[cnt]->dq_dqb_lock);
                        goto over_quota;
                }
        }
index c0187cda2c1ed3ff65b449a74aa71c05ca29eb58..a73e5b34db4181272bc943c4e0ea406797ff0311 100644 (file)
@@ -328,12 +328,16 @@ static int v2_write_dquot(struct dquot *dquot)
        if (!dquot->dq_off) {
                alloc = true;
                down_write(&dqopt->dqio_sem);
+       } else {
+               down_read(&dqopt->dqio_sem);
        }
        ret = qtree_write_dquot(
                        sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv,
                        dquot);
        if (alloc)
                up_write(&dqopt->dqio_sem);
+       else
+               up_read(&dqopt->dqio_sem);
        return ret;
 }
 
index a2b9a47235c5ba48b4db2bf81d03c1579b562f79..f0d4b16873e89aa23522c9ece34b8f1900638176 100644 (file)
@@ -112,7 +112,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
                 * In the generic case the entire file is data, so as long as
                 * offset isn't at the end of the file then the offset is data.
                 */
-               if (offset >= eof)
+               if ((unsigned long long)offset >= eof)
                        return -ENXIO;
                break;
        case SEEK_HOLE:
@@ -120,7 +120,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence,
                 * There is a virtual hole at the end of the file, so as long as
                 * offset isn't i_size or larger, return i_size.
                 */
-               if (offset >= eof)
+               if ((unsigned long long)offset >= eof)
                        return -ENXIO;
                offset = eof;
                break;
index b008ff3250eba4f3884e18841c4c316b7e7cbf50..df3e600835e8de81e69ac295b06fae6fecefd7a4 100644 (file)
@@ -156,7 +156,8 @@ __xfs_ag_resv_free(
        trace_xfs_ag_resv_free(pag, type, 0);
 
        resv = xfs_perag_resv(pag, type);
-       pag->pag_mount->m_ag_max_usable += resv->ar_asked;
+       if (pag->pag_agno == 0)
+               pag->pag_mount->m_ag_max_usable += resv->ar_asked;
        /*
         * AGFL blocks are always considered "free", so whatever
         * was reserved at mount time must be given back at umount.
@@ -216,7 +217,14 @@ __xfs_ag_resv_init(
                return error;
        }
 
-       mp->m_ag_max_usable -= ask;
+       /*
+        * Reduce the maximum per-AG allocation length by however much we're
+        * trying to reserve for an AG.  Since this is a filesystem-wide
+        * counter, we only make the adjustment for AG 0.  This assumes that
+        * there aren't any AGs hungrier for per-AG reservation than AG 0.
+        */
+       if (pag->pag_agno == 0)
+               mp->m_ag_max_usable -= ask;
 
        resv = xfs_perag_resv(pag, type);
        resv->ar_asked = ask;
index 459f4b4f08fe5a1eba6fd725cb3a8866a5876a11..044a363119bead470113a35227a8ee6923ebab65 100644 (file)
@@ -49,7 +49,6 @@
 #include "xfs_rmap.h"
 #include "xfs_ag_resv.h"
 #include "xfs_refcount.h"
-#include "xfs_rmap_btree.h"
 #include "xfs_icache.h"
 
 
@@ -192,12 +191,8 @@ xfs_bmap_worst_indlen(
        int             maxrecs;        /* maximum record count at this level */
        xfs_mount_t     *mp;            /* mount structure */
        xfs_filblks_t   rval;           /* return value */
-       xfs_filblks_t   orig_len;
 
        mp = ip->i_mount;
-
-       /* Calculate the worst-case size of the bmbt. */
-       orig_len = len;
        maxrecs = mp->m_bmap_dmxr[0];
        for (level = 0, rval = 0;
             level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
@@ -205,20 +200,12 @@ xfs_bmap_worst_indlen(
                len += maxrecs - 1;
                do_div(len, maxrecs);
                rval += len;
-               if (len == 1) {
-                       rval += XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
+               if (len == 1)
+                       return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
                                level - 1;
-                       break;
-               }
                if (level == 0)
                        maxrecs = mp->m_bmap_dmxr[1];
        }
-
-       /* Calculate the worst-case size of the rmapbt. */
-       if (xfs_sb_version_hasrmapbt(&mp->m_sb))
-               rval += 1 + xfs_rmapbt_calc_size(mp, orig_len) +
-                               mp->m_rmap_maxlevels;
-
        return rval;
 }
 
index 29172609f2a31b756cd40da7b42f288fe8b0915b..f18e5932aec4bfe5f1e1b3fb0d69d1b32c540b16 100644 (file)
@@ -343,7 +343,8 @@ xfs_end_io(
                error = xfs_reflink_end_cow(ip, offset, size);
                break;
        case XFS_IO_UNWRITTEN:
-               error = xfs_iomap_write_unwritten(ip, offset, size);
+               /* writeback should never update isize */
+               error = xfs_iomap_write_unwritten(ip, offset, size, false);
                break;
        default:
                ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_append_trans);
index cd9a5400ba4fef2a75d5c24f3f626f5ad0211fae..bc6c6e10a9699f789b998035fde33973796f46fa 100644 (file)
@@ -1459,7 +1459,19 @@ xfs_shift_file_space(
                return error;
 
        /*
-        * The extent shiting code works on extent granularity. So, if
+        * Clean out anything hanging around in the cow fork now that
+        * we've flushed all the dirty data out to disk to avoid having
+        * CoW extents at the wrong offsets.
+        */
+       if (xfs_is_reflink_inode(ip)) {
+               error = xfs_reflink_cancel_cow_range(ip, offset, NULLFILEOFF,
+                               true);
+               if (error)
+                       return error;
+       }
+
+       /*
+        * The extent shifting code works on extent granularity. So, if
         * stop_fsb is not the starting block of extent, we need to split
         * the extent at stop_fsb.
         */
index da14658da3103475940555600581f0bf12217d55..2f97c12ca75e4d5554b94b7a195b4dca53f90174 100644 (file)
@@ -1258,8 +1258,6 @@ xfs_buf_ioapply_map(
        int             size;
        int             offset;
 
-       total_nr_pages = bp->b_page_count;
-
        /* skip the pages in the buffer before the start offset */
        page_index = 0;
        offset = *buf_offset;
index bd786a9ac2c38879cf6e94ad660cd1bda19873c5..eaf86f55b7f2156c351aa26fd0190871ef1772bd 100644 (file)
@@ -347,7 +347,7 @@ xfs_verifier_error(
 {
        struct xfs_mount *mp = bp->b_target->bt_mount;
 
-       xfs_alert(mp, "Metadata %s detected at %pF, %s block 0x%llx",
+       xfs_alert(mp, "Metadata %s detected at %pS, %s block 0x%llx",
                  bp->b_error == -EFSBADCRC ? "CRC error" : "corruption",
                  __return_address, bp->b_ops->name, bp->b_bn);
 
index ebdd0bd2b2616a7e9052b4da8378721b144dc0af..309e26c9dddb49715e81cb38b3aed00e33214463 100644 (file)
@@ -58,7 +58,7 @@ xfs_zero_range(
        xfs_off_t               count,
        bool                    *did_zero)
 {
-       return iomap_zero_range(VFS_I(ip), pos, count, NULL, &xfs_iomap_ops);
+       return iomap_zero_range(VFS_I(ip), pos, count, did_zero, &xfs_iomap_ops);
 }
 
 int
@@ -377,8 +377,6 @@ restart:
         */
        spin_lock(&ip->i_flags_lock);
        if (iocb->ki_pos > i_size_read(inode)) {
-               bool    zero = false;
-
                spin_unlock(&ip->i_flags_lock);
                if (!drained_dio) {
                        if (*iolock == XFS_IOLOCK_SHARED) {
@@ -399,7 +397,7 @@ restart:
                        drained_dio = true;
                        goto restart;
                }
-               error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), &zero);
+               error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), NULL);
                if (error)
                        return error;
        } else
@@ -436,7 +434,6 @@ xfs_dio_write_end_io(
        struct inode            *inode = file_inode(iocb->ki_filp);
        struct xfs_inode        *ip = XFS_I(inode);
        loff_t                  offset = iocb->ki_pos;
-       bool                    update_size = false;
        int                     error = 0;
 
        trace_xfs_end_io_direct_write(ip, offset, size);
@@ -447,6 +444,21 @@ xfs_dio_write_end_io(
        if (size <= 0)
                return size;
 
+       if (flags & IOMAP_DIO_COW) {
+               error = xfs_reflink_end_cow(ip, offset, size);
+               if (error)
+                       return error;
+       }
+
+       /*
+        * Unwritten conversion updates the in-core isize after extent
+        * conversion but before updating the on-disk size. Updating isize any
+        * earlier allows a racing dio read to find unwritten extents before
+        * they are converted.
+        */
+       if (flags & IOMAP_DIO_UNWRITTEN)
+               return xfs_iomap_write_unwritten(ip, offset, size, true);
+
        /*
         * We need to update the in-core inode size here so that we don't end up
         * with the on-disk inode size being outside the in-core inode size. We
@@ -461,20 +473,11 @@ xfs_dio_write_end_io(
        spin_lock(&ip->i_flags_lock);
        if (offset + size > i_size_read(inode)) {
                i_size_write(inode, offset + size);
-               update_size = true;
-       }
-       spin_unlock(&ip->i_flags_lock);
-
-       if (flags & IOMAP_DIO_COW) {
-               error = xfs_reflink_end_cow(ip, offset, size);
-               if (error)
-                       return error;
-       }
-
-       if (flags & IOMAP_DIO_UNWRITTEN)
-               error = xfs_iomap_write_unwritten(ip, offset, size);
-       else if (update_size)
+               spin_unlock(&ip->i_flags_lock);
                error = xfs_setfilesize(ip, offset, size);
+       } else {
+               spin_unlock(&ip->i_flags_lock);
+       }
 
        return error;
 }
index 5599dda4727af6736fa1ae15429456b2e5fc6a04..4ec5b7f4540137622856883ab5dafb73d95f89ab 100644 (file)
@@ -1624,10 +1624,12 @@ xfs_itruncate_extents(
                goto out;
 
        /*
-        * Clear the reflink flag if we truncated everything.
+        * Clear the reflink flag if there are no data fork blocks and
+        * there are no extents staged in the cow fork.
         */
-       if (ip->i_d.di_nblocks == 0 && xfs_is_reflink_inode(ip)) {
-               ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
+       if (xfs_is_reflink_inode(ip) && ip->i_cnextents == 0) {
+               if (ip->i_d.di_nblocks == 0)
+                       ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
                xfs_inode_clear_cowblocks_tag(ip);
        }
 
index 6d0f74ec31e89c35769b55f3402003c2548ae980..a705f34b58fad089659a019dcdd1caecffd01aa3 100644 (file)
@@ -745,7 +745,7 @@ xfs_iflush_done(
                 */
                iip = INODE_ITEM(blip);
                if ((iip->ili_logged && blip->li_lsn == iip->ili_flush_lsn) ||
-                   lip->li_flags & XFS_LI_FAILED)
+                   (blip->li_flags & XFS_LI_FAILED))
                        need_ail++;
 
                blip = next;
index 5049e8ab6e302e05b4c0d66fcf3eaa1ba9e2721b..aa75389be8cfa81d06695f80701c2093b65289b0 100644 (file)
@@ -1088,6 +1088,7 @@ xfs_ioctl_setattr_dax_invalidate(
        int                     *join_flags)
 {
        struct inode            *inode = VFS_I(ip);
+       struct super_block      *sb = inode->i_sb;
        int                     error;
 
        *join_flags = 0;
@@ -1100,7 +1101,7 @@ xfs_ioctl_setattr_dax_invalidate(
        if (fa->fsx_xflags & FS_XFLAG_DAX) {
                if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
                        return -EINVAL;
-               if (ip->i_mount->m_sb.sb_blocksize != PAGE_SIZE)
+               if (bdev_dax_supported(sb, sb->s_blocksize) < 0)
                        return -EINVAL;
        }
 
index a1909bc064e9e70c90ef6ced3017935951aefc2e..f179bdf1644dc346b2f7f064543eca0c3f808c6a 100644 (file)
@@ -829,7 +829,8 @@ int
 xfs_iomap_write_unwritten(
        xfs_inode_t     *ip,
        xfs_off_t       offset,
-       xfs_off_t       count)
+       xfs_off_t       count,
+       bool            update_isize)
 {
        xfs_mount_t     *mp = ip->i_mount;
        xfs_fileoff_t   offset_fsb;
@@ -840,6 +841,7 @@ xfs_iomap_write_unwritten(
        xfs_trans_t     *tp;
        xfs_bmbt_irec_t imap;
        struct xfs_defer_ops dfops;
+       struct inode    *inode = VFS_I(ip);
        xfs_fsize_t     i_size;
        uint            resblks;
        int             error;
@@ -899,7 +901,8 @@ xfs_iomap_write_unwritten(
                i_size = XFS_FSB_TO_B(mp, offset_fsb + count_fsb);
                if (i_size > offset + count)
                        i_size = offset + count;
-
+               if (update_isize && i_size > i_size_read(inode))
+                       i_size_write(inode, i_size);
                i_size = xfs_new_eof(ip, i_size);
                if (i_size) {
                        ip->i_d.di_size = i_size;
index 00db3ecea0840c2587f6c0de2f2828bcaaab6fbe..ee535065c5d0e3795158e9cf1ce7dafad5f3a729 100644 (file)
@@ -27,7 +27,7 @@ int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
                        struct xfs_bmbt_irec *, int);
 int xfs_iomap_write_allocate(struct xfs_inode *, int, xfs_off_t,
                        struct xfs_bmbt_irec *);
-int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t);
+int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t, bool);
 
 void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *,
                struct xfs_bmbt_irec *);
index 2f2dc3c09ad008a75fa0ffba6fd5d7aed392c162..4246876df7b759cdd63ddd43b5eb4612af0b0c93 100644 (file)
@@ -274,7 +274,7 @@ xfs_fs_commit_blocks(
                                        (end - 1) >> PAGE_SHIFT);
                WARN_ON_ONCE(error);
 
-               error = xfs_iomap_write_unwritten(ip, start, length);
+               error = xfs_iomap_write_unwritten(ip, start, length, false);
                if (error)
                        goto out_drop_iolock;
        }
index c996f4ae4a5f293199ede0d0137329cc0919418b..584cf2d573babe6b8331b856e617c4e6f08b5a53 100644 (file)
@@ -1654,6 +1654,16 @@ xfs_fs_fill_super(
                "DAX and reflink have not been tested together!");
        }
 
+       if (mp->m_flags & XFS_MOUNT_DISCARD) {
+               struct request_queue *q = bdev_get_queue(sb->s_bdev);
+
+               if (!blk_queue_discard(q)) {
+                       xfs_warn(mp, "mounting with \"discard\" option, but "
+                                       "the device does not support discard");
+                       mp->m_flags &= ~XFS_MOUNT_DISCARD;
+               }
+       }
+
        if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
                if (mp->m_sb.sb_rblocks) {
                        xfs_alert(mp,
index dedf9d789166184fbe859faa12a9415d55804dc8..fa1505292f6cda4c4b2434d264d4116bcefe640c 100644 (file)
@@ -399,17 +399,12 @@ extern const struct fwnode_operations acpi_device_fwnode_ops;
 extern const struct fwnode_operations acpi_data_fwnode_ops;
 extern const struct fwnode_operations acpi_static_fwnode_ops;
 
+bool is_acpi_device_node(const struct fwnode_handle *fwnode);
+bool is_acpi_data_node(const struct fwnode_handle *fwnode);
+
 static inline bool is_acpi_node(const struct fwnode_handle *fwnode)
 {
-       return !IS_ERR_OR_NULL(fwnode) &&
-               (fwnode->ops == &acpi_device_fwnode_ops
-                || fwnode->ops == &acpi_data_fwnode_ops);
-}
-
-static inline bool is_acpi_device_node(const struct fwnode_handle *fwnode)
-{
-       return !IS_ERR_OR_NULL(fwnode) &&
-               fwnode->ops == &acpi_device_fwnode_ops;
+       return (is_acpi_device_node(fwnode) || is_acpi_data_node(fwnode));
 }
 
 #define to_acpi_device_node(__fwnode)                                  \
@@ -422,11 +417,6 @@ static inline bool is_acpi_device_node(const struct fwnode_handle *fwnode)
                        NULL;                                           \
        })
 
-static inline bool is_acpi_data_node(const struct fwnode_handle *fwnode)
-{
-       return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
-}
-
 #define to_acpi_data_node(__fwnode)                                    \
        ({                                                              \
                typeof(__fwnode) __to_acpi_data_node_fwnode = __fwnode; \
index 74d4d4e8e3db9f173611dc169a20955a7c89dc45..cb708eb8accc59d3dafee57c7c696647e80be471 100644 (file)
@@ -314,11 +314,7 @@ void audit_core_dumps(long signr);
 
 static inline void audit_seccomp(unsigned long syscall, long signr, int code)
 {
-       if (!audit_enabled)
-               return;
-
-       /* Force a record to be reported if a signal was delivered. */
-       if (signr || unlikely(!audit_dummy_context()))
+       if (audit_enabled && unlikely(!audit_dummy_context()))
                __audit_seccomp(syscall, signr, code);
 }
 
index 460294bb0fa52560b44e4764ce34cf7bce9cd2ce..02fa42d24b52f5632500e2dd530a3b16be1f38d8 100644 (file)
@@ -551,6 +551,7 @@ struct request_queue {
        int                     node;
 #ifdef CONFIG_BLK_DEV_IO_TRACE
        struct blk_trace        *blk_trace;
+       struct mutex            blk_trace_mutex;
 #endif
        /*
         * for flush operations
index f24bfb2b9a2dcca0ac61034e86fe3bc489da7947..6d508767e14455d52470fe806f5f923637561edc 100644 (file)
@@ -3,8 +3,27 @@
 
 #include <linux/types.h>
 
+/*
+ * CPU-up                      CPU-down
+ *
+ * BP          AP              BP              AP
+ *
+ * OFFLINE                     OFFLINE
+ *   |                           ^
+ *   v                           |
+ * BRINGUP_CPU->AP_OFFLINE     BRINGUP_CPU  <- AP_IDLE_DEAD (idle thread/play_dead)
+ *               |                             AP_OFFLINE
+ *               v (IRQ-off)     ,---------------^
+ *             AP_ONLNE          | (stop_machine)
+ *               |             TEARDOWN_CPU <- AP_ONLINE_IDLE
+ *               |                               ^
+ *               v                               |
+ *              AP_ACTIVE                      AP_ACTIVE
+ */
+
 enum cpuhp_state {
-       CPUHP_OFFLINE,
+       CPUHP_INVALID = -1,
+       CPUHP_OFFLINE = 0,
        CPUHP_CREATE_THREADS,
        CPUHP_PERF_PREPARE,
        CPUHP_PERF_X86_PREPARE,
index c6f27207dbe87392502dba2082e73617bd6d02ac..1d2607923a24d8aaf014cc172e90b0caeaa1d15f 100644 (file)
@@ -838,7 +838,7 @@ struct dev_links_info {
  * @driver_data: Private pointer for driver specific info.
  * @links:     Links to suppliers and consumers of this device.
  * @power:     For device power management.
- *             See Documentation/power/admin-guide/devices.rst for details.
+ *             See Documentation/driver-api/pm/devices.rst for details.
  * @pm_domain: Provide callbacks that are executed during system suspend,
  *             hibernation, system resume and during runtime PM transitions
  *             along with subsystem-level and driver-level callbacks.
index a65e3b24fb1838e43cffc24e2ecdc8a8f92eba12..fb5e23c7ed98894e2833f2143e35cd5f703a9b09 100644 (file)
@@ -529,6 +529,7 @@ int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code,
 
 int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file);
 int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
+int input_ff_flush(struct input_dev *dev, struct file *file);
 
 int input_ff_create_memless(struct input_dev *dev, void *data,
                int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
index a7f2ac689d2917e2902e78604e8b6b33df1ee333..41b8c575785916f7691a7686a5c5d4e7d99003fa 100644 (file)
@@ -167,11 +167,11 @@ struct iommu_resv_region {
  * @map: map a physically contiguous memory region to an iommu domain
  * @unmap: unmap a physically contiguous memory region from an iommu domain
  * @map_sg: map a scatter-gather list of physically contiguous memory chunks
+ *          to an iommu domain
  * @flush_tlb_all: Synchronously flush all hardware TLBs for this domain
  * @tlb_range_add: Add a given iova range to the flush queue for this domain
  * @tlb_sync: Flush all queued ranges from the hardware TLBs and empty flush
  *            queue
- * to an iommu domain
  * @iova_to_phys: translate iova to physical address
  * @add_device: add device to iommu grouping
  * @remove_device: remove device from iommu grouping
index b99a784635ff5801c20fce3a187a12cc4358660a..d4728bf6a537c802073592fcd6e440ccc628509e 100644 (file)
@@ -783,10 +783,7 @@ static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
 static inline
 struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d)
 {
-       if (!cpumask_empty(d->common->effective_affinity))
-               return d->common->effective_affinity;
-
-       return d->common->affinity;
+       return d->common->effective_affinity;
 }
 static inline void irq_data_update_effective_affinity(struct irq_data *d,
                                                      const struct cpumask *m)
index 044114185120633b8ca5c678b22570c3c2f8e264..e315e16b6ff8a0aaade2552ee404d35e27da5570 100644 (file)
@@ -187,6 +187,7 @@ struct key {
 #define KEY_FLAG_BUILTIN       8       /* set if key is built in to the kernel */
 #define KEY_FLAG_ROOT_CAN_INVAL        9       /* set if key can be invalidated by root without permission */
 #define KEY_FLAG_KEEP          10      /* set if key should not be removed */
+#define KEY_FLAG_UID_KEYRING   11      /* set if key is a user or user session keyring */
 
        /* the key type and key description string
         * - the desc is used to match a key against search criteria
@@ -243,6 +244,7 @@ extern struct key *key_alloc(struct key_type *type,
 #define KEY_ALLOC_NOT_IN_QUOTA         0x0002  /* not in quota */
 #define KEY_ALLOC_BUILT_IN             0x0004  /* Key is built into kernel */
 #define KEY_ALLOC_BYPASS_RESTRICTION   0x0008  /* Override the check on restricted keyrings */
+#define KEY_ALLOC_UID_KEYRING          0x0010  /* allocating a user or user session keyring */
 
 extern void key_revoke(struct key *key);
 extern void key_invalidate(struct key *key);
index 9c5cb44808063d8531cfc800beb1e3f5e0e440a4..a726f96010d59d9d99eda4e6d5d5ea9776ebdd18 100644 (file)
@@ -346,11 +346,6 @@ struct nvme_fc_remote_port {
  *       indicating an FC transport Aborted status.
  *       Entrypoint is Mandatory.
  *
- * @defer_rcv:  Called by the transport to signal the LLLD that it has
- *       begun processing of a previously received NVME CMD IU. The LLDD
- *       is now free to re-use the rcv buffer associated with the
- *       nvmefc_tgt_fcp_req.
- *
  * @max_hw_queues:  indicates the maximum number of hw queues the LLDD
  *       supports for cpu affinitization.
  *       Value is Mandatory. Must be at least 1.
@@ -806,11 +801,19 @@ struct nvmet_fc_target_port {
  *       outstanding operation (if there was one) to complete, then will
  *       call the fcp_req_release() callback to return the command's
  *       exchange context back to the LLDD.
+ *       Entrypoint is Mandatory.
  *
  * @fcp_req_release:  Called by the transport to return a nvmefc_tgt_fcp_req
  *       to the LLDD after all operations on the fcp operation are complete.
  *       This may be due to the command completing or upon completion of
  *       abort cleanup.
+ *       Entrypoint is Mandatory.
+ *
+ * @defer_rcv:  Called by the transport to signal the LLLD that it has
+ *       begun processing of a previously received NVME CMD IU. The LLDD
+ *       is now free to re-use the rcv buffer associated with the
+ *       nvmefc_tgt_fcp_req.
+ *       Entrypoint is Optional.
  *
  * @max_hw_queues:  indicates the maximum number of hw queues the LLDD
  *       supports for cpu affinitization.
index 87723c86f136f0e48c64a4c39fa9f0dcb3ad979d..9310ce77d8e1f3b324e8c046ba414084530826e9 100644 (file)
@@ -471,12 +471,14 @@ enum nvme_opcode {
  *
  * @NVME_SGL_FMT_ADDRESS:     absolute address of the data block
  * @NVME_SGL_FMT_OFFSET:      relative offset of the in-capsule data block
+ * @NVME_SGL_FMT_TRANSPORT_A: transport defined format, value 0xA
  * @NVME_SGL_FMT_INVALIDATE:  RDMA transport specific remote invalidation
  *                            request subtype
  */
 enum {
        NVME_SGL_FMT_ADDRESS            = 0x00,
        NVME_SGL_FMT_OFFSET             = 0x01,
+       NVME_SGL_FMT_TRANSPORT_A        = 0x0A,
        NVME_SGL_FMT_INVALIDATE         = 0x0f,
 };
 
@@ -490,12 +492,16 @@ enum {
  *
  * For struct nvme_keyed_sgl_desc:
  *   @NVME_KEY_SGL_FMT_DATA_DESC:      keyed data block descriptor
+ *
+ * Transport-specific SGL types:
+ *   @NVME_TRANSPORT_SGL_DATA_DESC:    Transport SGL data dlock descriptor
  */
 enum {
        NVME_SGL_FMT_DATA_DESC          = 0x00,
        NVME_SGL_FMT_SEG_DESC           = 0x02,
        NVME_SGL_FMT_LAST_SEG_DESC      = 0x03,
        NVME_KEY_SGL_FMT_DATA_DESC      = 0x04,
+       NVME_TRANSPORT_SGL_DATA_DESC    = 0x05,
 };
 
 struct nvme_sgl_desc {
@@ -1127,19 +1133,6 @@ enum {
        NVME_SC_UNWRITTEN_BLOCK         = 0x287,
 
        NVME_SC_DNR                     = 0x4000,
-
-
-       /*
-        * FC Transport-specific error status values for NVME commands
-        *
-        * Transport-specific status code values must be in the range 0xB0..0xBF
-        */
-
-       /* Generic FC failure - catchall */
-       NVME_SC_FC_TRANSPORT_ERROR      = 0x00B0,
-
-       /* I/O failure due to FC ABTS'd */
-       NVME_SC_FC_TRANSPORT_ABORTED    = 0x00B1,
 };
 
 struct nvme_completion {
index e0d1946270f38e5238ddf0a3bb25cf03c3f3ebe4..fb908e598348097712981459b969f45fed4a8d09 100644 (file)
@@ -57,7 +57,14 @@ extern const struct of_device_id of_default_bus_match_table[];
 extern struct platform_device *of_device_alloc(struct device_node *np,
                                         const char *bus_id,
                                         struct device *parent);
+#ifdef CONFIG_OF
 extern struct platform_device *of_find_device_by_node(struct device_node *np);
+#else
+static inline struct platform_device *of_find_device_by_node(struct device_node *np)
+{
+       return NULL;
+}
+#endif
 
 /* Platform devices and busses creation */
 extern struct platform_device *of_platform_device_create(struct device_node *np,
index f68c58a93dd045b9b58de9882088621253ec7758..f4f8ee5a7362e982c0084d619c8ed1996a38f770 100644 (file)
@@ -1685,6 +1685,8 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
 
 #define dev_is_pci(d) (false)
 #define dev_is_pf(d) (false)
+static inline bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)
+{ return false; }
 #endif /* CONFIG_PCI */
 
 /* Include architecture-dependent settings and functions */
index 92fb8dd5a9e4884bfde2225bb0c6d933ed13c660..26a7df4e558c249c40b979ead73425989f8e8c7f 100644 (file)
@@ -65,25 +65,23 @@ struct task_group;
  */
 
 /* Used in tsk->state: */
-#define TASK_RUNNING                   0
-#define TASK_INTERRUPTIBLE             1
-#define TASK_UNINTERRUPTIBLE           2
-#define __TASK_STOPPED                 4
-#define __TASK_TRACED                  8
+#define TASK_RUNNING                   0x0000
+#define TASK_INTERRUPTIBLE             0x0001
+#define TASK_UNINTERRUPTIBLE           0x0002
+#define __TASK_STOPPED                 0x0004
+#define __TASK_TRACED                  0x0008
 /* Used in tsk->exit_state: */
-#define EXIT_DEAD                      16
-#define EXIT_ZOMBIE                    32
+#define EXIT_DEAD                      0x0010
+#define EXIT_ZOMBIE                    0x0020
 #define EXIT_TRACE                     (EXIT_ZOMBIE | EXIT_DEAD)
 /* Used in tsk->state again: */
-#define TASK_DEAD                      64
-#define TASK_WAKEKILL                  128
-#define TASK_WAKING                    256
-#define TASK_PARKED                    512
-#define TASK_NOLOAD                    1024
-#define TASK_NEW                       2048
-#define TASK_STATE_MAX                 4096
-
-#define TASK_STATE_TO_CHAR_STR         "RSDTtXZxKWPNn"
+#define TASK_PARKED                    0x0040
+#define TASK_DEAD                      0x0080
+#define TASK_WAKEKILL                  0x0100
+#define TASK_WAKING                    0x0200
+#define TASK_NOLOAD                    0x0400
+#define TASK_NEW                       0x0800
+#define TASK_STATE_MAX                 0x1000
 
 /* Convenience macros for the sake of set_current_state: */
 #define TASK_KILLABLE                  (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
@@ -99,7 +97,8 @@ struct task_group;
 /* get_task_state(): */
 #define TASK_REPORT                    (TASK_RUNNING | TASK_INTERRUPTIBLE | \
                                         TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \
-                                        __TASK_TRACED | EXIT_ZOMBIE | EXIT_DEAD)
+                                        __TASK_TRACED | EXIT_DEAD | EXIT_ZOMBIE | \
+                                        TASK_PARKED)
 
 #define task_is_traced(task)           ((task->state & __TASK_TRACED) != 0)
 
@@ -1243,17 +1242,34 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk)
        return task_pgrp_nr_ns(tsk, &init_pid_ns);
 }
 
-static inline char task_state_to_char(struct task_struct *task)
+#define TASK_REPORT_IDLE       (TASK_REPORT + 1)
+#define TASK_REPORT_MAX                (TASK_REPORT_IDLE << 1)
+
+static inline unsigned int __get_task_state(struct task_struct *tsk)
+{
+       unsigned int tsk_state = READ_ONCE(tsk->state);
+       unsigned int state = (tsk_state | tsk->exit_state) & TASK_REPORT;
+
+       BUILD_BUG_ON_NOT_POWER_OF_2(TASK_REPORT_MAX);
+
+       if (tsk_state == TASK_IDLE)
+               state = TASK_REPORT_IDLE;
+
+       return fls(state);
+}
+
+static inline char __task_state_to_char(unsigned int state)
 {
-       const char stat_nam[] = TASK_STATE_TO_CHAR_STR;
-       unsigned long state = task->state;
+       static const char state_char[] = "RSDTtXZPI";
 
-       state = state ? __ffs(state) + 1 : 0;
+       BUILD_BUG_ON(1 + ilog2(TASK_REPORT_MAX) != sizeof(state_char) - 1);
 
-       /* Make sure the string lines up properly with the number of task states: */
-       BUILD_BUG_ON(sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1);
+       return state_char[state];
+}
 
-       return state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?';
+static inline char task_state_to_char(struct task_struct *tsk)
+{
+       return __task_state_to_char(__get_task_state(tsk));
 }
 
 /**
index ecc296c137cd2e3e926821dc357e5c00563bedd4..c8bef436b61df236f5b600622ef54da883e1d7a7 100644 (file)
@@ -3,7 +3,8 @@
 
 #include <uapi/linux/seccomp.h>
 
-#define SECCOMP_FILTER_FLAG_MASK       (SECCOMP_FILTER_FLAG_TSYNC)
+#define SECCOMP_FILTER_FLAG_MASK       (SECCOMP_FILTER_FLAG_TSYNC | \
+                                        SECCOMP_FILTER_FLAG_LOG)
 
 #ifdef CONFIG_SECCOMP
 
index 95606a2d556fd299f487240078922abf408e435d..a78186d826d7963d99f168908f4a5ec386de04e1 100644 (file)
@@ -221,21 +221,25 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
        }                                                               \
        static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
-#ifdef TIF_FSCHECK
 /*
  * Called before coming back to user-mode. Returning to user-mode with an
  * address limit different than USER_DS can allow to overwrite kernel memory.
  */
 static inline void addr_limit_user_check(void)
 {
-
+#ifdef TIF_FSCHECK
        if (!test_thread_flag(TIF_FSCHECK))
                return;
+#endif
 
-       BUG_ON(!segment_eq(get_fs(), USER_DS));
+       if (CHECK_DATA_CORRUPTION(!segment_eq(get_fs(), USER_DS),
+                                 "Invalid address limit on user-mode return"))
+               force_sig(SIGKILL, current);
+
+#ifdef TIF_FSCHECK
        clear_thread_flag(TIF_FSCHECK);
-}
 #endif
+}
 
 asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
                               qid_t id, void __user *addr);
index e6789b8757d5021439c332751e52726bde83bec1..6383c528b1484fed5731b3074e1d1accf414ff31 100644 (file)
@@ -168,6 +168,20 @@ static inline void init_timer_on_stack_key(struct timer_list *timer,
 #define setup_pinned_deferrable_timer_on_stack(timer, fn, data)                \
        __setup_timer_on_stack((timer), (fn), (data), TIMER_DEFERRABLE | TIMER_PINNED)
 
+#define TIMER_DATA_TYPE                unsigned long
+#define TIMER_FUNC_TYPE                void (*)(TIMER_DATA_TYPE)
+
+static inline void timer_setup(struct timer_list *timer,
+                              void (*callback)(struct timer_list *),
+                              unsigned int flags)
+{
+       __setup_timer(timer, (TIMER_FUNC_TYPE)callback,
+                     (TIMER_DATA_TYPE)timer, flags);
+}
+
+#define from_timer(var, callback_timer, timer_fieldname) \
+       container_of(callback_timer, typeof(*var), timer_fieldname)
+
 /**
  * timer_pending - is a timer pending?
  * @timer: the timer in question
index 7f11050746aecb21dc6f12e9b9d58e6d05d7d9d9..2e0f22298fe952748edbc68b35d5e3435335e53a 100644 (file)
@@ -272,6 +272,7 @@ struct trace_event_call {
        int                             perf_refcount;
        struct hlist_head __percpu      *perf_events;
        struct bpf_prog                 *prog;
+       struct perf_event               *bpf_prog_owner;
 
        int     (*perf_perm)(struct trace_event_call *,
                             struct perf_event *);
index 93568bd0a3520bb7402f04d90cf04ac99c81cfbe..06a6765da074449e6f1fe42ee05e711e898ad372 100644 (file)
@@ -271,7 +271,7 @@ static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
 static inline struct dst_entry *dst_clone(struct dst_entry *dst)
 {
        if (dst)
-               atomic_inc(&dst->__refcnt);
+               dst_hold(dst);
        return dst;
 }
 
@@ -311,21 +311,6 @@ static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb
        __skb_dst_copy(nskb, oskb->_skb_refdst);
 }
 
-/**
- * skb_dst_force - makes sure skb dst is refcounted
- * @skb: buffer
- *
- * If dst is not yet refcounted, let's do it
- */
-static inline void skb_dst_force(struct sk_buff *skb)
-{
-       if (skb_dst_is_noref(skb)) {
-               WARN_ON(!rcu_read_lock_held());
-               skb->_skb_refdst &= ~SKB_DST_NOREF;
-               dst_clone(skb_dst(skb));
-       }
-}
-
 /**
  * dst_hold_safe - Take a reference on a dst if possible
  * @dst: pointer to dst entry
@@ -339,16 +324,17 @@ static inline bool dst_hold_safe(struct dst_entry *dst)
 }
 
 /**
- * skb_dst_force_safe - makes sure skb dst is refcounted
+ * skb_dst_force - makes sure skb dst is refcounted
  * @skb: buffer
  *
  * If dst is not yet refcounted and not destroyed, grab a ref on it.
  */
-static inline void skb_dst_force_safe(struct sk_buff *skb)
+static inline void skb_dst_force(struct sk_buff *skb)
 {
        if (skb_dst_is_noref(skb)) {
                struct dst_entry *dst = skb_dst(skb);
 
+               WARN_ON(!rcu_read_lock_held());
                if (!dst_hold_safe(dst))
                        dst = NULL;
 
index 1b09a9368c68d46f0c5ee8ce3cefe566000c1ec1..57dfc6850d378e4b96f13b140eef554d66c24cdf 100644 (file)
@@ -190,7 +190,7 @@ static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
        rcu_read_lock();
        err = ip_route_input_noref(skb, dst, src, tos, devin);
        if (!err) {
-               skb_dst_force_safe(skb);
+               skb_dst_force(skb);
                if (!skb_dst(skb))
                        err = -EINVAL;
        }
index 03a362568357acc7278a318423dd3873103f90ca..a6b9a8d1a6df3f72df8f1aac0f577257fa6452d0 100644 (file)
@@ -856,7 +856,7 @@ void sk_stream_write_space(struct sock *sk);
 static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
        /* dont let skb dst not refcounted, we are going to leave rcu lock */
-       skb_dst_force_safe(skb);
+       skb_dst_force(skb);
 
        if (!sk->sk_backlog.tail)
                sk->sk_backlog.head = skb;
index b510f284427aabc1f508d24d29d0f812e5e0aa61..3bc910a9bfc6f39ed0c8a4b451cf80e579de66ad 100644 (file)
@@ -544,7 +544,6 @@ u32 tcp_tso_autosize(const struct sock *sk, unsigned int mss_now,
                     int min_tso_segs);
 void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
                               int nonagle);
-bool tcp_may_send_now(struct sock *sk);
 int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs);
 int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs);
 void tcp_retransmit_timer(struct sock *sk);
index bdb1279a415b39f0597a02a6eb36aa6bd5e7ded5..e8608b2dc844fb27c0e7e5ceb359fe357ecf6553 100644 (file)
@@ -285,7 +285,7 @@ enum ib_tm_cap_flags {
        IB_TM_CAP_RC                = 1 << 0,
 };
 
-struct ib_xrq_caps {
+struct ib_tm_caps {
        /* Max size of RNDV header */
        u32 max_rndv_hdr_size;
        /* Max number of entries in tag matching list */
@@ -358,7 +358,7 @@ struct ib_device_attr {
        struct ib_rss_caps      rss_caps;
        u32                     max_wq_type_rq;
        u32                     raw_packet_caps; /* Use ib_raw_packet_caps enum */
-       struct ib_xrq_caps      xrq_caps;
+       struct ib_tm_caps       tm_caps;
 };
 
 enum ib_mtu {
@@ -1739,7 +1739,7 @@ struct ib_mr {
        u32                lkey;
        u32                rkey;
        u64                iova;
-       u32                length;
+       u64                length;
        unsigned int       page_size;
        bool               need_inval;
        union {
index ae1409ffe99a00817f02a2cc51771840712fc1c3..3c8b7f6256701b6c6eeb05b2bae9387fa95df692 100644 (file)
@@ -114,7 +114,10 @@ static inline long __trace_sched_switch_state(bool preempt, struct task_struct *
         * Preemption ignores task state, therefore preempted tasks are always
         * RUNNING (we will not have dequeued if state != RUNNING).
         */
-       return preempt ? TASK_RUNNING | TASK_STATE_MAX : p->state;
+       if (preempt)
+               return TASK_STATE_MAX;
+
+       return __get_task_state(p);
 }
 #endif /* CREATE_TRACE_POINTS */
 
@@ -152,12 +155,14 @@ TRACE_EVENT(sched_switch,
 
        TP_printk("prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s%s ==> next_comm=%s next_pid=%d next_prio=%d",
                __entry->prev_comm, __entry->prev_pid, __entry->prev_prio,
-               __entry->prev_state & (TASK_STATE_MAX-1) ?
-                 __print_flags(__entry->prev_state & (TASK_STATE_MAX-1), "|",
-                               { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" },
-                               { 16, "Z" }, { 32, "X" }, { 64, "x" },
-                               { 128, "K" }, { 256, "W" }, { 512, "P" },
-                               { 1024, "N" }) : "R",
+
+               (__entry->prev_state & (TASK_REPORT_MAX - 1)) ?
+                 __print_flags(__entry->prev_state & (TASK_REPORT_MAX - 1), "|",
+                               { 0x01, "S" }, { 0x02, "D" }, { 0x04, "T" },
+                               { 0x08, "t" }, { 0x10, "X" }, { 0x20, "Z" },
+                               { 0x40, "P" }, { 0x80, "I" }) :
+                 "R",
+
                __entry->prev_state & TASK_STATE_MAX ? "+" : "",
                __entry->next_comm, __entry->next_pid, __entry->next_prio)
 );
index 9c041dae8e2ca70ee8bf72d734db67c6118096d1..5bd1b1de4ea0670caf18ffb28e36ba9e35592605 100644 (file)
@@ -1753,6 +1753,8 @@ enum ethtool_reset_flags {
  *     %ethtool_link_mode_bit_indices for the link modes, and other
  *     link features that the link partner advertised through
  *     autonegotiation; 0 if unknown or not applicable.  Read-only.
+ * @transceiver: Used to distinguish different possible PHY types,
+ *     reported consistently by PHYLIB.  Read-only.
  *
  * If autonegotiation is disabled, the speed and @duplex represent the
  * fixed link mode and are writable if the driver supports multiple
@@ -1804,7 +1806,9 @@ struct ethtool_link_settings {
        __u8    eth_tp_mdix;
        __u8    eth_tp_mdix_ctrl;
        __s8    link_mode_masks_nwords;
-       __u32   reserved[8];
+       __u8    transceiver;
+       __u8    reserved1[3];
+       __u32   reserved[7];
        __u32   link_mode_masks[0];
        /* layout of link_mode_masks fields:
         * __u32 map_supported[link_mode_masks_nwords];
index 7b4567bacfc206a02d4e8a680cf8ecd81b87a84a..26283fefdf5fd5f86719fb954c02ae3b2492cd30 100644 (file)
 #ifndef KFD_IOCTL_H_INCLUDED
 #define KFD_IOCTL_H_INCLUDED
 
-#include <linux/types.h>
+#include <drm/drm.h>
 #include <linux/ioctl.h>
 
 #define KFD_IOCTL_MAJOR_VERSION 1
 #define KFD_IOCTL_MINOR_VERSION 1
 
 struct kfd_ioctl_get_version_args {
-       uint32_t major_version; /* from KFD */
-       uint32_t minor_version; /* from KFD */
+       __u32 major_version;    /* from KFD */
+       __u32 minor_version;    /* from KFD */
 };
 
 /* For kfd_ioctl_create_queue_args.queue_type. */
@@ -43,36 +43,36 @@ struct kfd_ioctl_get_version_args {
 #define KFD_MAX_QUEUE_PRIORITY         15
 
 struct kfd_ioctl_create_queue_args {
-       uint64_t ring_base_address;     /* to KFD */
-       uint64_t write_pointer_address; /* from KFD */
-       uint64_t read_pointer_address;  /* from KFD */
-       uint64_t doorbell_offset;       /* from KFD */
-
-       uint32_t ring_size;             /* to KFD */
-       uint32_t gpu_id;                /* to KFD */
-       uint32_t queue_type;            /* to KFD */
-       uint32_t queue_percentage;      /* to KFD */
-       uint32_t queue_priority;        /* to KFD */
-       uint32_t queue_id;              /* from KFD */
-
-       uint64_t eop_buffer_address;    /* to KFD */
-       uint64_t eop_buffer_size;       /* to KFD */
-       uint64_t ctx_save_restore_address; /* to KFD */
-       uint64_t ctx_save_restore_size; /* to KFD */
+       __u64 ring_base_address;        /* to KFD */
+       __u64 write_pointer_address;    /* from KFD */
+       __u64 read_pointer_address;     /* from KFD */
+       __u64 doorbell_offset;  /* from KFD */
+
+       __u32 ring_size;                /* to KFD */
+       __u32 gpu_id;           /* to KFD */
+       __u32 queue_type;               /* to KFD */
+       __u32 queue_percentage; /* to KFD */
+       __u32 queue_priority;   /* to KFD */
+       __u32 queue_id;         /* from KFD */
+
+       __u64 eop_buffer_address;       /* to KFD */
+       __u64 eop_buffer_size;  /* to KFD */
+       __u64 ctx_save_restore_address; /* to KFD */
+       __u64 ctx_save_restore_size;    /* to KFD */
 };
 
 struct kfd_ioctl_destroy_queue_args {
-       uint32_t queue_id;              /* to KFD */
-       uint32_t pad;
+       __u32 queue_id;         /* to KFD */
+       __u32 pad;
 };
 
 struct kfd_ioctl_update_queue_args {
-       uint64_t ring_base_address;     /* to KFD */
+       __u64 ring_base_address;        /* to KFD */
 
-       uint32_t queue_id;              /* to KFD */
-       uint32_t ring_size;             /* to KFD */
-       uint32_t queue_percentage;      /* to KFD */
-       uint32_t queue_priority;        /* to KFD */
+       __u32 queue_id;         /* to KFD */
+       __u32 ring_size;                /* to KFD */
+       __u32 queue_percentage; /* to KFD */
+       __u32 queue_priority;   /* to KFD */
 };
 
 /* For kfd_ioctl_set_memory_policy_args.default_policy and alternate_policy */
@@ -80,13 +80,13 @@ struct kfd_ioctl_update_queue_args {
 #define KFD_IOC_CACHE_POLICY_NONCOHERENT 1
 
 struct kfd_ioctl_set_memory_policy_args {
-       uint64_t alternate_aperture_base;       /* to KFD */
-       uint64_t alternate_aperture_size;       /* to KFD */
+       __u64 alternate_aperture_base;  /* to KFD */
+       __u64 alternate_aperture_size;  /* to KFD */
 
-       uint32_t gpu_id;                        /* to KFD */
-       uint32_t default_policy;                /* to KFD */
-       uint32_t alternate_policy;              /* to KFD */
-       uint32_t pad;
+       __u32 gpu_id;                   /* to KFD */
+       __u32 default_policy;           /* to KFD */
+       __u32 alternate_policy;         /* to KFD */
+       __u32 pad;
 };
 
 /*
@@ -97,26 +97,26 @@ struct kfd_ioctl_set_memory_policy_args {
  */
 
 struct kfd_ioctl_get_clock_counters_args {
-       uint64_t gpu_clock_counter;     /* from KFD */
-       uint64_t cpu_clock_counter;     /* from KFD */
-       uint64_t system_clock_counter;  /* from KFD */
-       uint64_t system_clock_freq;     /* from KFD */
+       __u64 gpu_clock_counter;        /* from KFD */
+       __u64 cpu_clock_counter;        /* from KFD */
+       __u64 system_clock_counter;     /* from KFD */
+       __u64 system_clock_freq;        /* from KFD */
 
-       uint32_t gpu_id;                /* to KFD */
-       uint32_t pad;
+       __u32 gpu_id;           /* to KFD */
+       __u32 pad;
 };
 
 #define NUM_OF_SUPPORTED_GPUS 7
 
 struct kfd_process_device_apertures {
-       uint64_t lds_base;              /* from KFD */
-       uint64_t lds_limit;             /* from KFD */
-       uint64_t scratch_base;          /* from KFD */
-       uint64_t scratch_limit;         /* from KFD */
-       uint64_t gpuvm_base;            /* from KFD */
-       uint64_t gpuvm_limit;           /* from KFD */
-       uint32_t gpu_id;                /* from KFD */
-       uint32_t pad;
+       __u64 lds_base;         /* from KFD */
+       __u64 lds_limit;                /* from KFD */
+       __u64 scratch_base;             /* from KFD */
+       __u64 scratch_limit;            /* from KFD */
+       __u64 gpuvm_base;               /* from KFD */
+       __u64 gpuvm_limit;              /* from KFD */
+       __u32 gpu_id;           /* from KFD */
+       __u32 pad;
 };
 
 struct kfd_ioctl_get_process_apertures_args {
@@ -124,8 +124,8 @@ struct kfd_ioctl_get_process_apertures_args {
                        process_apertures[NUM_OF_SUPPORTED_GPUS];/* from KFD */
 
        /* from KFD, should be in the range [1 - NUM_OF_SUPPORTED_GPUS] */
-       uint32_t num_of_nodes;
-       uint32_t pad;
+       __u32 num_of_nodes;
+       __u32 pad;
 };
 
 #define MAX_ALLOWED_NUM_POINTS    100
@@ -133,25 +133,25 @@ struct kfd_ioctl_get_process_apertures_args {
 #define MAX_ALLOWED_WAC_BUFF_SIZE  128
 
 struct kfd_ioctl_dbg_register_args {
-       uint32_t gpu_id;                /* to KFD */
-       uint32_t pad;
+       __u32 gpu_id;           /* to KFD */
+       __u32 pad;
 };
 
 struct kfd_ioctl_dbg_unregister_args {
-       uint32_t gpu_id;                /* to KFD */
-       uint32_t pad;
+       __u32 gpu_id;           /* to KFD */
+       __u32 pad;
 };
 
 struct kfd_ioctl_dbg_address_watch_args {
-       uint64_t content_ptr;           /* a pointer to the actual content */
-       uint32_t gpu_id;                /* to KFD */
-       uint32_t buf_size_in_bytes;     /*including gpu_id and buf_size */
+       __u64 content_ptr;              /* a pointer to the actual content */
+       __u32 gpu_id;           /* to KFD */
+       __u32 buf_size_in_bytes;        /*including gpu_id and buf_size */
 };
 
 struct kfd_ioctl_dbg_wave_control_args {
-       uint64_t content_ptr;           /* a pointer to the actual content */
-       uint32_t gpu_id;                /* to KFD */
-       uint32_t buf_size_in_bytes;     /*including gpu_id and buf_size */
+       __u64 content_ptr;              /* a pointer to the actual content */
+       __u32 gpu_id;           /* to KFD */
+       __u32 buf_size_in_bytes;        /*including gpu_id and buf_size */
 };
 
 /* Matching HSA_EVENTTYPE */
@@ -172,44 +172,44 @@ struct kfd_ioctl_dbg_wave_control_args {
 #define KFD_SIGNAL_EVENT_LIMIT                 256
 
 struct kfd_ioctl_create_event_args {
-       uint64_t event_page_offset;     /* from KFD */
-       uint32_t event_trigger_data;    /* from KFD - signal events only */
-       uint32_t event_type;            /* to KFD */
-       uint32_t auto_reset;            /* to KFD */
-       uint32_t node_id;               /* to KFD - only valid for certain
+       __u64 event_page_offset;        /* from KFD */
+       __u32 event_trigger_data;       /* from KFD - signal events only */
+       __u32 event_type;               /* to KFD */
+       __u32 auto_reset;               /* to KFD */
+       __u32 node_id;          /* to KFD - only valid for certain
                                                        event types */
-       uint32_t event_id;              /* from KFD */
-       uint32_t event_slot_index;      /* from KFD */
+       __u32 event_id;         /* from KFD */
+       __u32 event_slot_index; /* from KFD */
 };
 
 struct kfd_ioctl_destroy_event_args {
-       uint32_t event_id;              /* to KFD */
-       uint32_t pad;
+       __u32 event_id;         /* to KFD */
+       __u32 pad;
 };
 
 struct kfd_ioctl_set_event_args {
-       uint32_t event_id;              /* to KFD */
-       uint32_t pad;
+       __u32 event_id;         /* to KFD */
+       __u32 pad;
 };
 
 struct kfd_ioctl_reset_event_args {
-       uint32_t event_id;              /* to KFD */
-       uint32_t pad;
+       __u32 event_id;         /* to KFD */
+       __u32 pad;
 };
 
 struct kfd_memory_exception_failure {
-       uint32_t NotPresent;    /* Page not present or supervisor privilege */
-       uint32_t ReadOnly;      /* Write access to a read-only page */
-       uint32_t NoExecute;     /* Execute access to a page marked NX */
-       uint32_t pad;
+       __u32 NotPresent;       /* Page not present or supervisor privilege */
+       __u32 ReadOnly; /* Write access to a read-only page */
+       __u32 NoExecute;        /* Execute access to a page marked NX */
+       __u32 pad;
 };
 
 /* memory exception data*/
 struct kfd_hsa_memory_exception_data {
        struct kfd_memory_exception_failure failure;
-       uint64_t va;
-       uint32_t gpu_id;
-       uint32_t pad;
+       __u64 va;
+       __u32 gpu_id;
+       __u32 pad;
 };
 
 /* Event data*/
@@ -217,19 +217,19 @@ struct kfd_event_data {
        union {
                struct kfd_hsa_memory_exception_data memory_exception_data;
        };                              /* From KFD */
-       uint64_t kfd_event_data_ext;    /* pointer to an extension structure
+       __u64 kfd_event_data_ext;       /* pointer to an extension structure
                                           for future exception types */
-       uint32_t event_id;              /* to KFD */
-       uint32_t pad;
+       __u32 event_id;         /* to KFD */
+       __u32 pad;
 };
 
 struct kfd_ioctl_wait_events_args {
-       uint64_t events_ptr;            /* pointed to struct
+       __u64 events_ptr;               /* pointed to struct
                                           kfd_event_data array, to KFD */
-       uint32_t num_events;            /* to KFD */
-       uint32_t wait_for_all;          /* to KFD */
-       uint32_t timeout;               /* to KFD */
-       uint32_t wait_result;           /* from KFD */
+       __u32 num_events;               /* to KFD */
+       __u32 wait_for_all;             /* to KFD */
+       __u32 timeout;          /* to KFD */
+       __u32 wait_result;              /* from KFD */
 };
 
 struct kfd_ioctl_set_scratch_backing_va_args {
index 0f238a43ff1e7e5ebd8bd746a055fa910c10b51d..f6bc1dea32479f080de8f0d380b4cfaf2a547aae 100644 (file)
 #define SECCOMP_MODE_FILTER    2 /* uses user-supplied filter. */
 
 /* Valid operations for seccomp syscall. */
-#define SECCOMP_SET_MODE_STRICT        0
-#define SECCOMP_SET_MODE_FILTER        1
+#define SECCOMP_SET_MODE_STRICT                0
+#define SECCOMP_SET_MODE_FILTER                1
+#define SECCOMP_GET_ACTION_AVAIL       2
 
 /* Valid flags for SECCOMP_SET_MODE_FILTER */
 #define SECCOMP_FILTER_FLAG_TSYNC      1
+#define SECCOMP_FILTER_FLAG_LOG                2
 
 /*
  * All BPF programs must return a 32-bit value.
  * The bottom 16-bits are for optional return data.
- * The upper 16-bits are ordered from least permissive values to most.
+ * The upper 16-bits are ordered from least permissive values to most,
+ * as a signed value (so 0x8000000 is negative).
  *
  * The ordering ensures that a min_t() over composed return values always
  * selects the least permissive choice.
  */
-#define SECCOMP_RET_KILL       0x00000000U /* kill the task immediately */
-#define SECCOMP_RET_TRAP       0x00030000U /* disallow and force a SIGSYS */
-#define SECCOMP_RET_ERRNO      0x00050000U /* returns an errno */
-#define SECCOMP_RET_TRACE      0x7ff00000U /* pass to a tracer or disallow */
-#define SECCOMP_RET_ALLOW      0x7fff0000U /* allow */
+#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
+#define SECCOMP_RET_KILL_THREAD         0x00000000U /* kill the thread */
+#define SECCOMP_RET_KILL        SECCOMP_RET_KILL_THREAD
+#define SECCOMP_RET_TRAP        0x00030000U /* disallow and force a SIGSYS */
+#define SECCOMP_RET_ERRNO       0x00050000U /* returns an errno */
+#define SECCOMP_RET_TRACE       0x7ff00000U /* pass to a tracer or disallow */
+#define SECCOMP_RET_LOG                 0x7ffc0000U /* allow after logging */
+#define SECCOMP_RET_ALLOW       0x7fff0000U /* allow */
 
 /* Masks for the return value sections. */
+#define SECCOMP_RET_ACTION_FULL        0xffff0000U
 #define SECCOMP_RET_ACTION     0x7fff0000U
 #define SECCOMP_RET_DATA       0x0000ffffU
 
index 9a0b6479fe0c626a05cc86da382181c81b1db73f..d4e0b53bfc75ccdf03585c7b402389a21aba4dca 100644 (file)
@@ -261,7 +261,7 @@ struct ib_uverbs_ex_query_device_resp {
        struct ib_uverbs_rss_caps rss_caps;
        __u32  max_wq_type_rq;
        __u32 raw_packet_caps;
-       struct ib_uverbs_tm_caps xrq_caps;
+       struct ib_uverbs_tm_caps tm_caps;
 };
 
 struct ib_uverbs_query_port {
index 415dbc6e43fd7ac6c256e2b30b704567ab5966d2..6adc2a955340627c590e1e06e8ab146b3c058f12 100644 (file)
@@ -84,16 +84,6 @@ static inline xmaddr_t arbitrary_virt_to_machine(void *vaddr)
        BUG();
 }
 
-/* TODO: this shouldn't be here but it is because the frontend drivers
- * are using it (its rolled in headers) even though we won't hit the code path.
- * So for right now just punt with this.
- */
-static inline pte_t *lookup_address(unsigned long address, unsigned int *level)
-{
-       BUG();
-       return NULL;
-}
-
 extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
                                   struct gnttab_map_grant_ref *kmap_ops,
                                   struct page **pages, unsigned int count);
index 1b3adfe3c60e259e7366aa76a23b14e7c1a173b5..badac463e2c8ea7a035c73acd385d4d58211e6ac 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1154,7 +1154,7 @@ static int put_compat_shm_info(struct shm_info *ip,
        info.shm_swp = ip->shm_swp;
        info.swap_attempts = ip->swap_attempts;
        info.swap_successes = ip->swap_successes;
-       return copy_to_user(up, &info, sizeof(info));
+       return copy_to_user(uip, &info, sizeof(info));
 }
 
 static int copy_compat_shmid_to_user(void __user *buf, struct shmid64_ds *in,
@@ -1237,7 +1237,7 @@ COMPAT_SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, void __user *, uptr)
                err = shmctl_stat(ns, shmid, cmd, &sem64);
                if (err < 0)
                        return err;
-               if (copy_compat_shmid_to_user(&sem64, uptr, version))
+               if (copy_compat_shmid_to_user(uptr, &sem64, version))
                        err = -EFAULT;
                return err;
 
index 959c9a07f318b14f6ab4719973f6010de061aadc..e093d9a2c4dd3fb5f02503bf0c741f2af9cc7c48 100644 (file)
@@ -75,8 +75,8 @@ static u64 dev_map_bitmap_size(const union bpf_attr *attr)
 static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
 {
        struct bpf_dtab *dtab;
+       int err = -EINVAL;
        u64 cost;
-       int err;
 
        /* check sanity of attributes */
        if (attr->max_entries == 0 || attr->key_size != 4 ||
@@ -108,6 +108,8 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
        if (err)
                goto free_dtab;
 
+       err = -ENOMEM;
+
        /* A per cpu bitfield with a bit per possible net device */
        dtab->flush_needed = __alloc_percpu(dev_map_bitmap_size(attr),
                                            __alignof__(unsigned long));
@@ -128,7 +130,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
 free_dtab:
        free_percpu(dtab->flush_needed);
        kfree(dtab);
-       return ERR_PTR(-ENOMEM);
+       return ERR_PTR(err);
 }
 
 static void dev_map_free(struct bpf_map *map)
index cb17e1cd1d434dc2e052a2a9fb0aea967fcf4417..25d074920a009ff682d97bf88e68f466c79bd564 100644 (file)
@@ -186,15 +186,17 @@ static int bpf_map_alloc_id(struct bpf_map *map)
 
 static void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock)
 {
+       unsigned long flags;
+
        if (do_idr_lock)
-               spin_lock_bh(&map_idr_lock);
+               spin_lock_irqsave(&map_idr_lock, flags);
        else
                __acquire(&map_idr_lock);
 
        idr_remove(&map_idr, map->id);
 
        if (do_idr_lock)
-               spin_unlock_bh(&map_idr_lock);
+               spin_unlock_irqrestore(&map_idr_lock, flags);
        else
                __release(&map_idr_lock);
 }
index 799b2451ef2df42b17aadfe679a09dee9a0848c9..b914fbe1383e83fa9609944bc54358456794f470 100644 (file)
@@ -4205,7 +4205,12 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
                }
 
                if (insn->imm == BPF_FUNC_redirect_map) {
-                       u64 addr = (unsigned long)prog;
+                       /* Note, we cannot use prog directly as imm as subsequent
+                        * rewrites would still change the prog pointer. The only
+                        * stable address we can use is aux, which also works with
+                        * prog clones during blinding.
+                        */
+                       u64 addr = (unsigned long)prog->aux;
                        struct bpf_insn r4_ld[] = {
                                BPF_LD_IMM64(BPF_REG_4, addr),
                                *insn,
index acf5308fad51f17706197ca6550ce7ae3c8b5378..8de11a29e4955d846c0d1d90a2c0b3a207e21a3d 100644 (file)
  * @bringup:   Single callback bringup or teardown selector
  * @cb_state:  The state for a single callback (install/uninstall)
  * @result:    Result of the operation
- * @done:      Signal completion to the issuer of the task
+ * @done_up:   Signal completion to the issuer of the task for cpu-up
+ * @done_down: Signal completion to the issuer of the task for cpu-down
  */
 struct cpuhp_cpu_state {
        enum cpuhp_state        state;
        enum cpuhp_state        target;
+       enum cpuhp_state        fail;
 #ifdef CONFIG_SMP
        struct task_struct      *thread;
        bool                    should_run;
@@ -58,18 +60,39 @@ struct cpuhp_cpu_state {
        bool                    single;
        bool                    bringup;
        struct hlist_node       *node;
+       struct hlist_node       *last;
        enum cpuhp_state        cb_state;
        int                     result;
-       struct completion       done;
+       struct completion       done_up;
+       struct completion       done_down;
 #endif
 };
 
-static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state);
+static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state) = {
+       .fail = CPUHP_INVALID,
+};
 
 #if defined(CONFIG_LOCKDEP) && defined(CONFIG_SMP)
-static struct lock_class_key cpuhp_state_key;
-static struct lockdep_map cpuhp_state_lock_map =
-       STATIC_LOCKDEP_MAP_INIT("cpuhp_state", &cpuhp_state_key);
+static struct lockdep_map cpuhp_state_up_map =
+       STATIC_LOCKDEP_MAP_INIT("cpuhp_state-up", &cpuhp_state_up_map);
+static struct lockdep_map cpuhp_state_down_map =
+       STATIC_LOCKDEP_MAP_INIT("cpuhp_state-down", &cpuhp_state_down_map);
+
+
+static void inline cpuhp_lock_acquire(bool bringup)
+{
+       lock_map_acquire(bringup ? &cpuhp_state_up_map : &cpuhp_state_down_map);
+}
+
+static void inline cpuhp_lock_release(bool bringup)
+{
+       lock_map_release(bringup ? &cpuhp_state_up_map : &cpuhp_state_down_map);
+}
+#else
+
+static void inline cpuhp_lock_acquire(bool bringup) { }
+static void inline cpuhp_lock_release(bool bringup) { }
+
 #endif
 
 /**
@@ -123,13 +146,16 @@ static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state)
 /**
  * cpuhp_invoke_callback _ Invoke the callbacks for a given state
  * @cpu:       The cpu for which the callback should be invoked
- * @step:      The step in the state machine
+ * @state:     The state to do callbacks for
  * @bringup:   True if the bringup callback should be invoked
+ * @node:      For multi-instance, do a single entry callback for install/remove
+ * @lastp:     For multi-instance rollback, remember how far we got
  *
  * Called from cpu hotplug and from the state register machinery.
  */
 static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
-                                bool bringup, struct hlist_node *node)
+                                bool bringup, struct hlist_node *node,
+                                struct hlist_node **lastp)
 {
        struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
        struct cpuhp_step *step = cpuhp_get_step(state);
@@ -137,7 +163,17 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
        int (*cb)(unsigned int cpu);
        int ret, cnt;
 
+       if (st->fail == state) {
+               st->fail = CPUHP_INVALID;
+
+               if (!(bringup ? step->startup.single : step->teardown.single))
+                       return 0;
+
+               return -EAGAIN;
+       }
+
        if (!step->multi_instance) {
+               WARN_ON_ONCE(lastp && *lastp);
                cb = bringup ? step->startup.single : step->teardown.single;
                if (!cb)
                        return 0;
@@ -152,6 +188,7 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
 
        /* Single invocation for instance add/remove */
        if (node) {
+               WARN_ON_ONCE(lastp && *lastp);
                trace_cpuhp_multi_enter(cpu, st->target, state, cbm, node);
                ret = cbm(cpu, node);
                trace_cpuhp_exit(cpu, st->state, state, ret);
@@ -161,13 +198,23 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
        /* State transition. Invoke on all instances */
        cnt = 0;
        hlist_for_each(node, &step->list) {
+               if (lastp && node == *lastp)
+                       break;
+
                trace_cpuhp_multi_enter(cpu, st->target, state, cbm, node);
                ret = cbm(cpu, node);
                trace_cpuhp_exit(cpu, st->state, state, ret);
-               if (ret)
-                       goto err;
+               if (ret) {
+                       if (!lastp)
+                               goto err;
+
+                       *lastp = node;
+                       return ret;
+               }
                cnt++;
        }
+       if (lastp)
+               *lastp = NULL;
        return 0;
 err:
        /* Rollback the instances if one failed */
@@ -178,12 +225,39 @@ err:
        hlist_for_each(node, &step->list) {
                if (!cnt--)
                        break;
-               cbm(cpu, node);
+
+               trace_cpuhp_multi_enter(cpu, st->target, state, cbm, node);
+               ret = cbm(cpu, node);
+               trace_cpuhp_exit(cpu, st->state, state, ret);
+               /*
+                * Rollback must not fail,
+                */
+               WARN_ON_ONCE(ret);
        }
        return ret;
 }
 
 #ifdef CONFIG_SMP
+static inline void wait_for_ap_thread(struct cpuhp_cpu_state *st, bool bringup)
+{
+       struct completion *done = bringup ? &st->done_up : &st->done_down;
+       wait_for_completion(done);
+}
+
+static inline void complete_ap_thread(struct cpuhp_cpu_state *st, bool bringup)
+{
+       struct completion *done = bringup ? &st->done_up : &st->done_down;
+       complete(done);
+}
+
+/*
+ * The former STARTING/DYING states, ran with IRQs disabled and must not fail.
+ */
+static bool cpuhp_is_atomic_state(enum cpuhp_state state)
+{
+       return CPUHP_AP_IDLE_DEAD <= state && state < CPUHP_AP_ONLINE;
+}
+
 /* Serializes the updates to cpu_online_mask, cpu_present_mask */
 static DEFINE_MUTEX(cpu_add_remove_lock);
 bool cpuhp_tasks_frozen;
@@ -271,14 +345,79 @@ void cpu_hotplug_enable(void)
 EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st);
+static inline enum cpuhp_state
+cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target)
+{
+       enum cpuhp_state prev_state = st->state;
+
+       st->rollback = false;
+       st->last = NULL;
+
+       st->target = target;
+       st->single = false;
+       st->bringup = st->state < target;
+
+       return prev_state;
+}
+
+static inline void
+cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state)
+{
+       st->rollback = true;
+
+       /*
+        * If we have st->last we need to undo partial multi_instance of this
+        * state first. Otherwise start undo at the previous state.
+        */
+       if (!st->last) {
+               if (st->bringup)
+                       st->state--;
+               else
+                       st->state++;
+       }
+
+       st->target = prev_state;
+       st->bringup = !st->bringup;
+}
+
+/* Regular hotplug invocation of the AP hotplug thread */
+static void __cpuhp_kick_ap(struct cpuhp_cpu_state *st)
+{
+       if (!st->single && st->state == st->target)
+               return;
+
+       st->result = 0;
+       /*
+        * Make sure the above stores are visible before should_run becomes
+        * true. Paired with the mb() above in cpuhp_thread_fun()
+        */
+       smp_mb();
+       st->should_run = true;
+       wake_up_process(st->thread);
+       wait_for_ap_thread(st, st->bringup);
+}
+
+static int cpuhp_kick_ap(struct cpuhp_cpu_state *st, enum cpuhp_state target)
+{
+       enum cpuhp_state prev_state;
+       int ret;
+
+       prev_state = cpuhp_set_state(st, target);
+       __cpuhp_kick_ap(st);
+       if ((ret = st->result)) {
+               cpuhp_reset_state(st, prev_state);
+               __cpuhp_kick_ap(st);
+       }
+
+       return ret;
+}
 
 static int bringup_wait_for_ap(unsigned int cpu)
 {
        struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
 
        /* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */
-       wait_for_completion(&st->done);
+       wait_for_ap_thread(st, true);
        if (WARN_ON_ONCE((!cpu_online(cpu))))
                return -ECANCELED;
 
@@ -286,12 +425,10 @@ static int bringup_wait_for_ap(unsigned int cpu)
        stop_machine_unpark(cpu);
        kthread_unpark(st->thread);
 
-       /* Should we go further up ? */
-       if (st->target > CPUHP_AP_ONLINE_IDLE) {
-               __cpuhp_kick_ap_work(st);
-               wait_for_completion(&st->done);
-       }
-       return st->result;
+       if (st->target <= CPUHP_AP_ONLINE_IDLE)
+               return 0;
+
+       return cpuhp_kick_ap(st, st->target);
 }
 
 static int bringup_cpu(unsigned int cpu)
@@ -317,32 +454,6 @@ static int bringup_cpu(unsigned int cpu)
 /*
  * Hotplug state machine related functions
  */
-static void undo_cpu_down(unsigned int cpu, struct cpuhp_cpu_state *st)
-{
-       for (st->state++; st->state < st->target; st->state++) {
-               struct cpuhp_step *step = cpuhp_get_step(st->state);
-
-               if (!step->skip_onerr)
-                       cpuhp_invoke_callback(cpu, st->state, true, NULL);
-       }
-}
-
-static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
-                               enum cpuhp_state target)
-{
-       enum cpuhp_state prev_state = st->state;
-       int ret = 0;
-
-       for (; st->state > target; st->state--) {
-               ret = cpuhp_invoke_callback(cpu, st->state, false, NULL);
-               if (ret) {
-                       st->target = prev_state;
-                       undo_cpu_down(cpu, st);
-                       break;
-               }
-       }
-       return ret;
-}
 
 static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
 {
@@ -350,7 +461,7 @@ static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
                struct cpuhp_step *step = cpuhp_get_step(st->state);
 
                if (!step->skip_onerr)
-                       cpuhp_invoke_callback(cpu, st->state, false, NULL);
+                       cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL);
        }
 }
 
@@ -362,7 +473,7 @@ static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
 
        while (st->state < target) {
                st->state++;
-               ret = cpuhp_invoke_callback(cpu, st->state, true, NULL);
+               ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
                if (ret) {
                        st->target = prev_state;
                        undo_cpu_up(cpu, st);
@@ -379,7 +490,8 @@ static void cpuhp_create(unsigned int cpu)
 {
        struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
 
-       init_completion(&st->done);
+       init_completion(&st->done_up);
+       init_completion(&st->done_down);
 }
 
 static int cpuhp_should_run(unsigned int cpu)
@@ -389,69 +501,90 @@ static int cpuhp_should_run(unsigned int cpu)
        return st->should_run;
 }
 
-/* Execute the teardown callbacks. Used to be CPU_DOWN_PREPARE */
-static int cpuhp_ap_offline(unsigned int cpu, struct cpuhp_cpu_state *st)
-{
-       enum cpuhp_state target = max((int)st->target, CPUHP_TEARDOWN_CPU);
-
-       return cpuhp_down_callbacks(cpu, st, target);
-}
-
-/* Execute the online startup callbacks. Used to be CPU_ONLINE */
-static int cpuhp_ap_online(unsigned int cpu, struct cpuhp_cpu_state *st)
-{
-       return cpuhp_up_callbacks(cpu, st, st->target);
-}
-
 /*
  * Execute teardown/startup callbacks on the plugged cpu. Also used to invoke
  * callbacks when a state gets [un]installed at runtime.
+ *
+ * Each invocation of this function by the smpboot thread does a single AP
+ * state callback.
+ *
+ * It has 3 modes of operation:
+ *  - single: runs st->cb_state
+ *  - up:     runs ++st->state, while st->state < st->target
+ *  - down:   runs st->state--, while st->state > st->target
+ *
+ * When complete or on error, should_run is cleared and the completion is fired.
  */
 static void cpuhp_thread_fun(unsigned int cpu)
 {
        struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
-       int ret = 0;
+       bool bringup = st->bringup;
+       enum cpuhp_state state;
 
        /*
-        * Paired with the mb() in cpuhp_kick_ap_work and
-        * cpuhp_invoke_ap_callback, so the work set is consistent visible.
+        * ACQUIRE for the cpuhp_should_run() load of ->should_run. Ensures
+        * that if we see ->should_run we also see the rest of the state.
         */
        smp_mb();
-       if (!st->should_run)
+
+       if (WARN_ON_ONCE(!st->should_run))
                return;
 
-       st->should_run = false;
+       cpuhp_lock_acquire(bringup);
 
-       lock_map_acquire(&cpuhp_state_lock_map);
-       /* Single callback invocation for [un]install ? */
        if (st->single) {
-               if (st->cb_state < CPUHP_AP_ONLINE) {
-                       local_irq_disable();
-                       ret = cpuhp_invoke_callback(cpu, st->cb_state,
-                                                   st->bringup, st->node);
-                       local_irq_enable();
+               state = st->cb_state;
+               st->should_run = false;
+       } else {
+               if (bringup) {
+                       st->state++;
+                       state = st->state;
+                       st->should_run = (st->state < st->target);
+                       WARN_ON_ONCE(st->state > st->target);
                } else {
-                       ret = cpuhp_invoke_callback(cpu, st->cb_state,
-                                                   st->bringup, st->node);
+                       state = st->state;
+                       st->state--;
+                       st->should_run = (st->state > st->target);
+                       WARN_ON_ONCE(st->state < st->target);
                }
-       } else if (st->rollback) {
-               BUG_ON(st->state < CPUHP_AP_ONLINE_IDLE);
+       }
+
+       WARN_ON_ONCE(!cpuhp_is_ap_state(state));
 
-               undo_cpu_down(cpu, st);
-               st->rollback = false;
+       if (st->rollback) {
+               struct cpuhp_step *step = cpuhp_get_step(state);
+               if (step->skip_onerr)
+                       goto next;
+       }
+
+       if (cpuhp_is_atomic_state(state)) {
+               local_irq_disable();
+               st->result = cpuhp_invoke_callback(cpu, state, bringup, st->node, &st->last);
+               local_irq_enable();
+
+               /*
+                * STARTING/DYING must not fail!
+                */
+               WARN_ON_ONCE(st->result);
        } else {
-               /* Cannot happen .... */
-               BUG_ON(st->state < CPUHP_AP_ONLINE_IDLE);
-
-               /* Regular hotplug work */
-               if (st->state < st->target)
-                       ret = cpuhp_ap_online(cpu, st);
-               else if (st->state > st->target)
-                       ret = cpuhp_ap_offline(cpu, st);
+               st->result = cpuhp_invoke_callback(cpu, state, bringup, st->node, &st->last);
+       }
+
+       if (st->result) {
+               /*
+                * If we fail on a rollback, we're up a creek without no
+                * paddle, no way forward, no way back. We loose, thanks for
+                * playing.
+                */
+               WARN_ON_ONCE(st->rollback);
+               st->should_run = false;
        }
-       lock_map_release(&cpuhp_state_lock_map);
-       st->result = ret;
-       complete(&st->done);
+
+next:
+       cpuhp_lock_release(bringup);
+
+       if (!st->should_run)
+               complete_ap_thread(st, bringup);
 }
 
 /* Invoke a single callback on a remote cpu */
@@ -460,62 +593,64 @@ cpuhp_invoke_ap_callback(int cpu, enum cpuhp_state state, bool bringup,
                         struct hlist_node *node)
 {
        struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+       int ret;
 
        if (!cpu_online(cpu))
                return 0;
 
-       lock_map_acquire(&cpuhp_state_lock_map);
-       lock_map_release(&cpuhp_state_lock_map);
+       cpuhp_lock_acquire(false);
+       cpuhp_lock_release(false);
+
+       cpuhp_lock_acquire(true);
+       cpuhp_lock_release(true);
 
        /*
         * If we are up and running, use the hotplug thread. For early calls
         * we invoke the thread function directly.
         */
        if (!st->thread)
-               return cpuhp_invoke_callback(cpu, state, bringup, node);
+               return cpuhp_invoke_callback(cpu, state, bringup, node, NULL);
 
+       st->rollback = false;
+       st->last = NULL;
+
+       st->node = node;
+       st->bringup = bringup;
        st->cb_state = state;
        st->single = true;
-       st->bringup = bringup;
-       st->node = node;
 
-       /*
-        * Make sure the above stores are visible before should_run becomes
-        * true. Paired with the mb() above in cpuhp_thread_fun()
-        */
-       smp_mb();
-       st->should_run = true;
-       wake_up_process(st->thread);
-       wait_for_completion(&st->done);
-       return st->result;
-}
+       __cpuhp_kick_ap(st);
 
-/* Regular hotplug invocation of the AP hotplug thread */
-static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st)
-{
-       st->result = 0;
-       st->single = false;
        /*
-        * Make sure the above stores are visible before should_run becomes
-        * true. Paired with the mb() above in cpuhp_thread_fun()
+        * If we failed and did a partial, do a rollback.
         */
-       smp_mb();
-       st->should_run = true;
-       wake_up_process(st->thread);
+       if ((ret = st->result) && st->last) {
+               st->rollback = true;
+               st->bringup = !bringup;
+
+               __cpuhp_kick_ap(st);
+       }
+
+       return ret;
 }
 
 static int cpuhp_kick_ap_work(unsigned int cpu)
 {
        struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
-       enum cpuhp_state state = st->state;
+       enum cpuhp_state prev_state = st->state;
+       int ret;
+
+       cpuhp_lock_acquire(false);
+       cpuhp_lock_release(false);
+
+       cpuhp_lock_acquire(true);
+       cpuhp_lock_release(true);
+
+       trace_cpuhp_enter(cpu, st->target, prev_state, cpuhp_kick_ap_work);
+       ret = cpuhp_kick_ap(st, st->target);
+       trace_cpuhp_exit(cpu, st->state, prev_state, ret);
 
-       trace_cpuhp_enter(cpu, st->target, state, cpuhp_kick_ap_work);
-       lock_map_acquire(&cpuhp_state_lock_map);
-       lock_map_release(&cpuhp_state_lock_map);
-       __cpuhp_kick_ap_work(st);
-       wait_for_completion(&st->done);
-       trace_cpuhp_exit(cpu, st->state, state, st->result);
-       return st->result;
+       return ret;
 }
 
 static struct smp_hotplug_thread cpuhp_threads = {
@@ -581,6 +716,7 @@ static int take_cpu_down(void *_param)
        struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
        enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE);
        int err, cpu = smp_processor_id();
+       int ret;
 
        /* Ensure this CPU doesn't handle any more interrupts. */
        err = __cpu_disable();
@@ -594,8 +730,13 @@ static int take_cpu_down(void *_param)
        WARN_ON(st->state != CPUHP_TEARDOWN_CPU);
        st->state--;
        /* Invoke the former CPU_DYING callbacks */
-       for (; st->state > target; st->state--)
-               cpuhp_invoke_callback(cpu, st->state, false, NULL);
+       for (; st->state > target; st->state--) {
+               ret = cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL);
+               /*
+                * DYING must not fail!
+                */
+               WARN_ON_ONCE(ret);
+       }
 
        /* Give up timekeeping duties */
        tick_handover_do_timer();
@@ -639,7 +780,7 @@ static int takedown_cpu(unsigned int cpu)
         *
         * Wait for the stop thread to go away.
         */
-       wait_for_completion(&st->done);
+       wait_for_ap_thread(st, false);
        BUG_ON(st->state != CPUHP_AP_IDLE_DEAD);
 
        /* Interrupts are moved away from the dying cpu, reenable alloc/free */
@@ -658,7 +799,7 @@ static void cpuhp_complete_idle_dead(void *arg)
 {
        struct cpuhp_cpu_state *st = arg;
 
-       complete(&st->done);
+       complete_ap_thread(st, false);
 }
 
 void cpuhp_report_idle_dead(void)
@@ -676,11 +817,32 @@ void cpuhp_report_idle_dead(void)
                                 cpuhp_complete_idle_dead, st, 0);
 }
 
-#else
-#define takedown_cpu           NULL
-#endif
+static void undo_cpu_down(unsigned int cpu, struct cpuhp_cpu_state *st)
+{
+       for (st->state++; st->state < st->target; st->state++) {
+               struct cpuhp_step *step = cpuhp_get_step(st->state);
 
-#ifdef CONFIG_HOTPLUG_CPU
+               if (!step->skip_onerr)
+                       cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
+       }
+}
+
+static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
+                               enum cpuhp_state target)
+{
+       enum cpuhp_state prev_state = st->state;
+       int ret = 0;
+
+       for (; st->state > target; st->state--) {
+               ret = cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL);
+               if (ret) {
+                       st->target = prev_state;
+                       undo_cpu_down(cpu, st);
+                       break;
+               }
+       }
+       return ret;
+}
 
 /* Requires cpu_add_remove_lock to be held */
 static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
@@ -699,13 +861,13 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
 
        cpuhp_tasks_frozen = tasks_frozen;
 
-       prev_state = st->state;
-       st->target = target;
+       prev_state = cpuhp_set_state(st, target);
        /*
         * If the current CPU state is in the range of the AP hotplug thread,
         * then we need to kick the thread.
         */
        if (st->state > CPUHP_TEARDOWN_CPU) {
+               st->target = max((int)target, CPUHP_TEARDOWN_CPU);
                ret = cpuhp_kick_ap_work(cpu);
                /*
                 * The AP side has done the error rollback already. Just
@@ -720,6 +882,8 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
                 */
                if (st->state > CPUHP_TEARDOWN_CPU)
                        goto out;
+
+               st->target = target;
        }
        /*
         * The AP brought itself down to CPUHP_TEARDOWN_CPU. So we need
@@ -727,9 +891,8 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
         */
        ret = cpuhp_down_callbacks(cpu, st, target);
        if (ret && st->state > CPUHP_TEARDOWN_CPU && st->state < prev_state) {
-               st->target = prev_state;
-               st->rollback = true;
-               cpuhp_kick_ap_work(cpu);
+               cpuhp_reset_state(st, prev_state);
+               __cpuhp_kick_ap(st);
        }
 
 out:
@@ -754,11 +917,15 @@ out:
        cpu_maps_update_done();
        return err;
 }
+
 int cpu_down(unsigned int cpu)
 {
        return do_cpu_down(cpu, CPUHP_OFFLINE);
 }
 EXPORT_SYMBOL(cpu_down);
+
+#else
+#define takedown_cpu           NULL
 #endif /*CONFIG_HOTPLUG_CPU*/
 
 /**
@@ -772,11 +939,16 @@ void notify_cpu_starting(unsigned int cpu)
 {
        struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
        enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE);
+       int ret;
 
        rcu_cpu_starting(cpu);  /* Enables RCU usage on this CPU. */
        while (st->state < target) {
                st->state++;
-               cpuhp_invoke_callback(cpu, st->state, true, NULL);
+               ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
+               /*
+                * STARTING must not fail!
+                */
+               WARN_ON_ONCE(ret);
        }
 }
 
@@ -794,7 +966,7 @@ void cpuhp_online_idle(enum cpuhp_state state)
                return;
 
        st->state = CPUHP_AP_ONLINE_IDLE;
-       complete(&st->done);
+       complete_ap_thread(st, true);
 }
 
 /* Requires cpu_add_remove_lock to be held */
@@ -829,7 +1001,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
 
        cpuhp_tasks_frozen = tasks_frozen;
 
-       st->target = target;
+       cpuhp_set_state(st, target);
        /*
         * If the current CPU state is in the range of the AP hotplug thread,
         * then we need to kick the thread once more.
@@ -1296,6 +1468,10 @@ static int cpuhp_issue_call(int cpu, enum cpuhp_state state, bool bringup,
        struct cpuhp_step *sp = cpuhp_get_step(state);
        int ret;
 
+       /*
+        * If there's nothing to do, we done.
+        * Relies on the union for multi_instance.
+        */
        if ((bringup && !sp->startup.single) ||
            (!bringup && !sp->teardown.single))
                return 0;
@@ -1307,9 +1483,9 @@ static int cpuhp_issue_call(int cpu, enum cpuhp_state state, bool bringup,
        if (cpuhp_is_ap_state(state))
                ret = cpuhp_invoke_ap_callback(cpu, state, bringup, node);
        else
-               ret = cpuhp_invoke_callback(cpu, state, bringup, node);
+               ret = cpuhp_invoke_callback(cpu, state, bringup, node, NULL);
 #else
-       ret = cpuhp_invoke_callback(cpu, state, bringup, node);
+       ret = cpuhp_invoke_callback(cpu, state, bringup, node, NULL);
 #endif
        BUG_ON(ret && !bringup);
        return ret;
@@ -1641,9 +1817,55 @@ static ssize_t show_cpuhp_target(struct device *dev,
 }
 static DEVICE_ATTR(target, 0644, show_cpuhp_target, write_cpuhp_target);
 
+
+static ssize_t write_cpuhp_fail(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, dev->id);
+       struct cpuhp_step *sp;
+       int fail, ret;
+
+       ret = kstrtoint(buf, 10, &fail);
+       if (ret)
+               return ret;
+
+       /*
+        * Cannot fail STARTING/DYING callbacks.
+        */
+       if (cpuhp_is_atomic_state(fail))
+               return -EINVAL;
+
+       /*
+        * Cannot fail anything that doesn't have callbacks.
+        */
+       mutex_lock(&cpuhp_state_mutex);
+       sp = cpuhp_get_step(fail);
+       if (!sp->startup.single && !sp->teardown.single)
+               ret = -EINVAL;
+       mutex_unlock(&cpuhp_state_mutex);
+       if (ret)
+               return ret;
+
+       st->fail = fail;
+
+       return count;
+}
+
+static ssize_t show_cpuhp_fail(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, dev->id);
+
+       return sprintf(buf, "%d\n", st->fail);
+}
+
+static DEVICE_ATTR(fail, 0644, show_cpuhp_fail, write_cpuhp_fail);
+
 static struct attribute *cpuhp_cpu_attrs[] = {
        &dev_attr_state.attr,
        &dev_attr_target.attr,
+       &dev_attr_fail.attr,
        NULL
 };
 
index 3e691b75b2db2eab410208b7312687270e1fe765..6bc21e202ae40d36ceb9fa23d3c78785cad957da 100644 (file)
@@ -8171,6 +8171,7 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
                }
        }
        event->tp_event->prog = prog;
+       event->tp_event->bpf_prog_owner = event;
 
        return 0;
 }
@@ -8185,7 +8186,7 @@ static void perf_event_free_bpf_prog(struct perf_event *event)
                return;
 
        prog = event->tp_event->prog;
-       if (prog) {
+       if (prog && event->tp_event->bpf_prog_owner == event) {
                event->tp_event->prog = NULL;
                bpf_prog_put(prog);
        }
index af71a84e12eea343c6047184599fedf7f5592e65..f684d8e5fa2be2fd10e4d5e2f1e65a5c2afeb629 100644 (file)
@@ -412,6 +412,19 @@ err:
        return NULL;
 }
 
+static bool __always_inline rb_need_aux_wakeup(struct ring_buffer *rb)
+{
+       if (rb->aux_overwrite)
+               return false;
+
+       if (rb->aux_head - rb->aux_wakeup >= rb->aux_watermark) {
+               rb->aux_wakeup = rounddown(rb->aux_head, rb->aux_watermark);
+               return true;
+       }
+
+       return false;
+}
+
 /*
  * Commit the data written by hardware into the ring buffer by adjusting
  * aux_head and posting a PERF_RECORD_AUX into the perf buffer. It is the
@@ -451,10 +464,8 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
        }
 
        rb->user_page->aux_head = rb->aux_head;
-       if (rb->aux_head - rb->aux_wakeup >= rb->aux_watermark) {
+       if (rb_need_aux_wakeup(rb))
                wakeup = true;
-               rb->aux_wakeup = rounddown(rb->aux_head, rb->aux_watermark);
-       }
 
        if (wakeup) {
                if (handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)
@@ -484,9 +495,8 @@ int perf_aux_output_skip(struct perf_output_handle *handle, unsigned long size)
        rb->aux_head += size;
 
        rb->user_page->aux_head = rb->aux_head;
-       if (rb->aux_head - rb->aux_wakeup >= rb->aux_watermark) {
+       if (rb_need_aux_wakeup(rb)) {
                perf_output_wakeup(handle);
-               rb->aux_wakeup = rounddown(rb->aux_head, rb->aux_watermark);
                handle->wakeup = rb->aux_wakeup + rb->aux_watermark;
        }
 
index 3481ababd06aa6cdd2aedd1fee0e56026acddc3b..f2cd53e92147c35c43d773b1eb688098fe4b7db3 100644 (file)
@@ -1600,12 +1600,10 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
        struct waitid_info info = {.status = 0};
        long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
        int signo = 0;
+
        if (err > 0) {
                signo = SIGCHLD;
                err = 0;
-       }
-
-       if (!err) {
                if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
                        return -EFAULT;
        }
@@ -1723,16 +1721,15 @@ COMPAT_SYSCALL_DEFINE5(waitid,
        if (err > 0) {
                signo = SIGCHLD;
                err = 0;
-       }
-
-       if (!err && uru) {
-               /* kernel_waitid() overwrites everything in ru */
-               if (COMPAT_USE_64BIT_TIME)
-                       err = copy_to_user(uru, &ru, sizeof(ru));
-               else
-                       err = put_compat_rusage(&ru, uru);
-               if (err)
-                       return -EFAULT;
+               if (uru) {
+                       /* kernel_waitid() overwrites everything in ru */
+                       if (COMPAT_USE_64BIT_TIME)
+                               err = copy_to_user(uru, &ru, sizeof(ru));
+                       else
+                               err = put_compat_rusage(&ru, uru);
+                       if (err)
+                               return -EFAULT;
+               }
        }
 
        if (!infop)
index 38c2412401a1b118d53d3cff92eba24753134aed..9aa1cc41ecf79c8c2cc5fb9dbd3fbd418025c0dd 100644 (file)
@@ -102,15 +102,7 @@ int core_kernel_data(unsigned long addr)
 
 int __kernel_text_address(unsigned long addr)
 {
-       if (core_kernel_text(addr))
-               return 1;
-       if (is_module_text_address(addr))
-               return 1;
-       if (is_ftrace_trampoline(addr))
-               return 1;
-       if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
-               return 1;
-       if (is_bpf_text_address(addr))
+       if (kernel_text_address(addr))
                return 1;
        /*
         * There might be init symbols in saved stacktraces.
@@ -127,17 +119,42 @@ int __kernel_text_address(unsigned long addr)
 
 int kernel_text_address(unsigned long addr)
 {
+       bool no_rcu;
+       int ret = 1;
+
        if (core_kernel_text(addr))
                return 1;
+
+       /*
+        * If a stack dump happens while RCU is not watching, then
+        * RCU needs to be notified that it requires to start
+        * watching again. This can happen either by tracing that
+        * triggers a stack trace, or a WARN() that happens during
+        * coming back from idle, or cpu on or offlining.
+        *
+        * is_module_text_address() as well as the kprobe slots
+        * and is_bpf_text_address() require RCU to be watching.
+        */
+       no_rcu = !rcu_is_watching();
+
+       /* Treat this like an NMI as it can happen anywhere */
+       if (no_rcu)
+               rcu_nmi_enter();
+
        if (is_module_text_address(addr))
-               return 1;
+               goto out;
        if (is_ftrace_trampoline(addr))
-               return 1;
+               goto out;
        if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
-               return 1;
+               goto out;
        if (is_bpf_text_address(addr))
-               return 1;
-       return 0;
+               goto out;
+       ret = 0;
+out:
+       if (no_rcu)
+               rcu_nmi_exit();
+
+       return ret;
 }
 
 /*
index 3d38eaf0549209ddb72e83780df6167a4423e8a2..0518a0bfc746bab4f257f2fa81ef7361f99ff113 100644 (file)
@@ -821,8 +821,6 @@ static void get_pi_state(struct futex_pi_state *pi_state)
 /*
  * Drops a reference to the pi_state object and frees or caches it
  * when the last reference is gone.
- *
- * Must be called with the hb lock held.
  */
 static void put_pi_state(struct futex_pi_state *pi_state)
 {
@@ -837,16 +835,22 @@ static void put_pi_state(struct futex_pi_state *pi_state)
         * and has cleaned up the pi_state already
         */
        if (pi_state->owner) {
-               raw_spin_lock_irq(&pi_state->owner->pi_lock);
-               list_del_init(&pi_state->list);
-               raw_spin_unlock_irq(&pi_state->owner->pi_lock);
+               struct task_struct *owner;
 
-               rt_mutex_proxy_unlock(&pi_state->pi_mutex, pi_state->owner);
+               raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+               owner = pi_state->owner;
+               if (owner) {
+                       raw_spin_lock(&owner->pi_lock);
+                       list_del_init(&pi_state->list);
+                       raw_spin_unlock(&owner->pi_lock);
+               }
+               rt_mutex_proxy_unlock(&pi_state->pi_mutex, owner);
+               raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
        }
 
-       if (current->pi_state_cache)
+       if (current->pi_state_cache) {
                kfree(pi_state);
-       else {
+       else {
                /*
                 * pi_state->list is already empty.
                 * clear pi_state->owner.
@@ -907,13 +911,14 @@ void exit_pi_state_list(struct task_struct *curr)
                raw_spin_unlock_irq(&curr->pi_lock);
 
                spin_lock(&hb->lock);
-
-               raw_spin_lock_irq(&curr->pi_lock);
+               raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+               raw_spin_lock(&curr->pi_lock);
                /*
                 * We dropped the pi-lock, so re-check whether this
                 * task still owns the PI-state:
                 */
                if (head->next != next) {
+                       raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
                        spin_unlock(&hb->lock);
                        continue;
                }
@@ -922,9 +927,10 @@ void exit_pi_state_list(struct task_struct *curr)
                WARN_ON(list_empty(&pi_state->list));
                list_del_init(&pi_state->list);
                pi_state->owner = NULL;
-               raw_spin_unlock_irq(&curr->pi_lock);
+               raw_spin_unlock(&curr->pi_lock);
 
                get_pi_state(pi_state);
+               raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
                spin_unlock(&hb->lock);
 
                rt_mutex_futex_unlock(&pi_state->pi_mutex);
@@ -1208,6 +1214,10 @@ static int attach_to_pi_owner(u32 uval, union futex_key *key,
 
        WARN_ON(!list_empty(&pi_state->list));
        list_add(&pi_state->list, &p->pi_state_list);
+       /*
+        * Assignment without holding pi_state->pi_mutex.wait_lock is safe
+        * because there is no concurrency as the object is not published yet.
+        */
        pi_state->owner = p;
        raw_spin_unlock_irq(&p->pi_lock);
 
@@ -2878,6 +2888,7 @@ retry:
                raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
                spin_unlock(&hb->lock);
 
+               /* drops pi_state->pi_mutex.wait_lock */
                ret = wake_futex_pi(uaddr, uval, pi_state);
 
                put_pi_state(pi_state);
index f51b7b6d245177292bb3dbdc2ab25ebc7ddf42b2..6fc89fd938248f7e616e1594a786e2ffc4f19a5c 100644 (file)
@@ -202,7 +202,7 @@ __irq_startup_managed(struct irq_desc *desc, struct cpumask *aff, bool force)
 
        irqd_clr_managed_shutdown(d);
 
-       if (cpumask_any_and(aff, cpu_online_mask) > nr_cpu_ids) {
+       if (cpumask_any_and(aff, cpu_online_mask) >= nr_cpu_ids) {
                /*
                 * Catch code which fiddles with enable_irq() on a managed
                 * and potentially shutdown IRQ. Chained interrupt
index f7086b78ad6e1e1bcb3995537b024d7ed057ef0e..5270a54b9fa4dbf6a4cbdf3e990edc6a0156a915 100644 (file)
@@ -322,7 +322,6 @@ int __irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip,
                /* Calc pointer to the next generic chip */
                tmp += sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
        }
-       d->name = name;
        return 0;
 }
 EXPORT_SYMBOL_GPL(__irq_alloc_domain_generic_chips);
index e84b7056bb083349b8326ee5dae71284a4fc22cb..ac4644e92b499949b1a11652ddde3e3bccba8072 100644 (file)
@@ -945,7 +945,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
        struct irq_desc *desc;
        struct irq_domain *domain;
        struct radix_tree_iter iter;
-       void **slot;
+       void __rcu **slot;
        int i;
 
        seq_printf(m, " %-16s  %-6s  %-10s  %-10s  %s\n",
@@ -1453,7 +1453,7 @@ out_free_desc:
 /* The irq_data was moved, fix the revmap to refer to the new location */
 static void irq_domain_fix_revmap(struct irq_data *d)
 {
-       void **slot;
+       void __rcu **slot;
 
        if (d->hwirq < d->domain->revmap_size)
                return; /* Not using radix tree. */
index 573dc52b0806054bc485c1290d0ed58ccfbb5c87..d00132b5c325b389f6646de064527df64e2d873e 100644 (file)
@@ -1643,6 +1643,10 @@ const void *free_irq(unsigned int irq, void *dev_id)
 #endif
 
        action = __free_irq(irq, dev_id);
+
+       if (!action)
+               return NULL;
+
        devname = action->name;
        kfree(action);
        return devname;
index 02f660666ab8976ea51215427050d1fe3807326f..1fefe6dcafd7403a9b172e11ebd0f41d35332211 100644 (file)
@@ -612,6 +612,33 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
        unsigned long flags;
        DEFINE_WAKE_Q(wake_q);
 
+       /*
+       * __rwsem_down_write_failed_common(sem)
+       *   rwsem_optimistic_spin(sem)
+       *     osq_unlock(sem->osq)
+       *   ...
+       *   atomic_long_add_return(&sem->count)
+       *
+       *      - VS -
+       *
+       *              __up_write()
+       *                if (atomic_long_sub_return_release(&sem->count) < 0)
+       *                  rwsem_wake(sem)
+       *                    osq_is_locked(&sem->osq)
+       *
+       * And __up_write() must observe !osq_is_locked() when it observes the
+       * atomic_long_add_return() in order to not miss a wakeup.
+       *
+       * This boils down to:
+       *
+       * [S.rel] X = 1                [RmW] r0 = (Y += 0)
+       *         MB                         RMB
+       * [RmW]   Y += 1               [L]   r1 = X
+       *
+       * exists (r0=1 /\ r1=0)
+       */
+       smp_rmb();
+
        /*
         * If a spinner is present, it is not necessary to do the wakeup.
         * Try to do wakeup only if the trylock succeeds to minimize
index 1250e4bd4b85e690c7db2b061a87599e8651a606..0c44c7b42e6d50bbb67ae47cbe257a734020b16c 100644 (file)
@@ -882,6 +882,11 @@ void rcu_irq_exit(void)
 
        RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_irq_exit() invoked with irqs enabled!!!");
        rdtp = this_cpu_ptr(&rcu_dynticks);
+
+       /* Page faults can happen in NMI handlers, so check... */
+       if (READ_ONCE(rdtp->dynticks_nmi_nesting))
+               return;
+
        WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
                     rdtp->dynticks_nesting < 1);
        if (rdtp->dynticks_nesting <= 1) {
@@ -1015,6 +1020,11 @@ void rcu_irq_enter(void)
 
        RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_irq_enter() invoked with irqs enabled!!!");
        rdtp = this_cpu_ptr(&rcu_dynticks);
+
+       /* Page faults can happen in NMI handlers, so check... */
+       if (READ_ONCE(rdtp->dynticks_nmi_nesting))
+               return;
+
        oldval = rdtp->dynticks_nesting;
        rdtp->dynticks_nesting++;
        WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
index 18a6966567daf30517a9f832e4a88b20ae705401..d17c5da523a0bc817a6b32413ee7e0ba3e7a6b2e 100644 (file)
@@ -5166,6 +5166,28 @@ void sched_show_task(struct task_struct *p)
        put_task_stack(p);
 }
 
+static inline bool
+state_filter_match(unsigned long state_filter, struct task_struct *p)
+{
+       /* no filter, everything matches */
+       if (!state_filter)
+               return true;
+
+       /* filter, but doesn't match */
+       if (!(p->state & state_filter))
+               return false;
+
+       /*
+        * When looking for TASK_UNINTERRUPTIBLE skip TASK_IDLE (allows
+        * TASK_KILLABLE).
+        */
+       if (state_filter == TASK_UNINTERRUPTIBLE && p->state == TASK_IDLE)
+               return false;
+
+       return true;
+}
+
+
 void show_state_filter(unsigned long state_filter)
 {
        struct task_struct *g, *p;
@@ -5188,7 +5210,7 @@ void show_state_filter(unsigned long state_filter)
                 */
                touch_nmi_watchdog();
                touch_all_softlockup_watchdogs();
-               if (!state_filter || (p->state & state_filter))
+               if (state_filter_match(state_filter, p))
                        sched_show_task(p);
        }
 
index 01217fb5a5de9bd007506020cffb5052ab3abba8..2f93e4a2d9f623915d0023f9b3a7d8b7d7b95cf7 100644 (file)
@@ -466,8 +466,6 @@ static char *task_group_path(struct task_group *tg)
 }
 #endif
 
-static const char stat_nam[] = TASK_STATE_TO_CHAR_STR;
-
 static void
 print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
 {
index 98b59b5db90baae53b091afe807c133e6027d081..bb3a38005b9cc3f3b9f80d49c40bb9428e12a20d 100644 (file)
 #include <linux/audit.h>
 #include <linux/compat.h>
 #include <linux/coredump.h>
+#include <linux/kmemleak.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/seccomp.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
+#include <linux/sysctl.h>
 
 #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
 #include <asm/syscall.h>
@@ -42,6 +44,7 @@
  *         get/put helpers should be used when accessing an instance
  *         outside of a lifetime-guarded section.  In general, this
  *         is only needed for handling filters shared across tasks.
+ * @log: true if all actions except for SECCOMP_RET_ALLOW should be logged
  * @prev: points to a previously installed, or inherited, filter
  * @prog: the BPF program to evaluate
  *
@@ -57,6 +60,7 @@
  */
 struct seccomp_filter {
        refcount_t usage;
+       bool log;
        struct seccomp_filter *prev;
        struct bpf_prog *prog;
 };
@@ -171,10 +175,15 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
 /**
  * seccomp_run_filters - evaluates all seccomp filters against @sd
  * @sd: optional seccomp data to be passed to filters
+ * @match: stores struct seccomp_filter that resulted in the return value,
+ *         unless filter returned SECCOMP_RET_ALLOW, in which case it will
+ *         be unchanged.
  *
  * Returns valid seccomp BPF response codes.
  */
-static u32 seccomp_run_filters(const struct seccomp_data *sd)
+#define ACTION_ONLY(ret) ((s32)((ret) & (SECCOMP_RET_ACTION_FULL)))
+static u32 seccomp_run_filters(const struct seccomp_data *sd,
+                              struct seccomp_filter **match)
 {
        struct seccomp_data sd_local;
        u32 ret = SECCOMP_RET_ALLOW;
@@ -184,7 +193,7 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd)
 
        /* Ensure unexpected behavior doesn't result in failing open. */
        if (unlikely(WARN_ON(f == NULL)))
-               return SECCOMP_RET_KILL;
+               return SECCOMP_RET_KILL_PROCESS;
 
        if (!sd) {
                populate_seccomp_data(&sd_local);
@@ -198,8 +207,10 @@ static u32 seccomp_run_filters(const struct seccomp_data *sd)
        for (; f; f = f->prev) {
                u32 cur_ret = BPF_PROG_RUN(f->prog, sd);
 
-               if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION))
+               if (ACTION_ONLY(cur_ret) < ACTION_ONLY(ret)) {
                        ret = cur_ret;
+                       *match = f;
+               }
        }
        return ret;
 }
@@ -444,6 +455,10 @@ static long seccomp_attach_filter(unsigned int flags,
                        return ret;
        }
 
+       /* Set log flag, if present. */
+       if (flags & SECCOMP_FILTER_FLAG_LOG)
+               filter->log = true;
+
        /*
         * If there is an existing filter, make it the prev and don't drop its
         * task reference.
@@ -458,14 +473,19 @@ static long seccomp_attach_filter(unsigned int flags,
        return 0;
 }
 
+void __get_seccomp_filter(struct seccomp_filter *filter)
+{
+       /* Reference count is bounded by the number of total processes. */
+       refcount_inc(&filter->usage);
+}
+
 /* get_seccomp_filter - increments the reference count of the filter on @tsk */
 void get_seccomp_filter(struct task_struct *tsk)
 {
        struct seccomp_filter *orig = tsk->seccomp.filter;
        if (!orig)
                return;
-       /* Reference count is bounded by the number of total processes. */
-       refcount_inc(&orig->usage);
+       __get_seccomp_filter(orig);
 }
 
 static inline void seccomp_filter_free(struct seccomp_filter *filter)
@@ -476,10 +496,8 @@ static inline void seccomp_filter_free(struct seccomp_filter *filter)
        }
 }
 
-/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */
-void put_seccomp_filter(struct task_struct *tsk)
+static void __put_seccomp_filter(struct seccomp_filter *orig)
 {
-       struct seccomp_filter *orig = tsk->seccomp.filter;
        /* Clean up single-reference branches iteratively. */
        while (orig && refcount_dec_and_test(&orig->usage)) {
                struct seccomp_filter *freeme = orig;
@@ -488,6 +506,12 @@ void put_seccomp_filter(struct task_struct *tsk)
        }
 }
 
+/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */
+void put_seccomp_filter(struct task_struct *tsk)
+{
+       __put_seccomp_filter(tsk->seccomp.filter);
+}
+
 static void seccomp_init_siginfo(siginfo_t *info, int syscall, int reason)
 {
        memset(info, 0, sizeof(*info));
@@ -514,6 +538,65 @@ static void seccomp_send_sigsys(int syscall, int reason)
 }
 #endif /* CONFIG_SECCOMP_FILTER */
 
+/* For use with seccomp_actions_logged */
+#define SECCOMP_LOG_KILL_PROCESS       (1 << 0)
+#define SECCOMP_LOG_KILL_THREAD                (1 << 1)
+#define SECCOMP_LOG_TRAP               (1 << 2)
+#define SECCOMP_LOG_ERRNO              (1 << 3)
+#define SECCOMP_LOG_TRACE              (1 << 4)
+#define SECCOMP_LOG_LOG                        (1 << 5)
+#define SECCOMP_LOG_ALLOW              (1 << 6)
+
+static u32 seccomp_actions_logged = SECCOMP_LOG_KILL_PROCESS |
+                                   SECCOMP_LOG_KILL_THREAD  |
+                                   SECCOMP_LOG_TRAP  |
+                                   SECCOMP_LOG_ERRNO |
+                                   SECCOMP_LOG_TRACE |
+                                   SECCOMP_LOG_LOG;
+
+static inline void seccomp_log(unsigned long syscall, long signr, u32 action,
+                              bool requested)
+{
+       bool log = false;
+
+       switch (action) {
+       case SECCOMP_RET_ALLOW:
+               break;
+       case SECCOMP_RET_TRAP:
+               log = requested && seccomp_actions_logged & SECCOMP_LOG_TRAP;
+               break;
+       case SECCOMP_RET_ERRNO:
+               log = requested && seccomp_actions_logged & SECCOMP_LOG_ERRNO;
+               break;
+       case SECCOMP_RET_TRACE:
+               log = requested && seccomp_actions_logged & SECCOMP_LOG_TRACE;
+               break;
+       case SECCOMP_RET_LOG:
+               log = seccomp_actions_logged & SECCOMP_LOG_LOG;
+               break;
+       case SECCOMP_RET_KILL_THREAD:
+               log = seccomp_actions_logged & SECCOMP_LOG_KILL_THREAD;
+               break;
+       case SECCOMP_RET_KILL_PROCESS:
+       default:
+               log = seccomp_actions_logged & SECCOMP_LOG_KILL_PROCESS;
+       }
+
+       /*
+        * Force an audit message to be emitted when the action is RET_KILL_*,
+        * RET_LOG, or the FILTER_FLAG_LOG bit was set and the action is
+        * allowed to be logged by the admin.
+        */
+       if (log)
+               return __audit_seccomp(syscall, signr, action);
+
+       /*
+        * Let the audit subsystem decide if the action should be audited based
+        * on whether the current task itself is being audited.
+        */
+       return audit_seccomp(syscall, signr, action);
+}
+
 /*
  * Secure computing mode 1 allows only read/write/exit/sigreturn.
  * To be fully secure this must be combined with rlimit
@@ -539,7 +622,7 @@ static void __secure_computing_strict(int this_syscall)
 #ifdef SECCOMP_DEBUG
        dump_stack();
 #endif
-       audit_seccomp(this_syscall, SIGKILL, SECCOMP_RET_KILL);
+       seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL_THREAD, true);
        do_exit(SIGKILL);
 }
 
@@ -566,6 +649,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
                            const bool recheck_after_trace)
 {
        u32 filter_ret, action;
+       struct seccomp_filter *match = NULL;
        int data;
 
        /*
@@ -574,9 +658,9 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
         */
        rmb();
 
-       filter_ret = seccomp_run_filters(sd);
+       filter_ret = seccomp_run_filters(sd, &match);
        data = filter_ret & SECCOMP_RET_DATA;
-       action = filter_ret & SECCOMP_RET_ACTION;
+       action = filter_ret & SECCOMP_RET_ACTION_FULL;
 
        switch (action) {
        case SECCOMP_RET_ERRNO:
@@ -637,14 +721,25 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
 
                return 0;
 
+       case SECCOMP_RET_LOG:
+               seccomp_log(this_syscall, 0, action, true);
+               return 0;
+
        case SECCOMP_RET_ALLOW:
+               /*
+                * Note that the "match" filter will always be NULL for
+                * this action since SECCOMP_RET_ALLOW is the starting
+                * state in seccomp_run_filters().
+                */
                return 0;
 
-       case SECCOMP_RET_KILL:
+       case SECCOMP_RET_KILL_THREAD:
+       case SECCOMP_RET_KILL_PROCESS:
        default:
-               audit_seccomp(this_syscall, SIGSYS, action);
+               seccomp_log(this_syscall, SIGSYS, action, true);
                /* Dump core only if this is the last remaining thread. */
-               if (get_nr_threads(current) == 1) {
+               if (action == SECCOMP_RET_KILL_PROCESS ||
+                   get_nr_threads(current) == 1) {
                        siginfo_t info;
 
                        /* Show the original registers in the dump. */
@@ -653,13 +748,16 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
                        seccomp_init_siginfo(&info, this_syscall, data);
                        do_coredump(&info);
                }
-               do_exit(SIGSYS);
+               if (action == SECCOMP_RET_KILL_PROCESS)
+                       do_group_exit(SIGSYS);
+               else
+                       do_exit(SIGSYS);
        }
 
        unreachable();
 
 skip:
-       audit_seccomp(this_syscall, 0, action);
+       seccomp_log(this_syscall, 0, action, match ? match->log : false);
        return -1;
 }
 #else
@@ -794,6 +892,29 @@ static inline long seccomp_set_mode_filter(unsigned int flags,
 }
 #endif
 
+static long seccomp_get_action_avail(const char __user *uaction)
+{
+       u32 action;
+
+       if (copy_from_user(&action, uaction, sizeof(action)))
+               return -EFAULT;
+
+       switch (action) {
+       case SECCOMP_RET_KILL_PROCESS:
+       case SECCOMP_RET_KILL_THREAD:
+       case SECCOMP_RET_TRAP:
+       case SECCOMP_RET_ERRNO:
+       case SECCOMP_RET_TRACE:
+       case SECCOMP_RET_LOG:
+       case SECCOMP_RET_ALLOW:
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 /* Common entry point for both prctl and syscall. */
 static long do_seccomp(unsigned int op, unsigned int flags,
                       const char __user *uargs)
@@ -805,6 +926,11 @@ static long do_seccomp(unsigned int op, unsigned int flags,
                return seccomp_set_mode_strict();
        case SECCOMP_SET_MODE_FILTER:
                return seccomp_set_mode_filter(flags, uargs);
+       case SECCOMP_GET_ACTION_AVAIL:
+               if (flags != 0)
+                       return -EINVAL;
+
+               return seccomp_get_action_avail(uargs);
        default:
                return -EINVAL;
        }
@@ -908,13 +1034,13 @@ long seccomp_get_filter(struct task_struct *task, unsigned long filter_off,
        if (!data)
                goto out;
 
-       get_seccomp_filter(task);
+       __get_seccomp_filter(filter);
        spin_unlock_irq(&task->sighand->siglock);
 
        if (copy_to_user(data, fprog->filter, bpf_classic_proglen(fprog)))
                ret = -EFAULT;
 
-       put_seccomp_filter(task);
+       __put_seccomp_filter(filter);
        return ret;
 
 out:
@@ -922,3 +1048,185 @@ out:
        return ret;
 }
 #endif
+
+#ifdef CONFIG_SYSCTL
+
+/* Human readable action names for friendly sysctl interaction */
+#define SECCOMP_RET_KILL_PROCESS_NAME  "kill_process"
+#define SECCOMP_RET_KILL_THREAD_NAME   "kill_thread"
+#define SECCOMP_RET_TRAP_NAME          "trap"
+#define SECCOMP_RET_ERRNO_NAME         "errno"
+#define SECCOMP_RET_TRACE_NAME         "trace"
+#define SECCOMP_RET_LOG_NAME           "log"
+#define SECCOMP_RET_ALLOW_NAME         "allow"
+
+static const char seccomp_actions_avail[] =
+                               SECCOMP_RET_KILL_PROCESS_NAME   " "
+                               SECCOMP_RET_KILL_THREAD_NAME    " "
+                               SECCOMP_RET_TRAP_NAME           " "
+                               SECCOMP_RET_ERRNO_NAME          " "
+                               SECCOMP_RET_TRACE_NAME          " "
+                               SECCOMP_RET_LOG_NAME            " "
+                               SECCOMP_RET_ALLOW_NAME;
+
+struct seccomp_log_name {
+       u32             log;
+       const char      *name;
+};
+
+static const struct seccomp_log_name seccomp_log_names[] = {
+       { SECCOMP_LOG_KILL_PROCESS, SECCOMP_RET_KILL_PROCESS_NAME },
+       { SECCOMP_LOG_KILL_THREAD, SECCOMP_RET_KILL_THREAD_NAME },
+       { SECCOMP_LOG_TRAP, SECCOMP_RET_TRAP_NAME },
+       { SECCOMP_LOG_ERRNO, SECCOMP_RET_ERRNO_NAME },
+       { SECCOMP_LOG_TRACE, SECCOMP_RET_TRACE_NAME },
+       { SECCOMP_LOG_LOG, SECCOMP_RET_LOG_NAME },
+       { SECCOMP_LOG_ALLOW, SECCOMP_RET_ALLOW_NAME },
+       { }
+};
+
+static bool seccomp_names_from_actions_logged(char *names, size_t size,
+                                             u32 actions_logged)
+{
+       const struct seccomp_log_name *cur;
+       bool append_space = false;
+
+       for (cur = seccomp_log_names; cur->name && size; cur++) {
+               ssize_t ret;
+
+               if (!(actions_logged & cur->log))
+                       continue;
+
+               if (append_space) {
+                       ret = strscpy(names, " ", size);
+                       if (ret < 0)
+                               return false;
+
+                       names += ret;
+                       size -= ret;
+               } else
+                       append_space = true;
+
+               ret = strscpy(names, cur->name, size);
+               if (ret < 0)
+                       return false;
+
+               names += ret;
+               size -= ret;
+       }
+
+       return true;
+}
+
+static bool seccomp_action_logged_from_name(u32 *action_logged,
+                                           const char *name)
+{
+       const struct seccomp_log_name *cur;
+
+       for (cur = seccomp_log_names; cur->name; cur++) {
+               if (!strcmp(cur->name, name)) {
+                       *action_logged = cur->log;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static bool seccomp_actions_logged_from_names(u32 *actions_logged, char *names)
+{
+       char *name;
+
+       *actions_logged = 0;
+       while ((name = strsep(&names, " ")) && *name) {
+               u32 action_logged = 0;
+
+               if (!seccomp_action_logged_from_name(&action_logged, name))
+                       return false;
+
+               *actions_logged |= action_logged;
+       }
+
+       return true;
+}
+
+static int seccomp_actions_logged_handler(struct ctl_table *ro_table, int write,
+                                         void __user *buffer, size_t *lenp,
+                                         loff_t *ppos)
+{
+       char names[sizeof(seccomp_actions_avail)];
+       struct ctl_table table;
+       int ret;
+
+       if (write && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       memset(names, 0, sizeof(names));
+
+       if (!write) {
+               if (!seccomp_names_from_actions_logged(names, sizeof(names),
+                                                      seccomp_actions_logged))
+                       return -EINVAL;
+       }
+
+       table = *ro_table;
+       table.data = names;
+       table.maxlen = sizeof(names);
+       ret = proc_dostring(&table, write, buffer, lenp, ppos);
+       if (ret)
+               return ret;
+
+       if (write) {
+               u32 actions_logged;
+
+               if (!seccomp_actions_logged_from_names(&actions_logged,
+                                                      table.data))
+                       return -EINVAL;
+
+               if (actions_logged & SECCOMP_LOG_ALLOW)
+                       return -EINVAL;
+
+               seccomp_actions_logged = actions_logged;
+       }
+
+       return 0;
+}
+
+static struct ctl_path seccomp_sysctl_path[] = {
+       { .procname = "kernel", },
+       { .procname = "seccomp", },
+       { }
+};
+
+static struct ctl_table seccomp_sysctl_table[] = {
+       {
+               .procname       = "actions_avail",
+               .data           = (void *) &seccomp_actions_avail,
+               .maxlen         = sizeof(seccomp_actions_avail),
+               .mode           = 0444,
+               .proc_handler   = proc_dostring,
+       },
+       {
+               .procname       = "actions_logged",
+               .mode           = 0644,
+               .proc_handler   = seccomp_actions_logged_handler,
+       },
+       { }
+};
+
+static int __init seccomp_sysctl_init(void)
+{
+       struct ctl_table_header *hdr;
+
+       hdr = register_sysctl_paths(seccomp_sysctl_path, seccomp_sysctl_table);
+       if (!hdr)
+               pr_warn("seccomp: sysctl registration failed\n");
+       else
+               kmemleak_not_leak(hdr);
+
+       return 0;
+}
+
+device_initcall(seccomp_sysctl_init)
+
+#endif /* CONFIG_SYSCTL */
index 6648fbbb8157fc12703d02fa0fdc9ff85c527ac4..423554ad361020b389b8f9fc296884ae64f74493 100644 (file)
@@ -367,7 +367,8 @@ static struct ctl_table kern_table[] = {
                .data           = &sysctl_sched_time_avg,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &one,
        },
 #ifdef CONFIG_SCHEDSTATS
        {
index 2a685b45b73be4159bd310d8c4530a87df9e4cec..45a3928544ce599183c415471f4624be0583ea40 100644 (file)
@@ -648,6 +648,12 @@ int blk_trace_startstop(struct request_queue *q, int start)
 }
 EXPORT_SYMBOL_GPL(blk_trace_startstop);
 
+/*
+ * When reading or writing the blktrace sysfs files, the references to the
+ * opened sysfs or device files should prevent the underlying block device
+ * from being removed. So no further delete protection is really needed.
+ */
+
 /**
  * blk_trace_ioctl: - handle the ioctls associated with tracing
  * @bdev:      the block device
@@ -665,7 +671,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
        if (!q)
                return -ENXIO;
 
-       mutex_lock(&bdev->bd_mutex);
+       mutex_lock(&q->blk_trace_mutex);
 
        switch (cmd) {
        case BLKTRACESETUP:
@@ -691,7 +697,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
                break;
        }
 
-       mutex_unlock(&bdev->bd_mutex);
+       mutex_unlock(&q->blk_trace_mutex);
        return ret;
 }
 
@@ -1727,7 +1733,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
        if (q == NULL)
                goto out_bdput;
 
-       mutex_lock(&bdev->bd_mutex);
+       mutex_lock(&q->blk_trace_mutex);
 
        if (attr == &dev_attr_enable) {
                ret = sprintf(buf, "%u\n", !!q->blk_trace);
@@ -1746,7 +1752,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
                ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba);
 
 out_unlock_bdev:
-       mutex_unlock(&bdev->bd_mutex);
+       mutex_unlock(&q->blk_trace_mutex);
 out_bdput:
        bdput(bdev);
 out:
@@ -1788,7 +1794,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
        if (q == NULL)
                goto out_bdput;
 
-       mutex_lock(&bdev->bd_mutex);
+       mutex_lock(&q->blk_trace_mutex);
 
        if (attr == &dev_attr_enable) {
                if (value)
@@ -1814,7 +1820,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
        }
 
 out_unlock_bdev:
-       mutex_unlock(&bdev->bd_mutex);
+       mutex_unlock(&q->blk_trace_mutex);
 out_bdput:
        bdput(bdev);
 out:
index 5360b7aec57ac1ccd1eea33b090f67ccb4b4e8cf..752e5daf0896fc529876f8801a95e23118713338 100644 (file)
@@ -4020,11 +4020,17 @@ static int tracing_open(struct inode *inode, struct file *file)
        /* If this file was open for write, then erase contents */
        if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
                int cpu = tracing_get_cpu(inode);
+               struct trace_buffer *trace_buf = &tr->trace_buffer;
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+               if (tr->current_trace->print_max)
+                       trace_buf = &tr->max_buffer;
+#endif
 
                if (cpu == RING_BUFFER_ALL_CPUS)
-                       tracing_reset_online_cpus(&tr->trace_buffer);
+                       tracing_reset_online_cpus(trace_buf);
                else
-                       tracing_reset(&tr->trace_buffer, cpu);
+                       tracing_reset(trace_buf, cpu);
        }
 
        if (file->f_mode & FMODE_READ) {
@@ -5358,6 +5364,13 @@ static int tracing_set_tracer(struct trace_array *tr, const char *buf)
        if (t == tr->current_trace)
                goto out;
 
+       /* Some tracers won't work on kernel command line */
+       if (system_state < SYSTEM_RUNNING && t->noboot) {
+               pr_warn("Tracer '%s' is not allowed on command line, ignored\n",
+                       t->name);
+               goto out;
+       }
+
        /* Some tracers are only allowed for the top level buffer */
        if (!trace_ok_for_array(t, tr)) {
                ret = -EINVAL;
@@ -5667,7 +5680,7 @@ static int tracing_wait_pipe(struct file *filp)
                 *
                 * iter->pos will be 0 if we haven't read anything.
                 */
-               if (!tracing_is_on() && iter->pos)
+               if (!tracer_tracing_is_on(iter->tr) && iter->pos)
                        break;
 
                mutex_unlock(&iter->mutex);
index fb5d54d0d1b3f297087e96f03a22003fc887d359..652c682707cdd4f489a00c3b14df0b97ae8d2425 100644 (file)
@@ -444,6 +444,8 @@ struct tracer {
 #ifdef CONFIG_TRACER_MAX_TRACE
        bool                    use_max_tr;
 #endif
+       /* True if tracer cannot be enabled in kernel param */
+       bool                    noboot;
 };
 
 
index cd7480d0a201e335cd7adc20c9cb0a8dba16f189..dca78fc48439d21a80cd6576269eded8bfe13623 100644 (file)
@@ -282,6 +282,7 @@ static struct tracer mmio_tracer __read_mostly =
        .close          = mmio_close,
        .read           = mmio_read,
        .print_line     = mmio_print_line,
+       .noboot         = true,
 };
 
 __init static int init_mmio_trace(void)
index bac629af2285748bbdac64b6b5c632f2fcaed49d..c738e764e2a55cfd3303a3262d748c94a917a86d 100644 (file)
@@ -656,15 +656,6 @@ int trace_print_lat_context(struct trace_iterator *iter)
        return !trace_seq_has_overflowed(s);
 }
 
-static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
-
-static int task_state_char(unsigned long state)
-{
-       int bit = state ? __ffs(state) + 1 : 0;
-
-       return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
-}
-
 /**
  * ftrace_find_event - find a registered event
  * @type: the type of event to look for
@@ -930,8 +921,8 @@ static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,
 
        trace_assign_type(field, iter->ent);
 
-       T = task_state_char(field->next_state);
-       S = task_state_char(field->prev_state);
+       T = __task_state_to_char(field->next_state);
+       S = __task_state_to_char(field->prev_state);
        trace_find_cmdline(field->next_pid, comm);
        trace_seq_printf(&iter->seq,
                         " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
@@ -966,8 +957,8 @@ static int trace_ctxwake_raw(struct trace_iterator *iter, char S)
        trace_assign_type(field, iter->ent);
 
        if (!S)
-               S = task_state_char(field->prev_state);
-       T = task_state_char(field->next_state);
+               S = __task_state_to_char(field->prev_state);
+       T = __task_state_to_char(field->next_state);
        trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n",
                         field->prev_pid,
                         field->prev_prio,
@@ -1002,8 +993,8 @@ static int trace_ctxwake_hex(struct trace_iterator *iter, char S)
        trace_assign_type(field, iter->ent);
 
        if (!S)
-               S = task_state_char(field->prev_state);
-       T = task_state_char(field->next_state);
+               S = __task_state_to_char(field->prev_state);
+       T = __task_state_to_char(field->next_state);
 
        SEQ_PUT_HEX_FIELD(s, field->prev_pid);
        SEQ_PUT_HEX_FIELD(s, field->prev_prio);
index ddec53b6764617e8fe431d93bf9f970a5015b4be..0c331978b1a636e9f2736f77bd93e97415c1ca10 100644 (file)
@@ -397,10 +397,10 @@ tracing_sched_switch_trace(struct trace_array *tr,
        entry   = ring_buffer_event_data(event);
        entry->prev_pid                 = prev->pid;
        entry->prev_prio                = prev->prio;
-       entry->prev_state               = prev->state;
+       entry->prev_state               = __get_task_state(prev);
        entry->next_pid                 = next->pid;
        entry->next_prio                = next->prio;
-       entry->next_state               = next->state;
+       entry->next_state               = __get_task_state(next);
        entry->next_cpu = task_cpu(next);
 
        if (!call_filter_check_discard(call, entry, buffer, event))
@@ -425,10 +425,10 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
        entry   = ring_buffer_event_data(event);
        entry->prev_pid                 = curr->pid;
        entry->prev_prio                = curr->prio;
-       entry->prev_state               = curr->state;
+       entry->prev_state               = __get_task_state(curr);
        entry->next_pid                 = wakee->pid;
        entry->next_prio                = wakee->prio;
-       entry->next_state               = wakee->state;
+       entry->next_state               = __get_task_state(wakee);
        entry->next_cpu                 = task_cpu(wakee);
 
        if (!call_filter_check_discard(call, entry, buffer, event))
index a4df67cbc711459df2aa8b4a313eb449a472ee45..49cb41412eece8bb7dff9bedf5fd7991ade07b76 100644 (file)
@@ -96,23 +96,9 @@ check_stack(unsigned long ip, unsigned long *stack)
        if (in_nmi())
                return;
 
-       /*
-        * There's a slight chance that we are tracing inside the
-        * RCU infrastructure, and rcu_irq_enter() will not work
-        * as expected.
-        */
-       if (unlikely(rcu_irq_enter_disabled()))
-               return;
-
        local_irq_save(flags);
        arch_spin_lock(&stack_trace_max_lock);
 
-       /*
-        * RCU may not be watching, make it see us.
-        * The stack trace code uses rcu_sched.
-        */
-       rcu_irq_enter();
-
        /* In case another CPU set the tracer_frame on us */
        if (unlikely(!frame_size))
                this_size -= tracer_frame;
@@ -205,7 +191,6 @@ check_stack(unsigned long ip, unsigned long *stack)
        }
 
  out:
-       rcu_irq_exit();
        arch_spin_unlock(&stack_trace_max_lock);
        local_irq_restore(flags);
 }
index b19c491cbc4e7934ab5bc78549c95423b91b2f7a..2689b7c50c52992623cc8d7e65df03bffc8798d3 100644 (file)
@@ -219,7 +219,8 @@ config FRAME_WARN
        range 0 8192
        default 0 if KASAN
        default 2048 if GCC_PLUGIN_LATENT_ENTROPY
-       default 1024 if !64BIT
+       default 1280 if (!64BIT && PARISC)
+       default 1024 if (!64BIT && !PARISC)
        default 2048 if 64BIT
        help
          Tell gcc to warn at build time for stack frames larger than this.
index 52c8dd6d8e8290fa8df614e0017542a600b9c536..1c1c06ddc20a8a961d7d9f73e43d65b695636d5d 100644 (file)
@@ -687,8 +687,10 @@ EXPORT_SYMBOL(_copy_from_iter_full_nocache);
 
 static inline bool page_copy_sane(struct page *page, size_t offset, size_t n)
 {
-       size_t v = n + offset;
-       if (likely(n <= v && v <= (PAGE_SIZE << compound_order(page))))
+       struct page *head = compound_head(page);
+       size_t v = n + offset + page_address(page) - page_address(head);
+
+       if (likely(n <= v && v <= (PAGE_SIZE << compound_order(head))))
                return true;
        WARN_ON(1);
        return false;
index 707ca5d677c676a599442604d918c215d7709138..ddd7dde87c3ca0db910d67a567f2a68c8d8e847e 100644 (file)
@@ -735,9 +735,9 @@ EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
  * rhashtable_walk_start - Start a hash table walk
  * @iter:      Hash table iterator
  *
- * Start a hash table walk.  Note that we take the RCU lock in all
- * cases including when we return an error.  So you must always call
- * rhashtable_walk_stop to clean up.
+ * Start a hash table walk at the current iterator position.  Note that we take
+ * the RCU lock in all cases including when we return an error.  So you must
+ * always call rhashtable_walk_stop to clean up.
  *
  * Returns zero if successful.
  *
@@ -846,7 +846,8 @@ EXPORT_SYMBOL_GPL(rhashtable_walk_next);
  * rhashtable_walk_stop - Finish a hash table walk
  * @iter:      Hash table iterator
  *
- * Finish a hash table walk.
+ * Finish a hash table walk.  Does not reset the iterator to the start of the
+ * hash table.
  */
 void rhashtable_walk_stop(struct rhashtable_iter *iter)
        __releases(RCU)
index 870971e209670c99a335bc05903f7f12326b9882..db250d0e05655a2e4b72e4f7a7834964a641c86d 100644 (file)
@@ -2926,9 +2926,15 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
         * we're writing.  Either one is a pretty crazy thing to do,
         * so we don't support it 100%.  If this invalidation
         * fails, tough, the write still worked...
+        *
+        * Most of the time we do not need this since dio_complete() will do
+        * the invalidation for us. However there are some file systems that
+        * do not end up with dio_complete() being called, so let's not break
+        * them by removing it completely
         */
-       invalidate_inode_pages2_range(mapping,
-                               pos >> PAGE_SHIFT, end);
+       if (mapping->nrpages)
+               invalidate_inode_pages2_range(mapping,
+                                       pos >> PAGE_SHIFT, end);
 
        if (written > 0) {
                pos += written;
index c18115d22f00be37f68d9bbdbb04f626de6cf3c4..db82a40875e8da3c9ad39881046d27bd8f0ee596 100644 (file)
@@ -126,14 +126,4 @@ config BT_DEBUGFS
          Provide extensive information about internal Bluetooth states
          in debugfs.
 
-config BT_LEGACY_IOCTL
-       bool "Enable legacy ioctl interfaces"
-       depends on BT && BT_BREDR
-       default y
-       help
-         Enable support for legacy ioctl interfaces.  This is only needed
-         for old and deprecated applications using direct ioctl calls for
-         controller management.  Since Linux 3.4 all configuration and
-         setup is done via mgmt interface and this is no longer needed.
-
 source "drivers/bluetooth/Kconfig"
index 0bad296fe0af970f5989b8a121039b99863088b9..65d734c165bd6368b8607d0b5078d345b5e642a8 100644 (file)
@@ -878,7 +878,6 @@ static int hci_sock_release(struct socket *sock)
        return 0;
 }
 
-#ifdef CONFIG_BT_LEGACY_IOCTL
 static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
 {
        bdaddr_t bdaddr;
@@ -1050,7 +1049,6 @@ done:
        release_sock(sk);
        return err;
 }
-#endif
 
 static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
                         int addr_len)
@@ -1971,11 +1969,7 @@ static const struct proto_ops hci_sock_ops = {
        .getname        = hci_sock_getname,
        .sendmsg        = hci_sock_sendmsg,
        .recvmsg        = hci_sock_recvmsg,
-#ifdef CONFIG_BT_LEGACY_IOCTL
        .ioctl          = hci_sock_ioctl,
-#else
-       .ioctl          = sock_no_ioctl,
-#endif
        .poll           = datagram_poll,
        .listen         = sock_no_listen,
        .shutdown       = sock_no_shutdown,
index f358d0bfa76b35cb978e9e92b57aea38a4e3b391..79d14d70b7ea7e032ecffec839b2f44ee4fe7cdc 100644 (file)
@@ -2445,19 +2445,34 @@ static void apply_upmap(struct ceph_osdmap *osdmap,
 
        pg = lookup_pg_mapping(&osdmap->pg_upmap_items, pgid);
        if (pg) {
-               for (i = 0; i < raw->size; i++) {
-                       for (j = 0; j < pg->pg_upmap_items.len; j++) {
-                               int from = pg->pg_upmap_items.from_to[j][0];
-                               int to = pg->pg_upmap_items.from_to[j][1];
-
-                               if (from == raw->osds[i]) {
-                                       if (!(to != CRUSH_ITEM_NONE &&
-                                             to < osdmap->max_osd &&
-                                             osdmap->osd_weight[to] == 0))
-                                               raw->osds[i] = to;
+               /*
+                * Note: this approach does not allow a bidirectional swap,
+                * e.g., [[1,2],[2,1]] applied to [0,1,2] -> [0,2,1].
+                */
+               for (i = 0; i < pg->pg_upmap_items.len; i++) {
+                       int from = pg->pg_upmap_items.from_to[i][0];
+                       int to = pg->pg_upmap_items.from_to[i][1];
+                       int pos = -1;
+                       bool exists = false;
+
+                       /* make sure replacement doesn't already appear */
+                       for (j = 0; j < raw->size; j++) {
+                               int osd = raw->osds[j];
+
+                               if (osd == to) {
+                                       exists = true;
                                        break;
                                }
+                               /* ignore mapping if target is marked out */
+                               if (osd == from && pos < 0 &&
+                                   !(to != CRUSH_ITEM_NONE &&
+                                     to < osdmap->max_osd &&
+                                     osdmap->osd_weight[to] == 0)) {
+                                       pos = j;
+                               }
                        }
+                       if (!exists && pos >= 0)
+                               raw->osds[pos] = to;
                }
        }
 }
index 6ded6c821d7a21f296d14db02552ea1c71643051..22381719718c4fbd5d63b8836e3161026b59a459 100644 (file)
@@ -185,6 +185,13 @@ int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
                ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
        }
 
+       /*
+        * check the length of messages copied in is the same as the
+        * what we get from the first loop
+        */
+       if ((char *)kcmsg - (char *)kcmsg_base != kcmlen)
+               goto Einval;
+
        /* Ok, looks like we made it.  Hook it up and return success. */
        kmsg->msg_control = kcmsg_base;
        kmsg->msg_controllen = kcmlen;
index fb766d906148e7d1e85a654eaf6048c1cdf49364..588b473194a8a8ce23bde368b2b0350a3317db8b 100644 (file)
@@ -1948,8 +1948,12 @@ again:
                goto again;
        }
 out_unlock:
-       if (pt_prev)
-               pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);
+       if (pt_prev) {
+               if (!skb_orphan_frags_rx(skb2, GFP_ATOMIC))
+                       pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);
+               else
+                       kfree_skb(skb2);
+       }
        rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(dev_queue_xmit_nit);
@@ -3892,6 +3896,7 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
                __skb_pull(skb, off);
        else if (off < 0)
                __skb_push(skb, -off);
+       skb->mac_header += off;
 
        switch (act) {
        case XDP_REDIRECT:
index 6a582ae4c5d972360736a966f02729bf22a64599..3228411ada0fa77e2796b733a695826282d82df9 100644 (file)
@@ -525,6 +525,8 @@ convert_link_ksettings_to_legacy_settings(
                = link_ksettings->base.eth_tp_mdix;
        legacy_settings->eth_tp_mdix_ctrl
                = link_ksettings->base.eth_tp_mdix_ctrl;
+       legacy_settings->transceiver
+               = link_ksettings->base.transceiver;
        return retval;
 }
 
index 24dd33dd9f0452994623e26e3a379f0bf56190ce..82edad58d066857aeee562661098effa3b3e6961 100644 (file)
@@ -1794,7 +1794,7 @@ struct redirect_info {
        u32 flags;
        struct bpf_map *map;
        struct bpf_map *map_to_flush;
-       const struct bpf_prog *map_owner;
+       unsigned long   map_owner;
 };
 
 static DEFINE_PER_CPU(struct redirect_info, redirect_info);
@@ -2500,11 +2500,17 @@ void xdp_do_flush_map(void)
 }
 EXPORT_SYMBOL_GPL(xdp_do_flush_map);
 
+static inline bool xdp_map_invalid(const struct bpf_prog *xdp_prog,
+                                  unsigned long aux)
+{
+       return (unsigned long)xdp_prog->aux != aux;
+}
+
 static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
                               struct bpf_prog *xdp_prog)
 {
        struct redirect_info *ri = this_cpu_ptr(&redirect_info);
-       const struct bpf_prog *map_owner = ri->map_owner;
+       unsigned long map_owner = ri->map_owner;
        struct bpf_map *map = ri->map;
        struct net_device *fwd = NULL;
        u32 index = ri->ifindex;
@@ -2512,9 +2518,9 @@ static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
 
        ri->ifindex = 0;
        ri->map = NULL;
-       ri->map_owner = NULL;
+       ri->map_owner = 0;
 
-       if (unlikely(map_owner != xdp_prog)) {
+       if (unlikely(xdp_map_invalid(xdp_prog, map_owner))) {
                err = -EFAULT;
                map = NULL;
                goto err;
@@ -2574,7 +2580,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
                            struct bpf_prog *xdp_prog)
 {
        struct redirect_info *ri = this_cpu_ptr(&redirect_info);
-       const struct bpf_prog *map_owner = ri->map_owner;
+       unsigned long map_owner = ri->map_owner;
        struct bpf_map *map = ri->map;
        struct net_device *fwd = NULL;
        u32 index = ri->ifindex;
@@ -2583,10 +2589,10 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
 
        ri->ifindex = 0;
        ri->map = NULL;
-       ri->map_owner = NULL;
+       ri->map_owner = 0;
 
        if (map) {
-               if (unlikely(map_owner != xdp_prog)) {
+               if (unlikely(xdp_map_invalid(xdp_prog, map_owner))) {
                        err = -EFAULT;
                        map = NULL;
                        goto err;
@@ -2632,7 +2638,7 @@ BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
        ri->ifindex = ifindex;
        ri->flags = flags;
        ri->map = NULL;
-       ri->map_owner = NULL;
+       ri->map_owner = 0;
 
        return XDP_REDIRECT;
 }
@@ -2646,7 +2652,7 @@ static const struct bpf_func_proto bpf_xdp_redirect_proto = {
 };
 
 BPF_CALL_4(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, u64, flags,
-          const struct bpf_prog *, map_owner)
+          unsigned long, map_owner)
 {
        struct redirect_info *ri = this_cpu_ptr(&redirect_info);
 
index b9c64b40a83af1e151f553ba0e624fae5060ffd0..c039c937ba90c7aec39ba2687bceb8253ead70aa 100644 (file)
@@ -266,7 +266,7 @@ static inline int sk_reuseport_match(struct inet_bind_bucket *tb,
 #if IS_ENABLED(CONFIG_IPV6)
        if (tb->fast_sk_family == AF_INET6)
                return ipv6_rcv_saddr_equal(&tb->fast_v6_rcv_saddr,
-                                           &sk->sk_v6_rcv_saddr,
+                                           inet6_rcv_saddr(sk),
                                            tb->fast_rcv_saddr,
                                            sk->sk_rcv_saddr,
                                            tb->fast_ipv6_only,
@@ -321,13 +321,14 @@ tb_found:
                        goto fail_unlock;
        }
 success:
-       if (!hlist_empty(&tb->owners)) {
+       if (hlist_empty(&tb->owners)) {
                tb->fastreuse = reuse;
                if (sk->sk_reuseport) {
                        tb->fastreuseport = FASTREUSEPORT_ANY;
                        tb->fastuid = uid;
                        tb->fast_rcv_saddr = sk->sk_rcv_saddr;
                        tb->fast_ipv6_only = ipv6_only_sock(sk);
+                       tb->fast_sk_family = sk->sk_family;
 #if IS_ENABLED(CONFIG_IPV6)
                        tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
 #endif
@@ -354,6 +355,7 @@ success:
                                tb->fastuid = uid;
                                tb->fast_rcv_saddr = sk->sk_rcv_saddr;
                                tb->fast_ipv6_only = ipv6_only_sock(sk);
+                               tb->fast_sk_family = sk->sk_family;
 #if IS_ENABLED(CONFIG_IPV6)
                                tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
 #endif
index 1c839c99114cd22bbfbd181cf702acccb3aeb61b..0bc9e46a53696578eb6e911f2f75e6b34c80894f 100644 (file)
@@ -1806,40 +1806,6 @@ static bool tcp_snd_wnd_test(const struct tcp_sock *tp,
        return !after(end_seq, tcp_wnd_end(tp));
 }
 
-/* This checks if the data bearing packet SKB (usually tcp_send_head(sk))
- * should be put on the wire right now.  If so, it returns the number of
- * packets allowed by the congestion window.
- */
-static unsigned int tcp_snd_test(const struct sock *sk, struct sk_buff *skb,
-                                unsigned int cur_mss, int nonagle)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       unsigned int cwnd_quota;
-
-       tcp_init_tso_segs(skb, cur_mss);
-
-       if (!tcp_nagle_test(tp, skb, cur_mss, nonagle))
-               return 0;
-
-       cwnd_quota = tcp_cwnd_test(tp, skb);
-       if (cwnd_quota && !tcp_snd_wnd_test(tp, skb, cur_mss))
-               cwnd_quota = 0;
-
-       return cwnd_quota;
-}
-
-/* Test if sending is allowed right now. */
-bool tcp_may_send_now(struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       struct sk_buff *skb = tcp_send_head(sk);
-
-       return skb &&
-               tcp_snd_test(sk, skb, tcp_current_mss(sk),
-                            (tcp_skb_is_last(sk, skb) ?
-                             tp->nonagle : TCP_NAGLE_PUSH));
-}
-
 /* Trim TSO SKB to LEN bytes, put the remaining data into a new packet
  * which is put after SKB on the list.  It is very much like
  * tcp_fragment() except that it may make several kinds of assumptions
@@ -3423,6 +3389,10 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
                goto done;
        }
 
+       /* data was not sent, this is our new send_head */
+       sk->sk_send_head = syn_data;
+       tp->packets_out -= tcp_skb_pcount(syn_data);
+
 fallback:
        /* Send a regular SYN with Fast Open cookie request option */
        if (fo->cookie.len > 0)
@@ -3475,6 +3445,11 @@ int tcp_connect(struct sock *sk)
         */
        tp->snd_nxt = tp->write_seq;
        tp->pushed_seq = tp->write_seq;
+       buff = tcp_send_head(sk);
+       if (unlikely(buff)) {
+               tp->snd_nxt     = TCP_SKB_CB(buff)->seq;
+               tp->pushed_seq  = TCP_SKB_CB(buff)->seq;
+       }
        TCP_INC_STATS(sock_net(sk), TCP_MIB_ACTIVEOPENS);
 
        /* Timer for repeating the SYN until an answer. */
index c2e2a78787ec990f4dac2040fb1e26dc150860e2..96861c702c069d67112cace3196e657fbfaabf87 100644 (file)
@@ -1399,10 +1399,18 @@ static inline int ipv6_saddr_preferred(int type)
        return 0;
 }
 
-static inline bool ipv6_use_optimistic_addr(struct inet6_dev *idev)
+static bool ipv6_use_optimistic_addr(struct net *net,
+                                    struct inet6_dev *idev)
 {
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
-       return idev && idev->cnf.optimistic_dad && idev->cnf.use_optimistic;
+       if (!idev)
+               return false;
+       if (!net->ipv6.devconf_all->optimistic_dad && !idev->cnf.optimistic_dad)
+               return false;
+       if (!net->ipv6.devconf_all->use_optimistic && !idev->cnf.use_optimistic)
+               return false;
+
+       return true;
 #else
        return false;
 #endif
@@ -1472,7 +1480,7 @@ static int ipv6_get_saddr_eval(struct net *net,
                /* Rule 3: Avoid deprecated and optimistic addresses */
                u8 avoid = IFA_F_DEPRECATED;
 
-               if (!ipv6_use_optimistic_addr(score->ifa->idev))
+               if (!ipv6_use_optimistic_addr(net, score->ifa->idev))
                        avoid |= IFA_F_OPTIMISTIC;
                ret = ipv6_saddr_preferred(score->addr_type) ||
                      !(score->ifa->flags & avoid);
@@ -2460,7 +2468,8 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
                int max_addresses = in6_dev->cnf.max_addresses;
 
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
-               if (in6_dev->cnf.optimistic_dad &&
+               if ((net->ipv6.devconf_all->optimistic_dad ||
+                    in6_dev->cnf.optimistic_dad) &&
                    !net->ipv6.devconf_all->forwarding && sllao)
                        addr_flags |= IFA_F_OPTIMISTIC;
 #endif
@@ -3051,7 +3060,8 @@ void addrconf_add_linklocal(struct inet6_dev *idev,
        u32 addr_flags = flags | IFA_F_PERMANENT;
 
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
-       if (idev->cnf.optimistic_dad &&
+       if ((dev_net(idev->dev)->ipv6.devconf_all->optimistic_dad ||
+            idev->cnf.optimistic_dad) &&
            !dev_net(idev->dev)->ipv6.devconf_all->forwarding)
                addr_flags |= IFA_F_OPTIMISTIC;
 #endif
@@ -3810,6 +3820,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
                goto out;
 
        if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
+           dev_net(dev)->ipv6.devconf_all->accept_dad < 1 ||
            idev->cnf.accept_dad < 1 ||
            !(ifp->flags&IFA_F_TENTATIVE) ||
            ifp->flags & IFA_F_NODAD) {
@@ -3841,7 +3852,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
         */
        if (ifp->flags & IFA_F_OPTIMISTIC) {
                ip6_ins_rt(ifp->rt);
-               if (ipv6_use_optimistic_addr(idev)) {
+               if (ipv6_use_optimistic_addr(dev_net(dev), idev)) {
                        /* Because optimistic nodes can use this address,
                         * notify listeners. If DAD fails, RTM_DELADDR is sent.
                         */
@@ -3897,7 +3908,9 @@ static void addrconf_dad_work(struct work_struct *w)
                action = DAD_ABORT;
                ifp->state = INET6_IFADDR_STATE_POSTDAD;
 
-               if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6 &&
+               if ((dev_net(idev->dev)->ipv6.devconf_all->accept_dad > 1 ||
+                    idev->cnf.accept_dad > 1) &&
+                   !idev->cnf.disable_ipv6 &&
                    !(ifp->flags & IFA_F_STABLE_PRIVACY)) {
                        struct in6_addr addr;
 
@@ -4940,9 +4953,10 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
 
        /* Don't send DELADDR notification for TENTATIVE address,
         * since NEWADDR notification is sent only after removing
-        * TENTATIVE flag.
+        * TENTATIVE flag, if DAD has not failed.
         */
-       if (ifa->flags & IFA_F_TENTATIVE && event == RTM_DELADDR)
+       if (ifa->flags & IFA_F_TENTATIVE && !(ifa->flags & IFA_F_DADFAILED) &&
+           event == RTM_DELADDR)
                return;
 
        skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
index b7a72d40933441f835708f55e2d8af371661a5fb..20f66f4c94605cc6e79a9843cc692d8b9035cd2f 100644 (file)
@@ -940,24 +940,25 @@ done:
 }
 
 static int ip6gre_header(struct sk_buff *skb, struct net_device *dev,
-                       unsigned short type,
-                       const void *daddr, const void *saddr, unsigned int len)
+                        unsigned short type, const void *daddr,
+                        const void *saddr, unsigned int len)
 {
        struct ip6_tnl *t = netdev_priv(dev);
-       struct ipv6hdr *ipv6h = skb_push(skb, t->hlen);
-       __be16 *p = (__be16 *)(ipv6h+1);
+       struct ipv6hdr *ipv6h;
+       __be16 *p;
 
-       ip6_flow_hdr(ipv6h, 0,
-                    ip6_make_flowlabel(dev_net(dev), skb,
-                                       t->fl.u.ip6.flowlabel, true,
-                                       &t->fl.u.ip6));
+       ipv6h = skb_push(skb, t->hlen + sizeof(*ipv6h));
+       ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb,
+                                                 t->fl.u.ip6.flowlabel,
+                                                 true, &t->fl.u.ip6));
        ipv6h->hop_limit = t->parms.hop_limit;
        ipv6h->nexthdr = NEXTHDR_GRE;
        ipv6h->saddr = t->parms.laddr;
        ipv6h->daddr = t->parms.raddr;
 
-       p[0]            = t->parms.o_flags;
-       p[1]            = htons(type);
+       p = (__be16 *)(ipv6h + 1);
+       p[0] = t->parms.o_flags;
+       p[1] = htons(type);
 
        /*
         *      Set the source hardware address.
index ae73164559d5c4d7f2650ae63c56d76dc93b165c..f2f21c24915f1079939dc2b88546aa0185010239 100644 (file)
@@ -2259,6 +2259,9 @@ static int __init ip6_tunnel_init(void)
 {
        int  err;
 
+       if (!ipv6_mod_enabled())
+               return -EOPNOTSUPP;
+
        err = register_pernet_device(&ip6_tnl_net_ops);
        if (err < 0)
                goto out_pernet;
index e2ecfb137297b931f05eb4d511f8e85cc7633336..40d7234c27b991e54f5cfbacb5d7081e8277ae56 100644 (file)
@@ -1015,6 +1015,7 @@ static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
                 */
                offset = skb_transport_offset(skb);
                skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
+               csum = skb->csum;
 
                skb->ip_summed = CHECKSUM_NONE;
 
index f236c0bc7b3f3e171e4303dd7c5379f34011812f..51063d9ed0f75d53be7a59738bf859570cd67d9b 100644 (file)
@@ -1041,12 +1041,24 @@ out:
 static int
 mtype_head(struct ip_set *set, struct sk_buff *skb)
 {
-       const struct htype *h = set->data;
+       struct htype *h = set->data;
        const struct htable *t;
        struct nlattr *nested;
        size_t memsize;
        u8 htable_bits;
 
+       /* If any members have expired, set->elements will be wrong
+        * mytype_expire function will update it with the right count.
+        * we do not hold set->lock here, so grab it first.
+        * set->elements can still be incorrect in the case of a huge set,
+        * because elements might time out during the listing.
+        */
+       if (SET_WITH_TIMEOUT(set)) {
+               spin_lock_bh(&set->lock);
+               mtype_expire(set, h);
+               spin_unlock_bh(&set->lock);
+       }
+
        rcu_read_lock_bh();
        t = rcu_dereference_bh_nfnl(h->table);
        memsize = mtype_ahash_memsize(h, t) + set->ext_size;
index f393a7086025f6c5e16032baeed63fa1cffba168..af8345fc4fbde30adad608b61a4fd293b4554584 100644 (file)
@@ -429,7 +429,7 @@ nf_nat_setup_info(struct nf_conn *ct,
 
                srchash = hash_by_src(net,
                                      &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-               lock = &nf_nat_locks[srchash % ARRAY_SIZE(nf_nat_locks)];
+               lock = &nf_nat_locks[srchash % CONNTRACK_LOCKS];
                spin_lock_bh(lock);
                hlist_add_head_rcu(&ct->nat_bysource,
                                   &nf_nat_bysource[srchash]);
@@ -532,9 +532,9 @@ static void __nf_nat_cleanup_conntrack(struct nf_conn *ct)
        unsigned int h;
 
        h = hash_by_src(nf_ct_net(ct), &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-       spin_lock_bh(&nf_nat_locks[h % ARRAY_SIZE(nf_nat_locks)]);
+       spin_lock_bh(&nf_nat_locks[h % CONNTRACK_LOCKS]);
        hlist_del_rcu(&ct->nat_bysource);
-       spin_unlock_bh(&nf_nat_locks[h % ARRAY_SIZE(nf_nat_locks)]);
+       spin_unlock_bh(&nf_nat_locks[h % CONNTRACK_LOCKS]);
 }
 
 static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
@@ -807,8 +807,8 @@ static int __init nf_nat_init(void)
 
        /* Leave them the same for the moment. */
        nf_nat_htable_size = nf_conntrack_htable_size;
-       if (nf_nat_htable_size < ARRAY_SIZE(nf_nat_locks))
-               nf_nat_htable_size = ARRAY_SIZE(nf_nat_locks);
+       if (nf_nat_htable_size < CONNTRACK_LOCKS)
+               nf_nat_htable_size = CONNTRACK_LOCKS;
 
        nf_nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, 0);
        if (!nf_nat_bysource)
@@ -821,7 +821,7 @@ static int __init nf_nat_init(void)
                return ret;
        }
 
-       for (i = 0; i < ARRAY_SIZE(nf_nat_locks); i++)
+       for (i = 0; i < CONNTRACK_LOCKS; i++)
                spin_lock_init(&nf_nat_locks[i]);
 
        nf_ct_helper_expectfn_register(&follow_master_nat);
index c26172995511f77bf9ed4c36d55fd1f430f6de5e..d288f52c53f7c1b16024e8369663ed4773c517c6 100644 (file)
@@ -1684,10 +1684,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 
        mutex_lock(&fanout_mutex);
 
-       err = -EINVAL;
-       if (!po->running)
-               goto out;
-
        err = -EALREADY;
        if (po->fanout)
                goto out;
@@ -1749,7 +1745,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
                list_add(&match->list, &fanout_list);
        }
        err = -EINVAL;
-       if (match->type == type &&
+
+       spin_lock(&po->bind_lock);
+       if (po->running &&
+           match->type == type &&
            match->prot_hook.type == po->prot_hook.type &&
            match->prot_hook.dev == po->prot_hook.dev) {
                err = -ENOSPC;
@@ -1761,6 +1760,13 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
                        err = 0;
                }
        }
+       spin_unlock(&po->bind_lock);
+
+       if (err && !refcount_read(&match->sk_ref)) {
+               list_del(&match->list);
+               kfree(match);
+       }
+
 out:
        if (err && rollover) {
                kfree(rollover);
index 1a267e77c6de93ad58fd609426d3daef27f39c54..d230cb4c809454137968be4bb1537d92bc8ebc5d 100644 (file)
@@ -922,28 +922,28 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
 
                if (!tc_flags_valid(fnew->flags)) {
                        err = -EINVAL;
-                       goto errout;
+                       goto errout_idr;
                }
        }
 
        err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr);
        if (err)
-               goto errout;
+               goto errout_idr;
 
        err = fl_check_assign_mask(head, &mask);
        if (err)
-               goto errout;
+               goto errout_idr;
 
        if (!tc_skip_sw(fnew->flags)) {
                if (!fold && fl_lookup(head, &fnew->mkey)) {
                        err = -EEXIST;
-                       goto errout;
+                       goto errout_idr;
                }
 
                err = rhashtable_insert_fast(&head->ht, &fnew->ht_node,
                                             head->ht_params);
                if (err)
-                       goto errout;
+                       goto errout_idr;
        }
 
        if (!tc_skip_hw(fnew->flags)) {
@@ -952,7 +952,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
                                           &mask.key,
                                           fnew);
                if (err)
-                       goto errout;
+                       goto errout_idr;
        }
 
        if (!tc_in_hw(fnew->flags))
@@ -981,6 +981,9 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        kfree(tb);
        return 0;
 
+errout_idr:
+       if (fnew->handle)
+               idr_remove_ext(&head->handle_idr, fnew->handle);
 errout:
        tcf_exts_destroy(&fnew->exts);
        kfree(fnew);
index 21cc45caf8424a2d9ba75558c11fe1dc8170cd48..eeac606c95abe99ca3f24ab462589adbe7c86388 100644 (file)
@@ -32,6 +32,7 @@ static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp,
        if (tc_skip_sw(head->flags))
                return -1;
 
+       *res = head->res;
        return tcf_exts_exec(skb, &head->exts, res);
 }
 
index 92237e75dbbc5e3e7dab124fb67baca98ae2160f..bf8c81e07c70457f37eeb167764a2aa33be34ace 100644 (file)
@@ -685,6 +685,7 @@ void qdisc_reset(struct Qdisc *qdisc)
                qdisc->gso_skb = NULL;
        }
        qdisc->q.qlen = 0;
+       qdisc->qstats.backlog = 0;
 }
 EXPORT_SYMBOL(qdisc_reset);
 
index daaf214e5201919ca3681e1670ac1389cb7985a4..3f88b75488b03275b152298bab0e66ea02298caa 100644 (file)
@@ -958,6 +958,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        }
 
        if (cl != NULL) {
+               int old_flags;
+
                if (parentid) {
                        if (cl->cl_parent &&
                            cl->cl_parent->cl_common.classid != parentid)
@@ -978,6 +980,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                }
 
                sch_tree_lock(sch);
+               old_flags = cl->cl_flags;
+
                if (rsc != NULL)
                        hfsc_change_rsc(cl, rsc, cur_time);
                if (fsc != NULL)
@@ -986,10 +990,21 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                        hfsc_change_usc(cl, usc, cur_time);
 
                if (cl->qdisc->q.qlen != 0) {
-                       if (cl->cl_flags & HFSC_RSC)
-                               update_ed(cl, qdisc_peek_len(cl->qdisc));
-                       if (cl->cl_flags & HFSC_FSC)
-                               update_vf(cl, 0, cur_time);
+                       int len = qdisc_peek_len(cl->qdisc);
+
+                       if (cl->cl_flags & HFSC_RSC) {
+                               if (old_flags & HFSC_RSC)
+                                       update_ed(cl, len);
+                               else
+                                       init_ed(cl, len);
+                       }
+
+                       if (cl->cl_flags & HFSC_FSC) {
+                               if (old_flags & HFSC_FSC)
+                                       update_vf(cl, 0, cur_time);
+                               else
+                                       init_vf(cl, len);
+                       }
                }
                sch_tree_unlock(sch);
 
index 8c6d24b2995dd5ced548275acce04d3a6d70f043..745f145d4c4d43316f3cb30083066456497fec3a 100644 (file)
@@ -282,6 +282,7 @@ int smc_netinfo_by_tcpsk(struct socket *clcsock,
                         __be32 *subnet, u8 *prefix_len)
 {
        struct dst_entry *dst = sk_dst_get(clcsock->sk);
+       struct in_device *in_dev;
        struct sockaddr_in addr;
        int rc = -ENOENT;
        int len;
@@ -298,14 +299,17 @@ int smc_netinfo_by_tcpsk(struct socket *clcsock,
        /* get address to which the internal TCP socket is bound */
        kernel_getsockname(clcsock, (struct sockaddr *)&addr, &len);
        /* analyze IPv4 specific data of net_device belonging to TCP socket */
-       for_ifa(dst->dev->ip_ptr) {
-               if (ifa->ifa_address != addr.sin_addr.s_addr)
+       rcu_read_lock();
+       in_dev = __in_dev_get_rcu(dst->dev);
+       for_ifa(in_dev) {
+               if (!inet_ifa_match(addr.sin_addr.s_addr, ifa))
                        continue;
                *prefix_len = inet_mask_len(ifa->ifa_mask);
                *subnet = ifa->ifa_address & ifa->ifa_mask;
                rc = 0;
                break;
-       } endfor_ifa(dst->dev->ip_ptr);
+       } endfor_ifa(in_dev);
+       rcu_read_unlock();
 
 out_rel:
        dst_release(dst);
@@ -509,7 +513,7 @@ decline_rdma:
        /* RDMA setup failed, switch back to TCP */
        smc->use_fallback = true;
        if (reason_code && (reason_code != SMC_CLC_DECL_REPLY)) {
-               rc = smc_clc_send_decline(smc, reason_code, 0);
+               rc = smc_clc_send_decline(smc, reason_code);
                if (rc < sizeof(struct smc_clc_msg_decline))
                        goto out_err;
        }
@@ -804,8 +808,6 @@ static void smc_listen_work(struct work_struct *work)
                rc = local_contact;
                if (rc == -ENOMEM)
                        reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/
-               else if (rc == -ENOLINK)
-                       reason_code = SMC_CLC_DECL_SYNCERR; /* synchr. error */
                goto decline_rdma;
        }
        link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK];
@@ -899,7 +901,7 @@ decline_rdma:
        smc_conn_free(&new_smc->conn);
        new_smc->use_fallback = true;
        if (reason_code && (reason_code != SMC_CLC_DECL_REPLY)) {
-               rc = smc_clc_send_decline(new_smc, reason_code, 0);
+               rc = smc_clc_send_decline(new_smc, reason_code);
                if (rc < sizeof(struct smc_clc_msg_decline))
                        goto out_err;
        }
index 6e44313e4467d01fbdc77f07ee7d14c50ab92ce2..0ccd6fa387ad7074cf0010cb3966f38d6c3b20cb 100644 (file)
@@ -149,7 +149,7 @@ struct smc_connection {
        atomic_t                sndbuf_space;   /* remaining space in sndbuf */
        u16                     tx_cdc_seq;     /* sequence # for CDC send */
        spinlock_t              send_lock;      /* protect wr_sends */
-       struct work_struct      tx_work;        /* retry of smc_cdc_msg_send */
+       struct delayed_work     tx_work;        /* retry of smc_cdc_msg_send */
 
        struct smc_host_cdc_msg local_rx_ctrl;  /* filled during event_handl.
                                                 * .prod cf. TCP rcv_nxt
index 3934913ab835cc791362a6a2ea816e871ce2cee1..b7dd2743fb5c0cfa11228b6c36b3a7fe3c53498e 100644 (file)
@@ -95,9 +95,10 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
        }
        if (clcm->type == SMC_CLC_DECLINE) {
                reason_code = SMC_CLC_DECL_REPLY;
-               if (ntohl(((struct smc_clc_msg_decline *)buf)->peer_diagnosis)
-                       == SMC_CLC_DECL_SYNCERR)
+               if (((struct smc_clc_msg_decline *)buf)->hdr.flag) {
                        smc->conn.lgr->sync_err = true;
+                       smc_lgr_terminate(smc->conn.lgr);
+               }
        }
 
 out:
@@ -105,8 +106,7 @@ out:
 }
 
 /* send CLC DECLINE message across internal TCP socket */
-int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info,
-                        u8 out_of_sync)
+int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
 {
        struct smc_clc_msg_decline dclc;
        struct msghdr msg;
@@ -118,7 +118,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info,
        dclc.hdr.type = SMC_CLC_DECLINE;
        dclc.hdr.length = htons(sizeof(struct smc_clc_msg_decline));
        dclc.hdr.version = SMC_CLC_V1;
-       dclc.hdr.flag = out_of_sync ? 1 : 0;
+       dclc.hdr.flag = (peer_diag_info == SMC_CLC_DECL_SYNCERR) ? 1 : 0;
        memcpy(dclc.id_for_peer, local_systemid, sizeof(local_systemid));
        dclc.peer_diagnosis = htonl(peer_diag_info);
        memcpy(dclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
index 13db8ce177c91dd913fac15fdebb5e05875e0ec9..1c55414041d49b560dfdd89fe9c1ed122a073cea 100644 (file)
@@ -106,8 +106,7 @@ struct smc_ib_device;
 
 int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
                     u8 expected_type);
-int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info,
-                        u8 out_of_sync);
+int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
 int smc_clc_send_proposal(struct smc_sock *smc, struct smc_ib_device *smcibdev,
                          u8 ibport);
 int smc_clc_send_confirm(struct smc_sock *smc);
index 3c2e166b5d222f4c932179ae442cbd88969efc92..f0d16fb825f7a545104232baacca32520cb14e08 100644 (file)
@@ -174,15 +174,15 @@ int smc_close_active(struct smc_sock *smc)
 {
        struct smc_cdc_conn_state_flags *txflags =
                &smc->conn.local_tx_ctrl.conn_state_flags;
-       long timeout = SMC_MAX_STREAM_WAIT_TIMEOUT;
        struct smc_connection *conn = &smc->conn;
        struct sock *sk = &smc->sk;
        int old_state;
+       long timeout;
        int rc = 0;
 
-       if (sock_flag(sk, SOCK_LINGER) &&
-           !(current->flags & PF_EXITING))
-               timeout = sk->sk_lingertime;
+       timeout = current->flags & PF_EXITING ?
+                 0 : sock_flag(sk, SOCK_LINGER) ?
+                     sk->sk_lingertime : SMC_MAX_STREAM_WAIT_TIMEOUT;
 
 again:
        old_state = sk->sk_state;
@@ -208,7 +208,7 @@ again:
        case SMC_ACTIVE:
                smc_close_stream_wait(smc, timeout);
                release_sock(sk);
-               cancel_work_sync(&conn->tx_work);
+               cancel_delayed_work_sync(&conn->tx_work);
                lock_sock(sk);
                if (sk->sk_state == SMC_ACTIVE) {
                        /* send close request */
@@ -234,7 +234,7 @@ again:
                if (!smc_cdc_rxed_any_close(conn))
                        smc_close_stream_wait(smc, timeout);
                release_sock(sk);
-               cancel_work_sync(&conn->tx_work);
+               cancel_delayed_work_sync(&conn->tx_work);
                lock_sock(sk);
                if (sk->sk_err != ECONNABORTED) {
                        /* confirm close from peer */
@@ -263,7 +263,9 @@ again:
                /* peer sending PeerConnectionClosed will cause transition */
                break;
        case SMC_PROCESSABORT:
-               cancel_work_sync(&conn->tx_work);
+               release_sock(sk);
+               cancel_delayed_work_sync(&conn->tx_work);
+               lock_sock(sk);
                smc_close_abort(conn);
                sk->sk_state = SMC_CLOSED;
                smc_close_wait_tx_pends(smc);
@@ -411,13 +413,14 @@ void smc_close_sock_put_work(struct work_struct *work)
 int smc_close_shutdown_write(struct smc_sock *smc)
 {
        struct smc_connection *conn = &smc->conn;
-       long timeout = SMC_MAX_STREAM_WAIT_TIMEOUT;
        struct sock *sk = &smc->sk;
        int old_state;
+       long timeout;
        int rc = 0;
 
-       if (sock_flag(sk, SOCK_LINGER))
-               timeout = sk->sk_lingertime;
+       timeout = current->flags & PF_EXITING ?
+                 0 : sock_flag(sk, SOCK_LINGER) ?
+                     sk->sk_lingertime : SMC_MAX_STREAM_WAIT_TIMEOUT;
 
 again:
        old_state = sk->sk_state;
@@ -425,7 +428,7 @@ again:
        case SMC_ACTIVE:
                smc_close_stream_wait(smc, timeout);
                release_sock(sk);
-               cancel_work_sync(&conn->tx_work);
+               cancel_delayed_work_sync(&conn->tx_work);
                lock_sock(sk);
                /* send close wr request */
                rc = smc_close_wr(conn);
@@ -439,7 +442,7 @@ again:
                if (!smc_cdc_rxed_any_close(conn))
                        smc_close_stream_wait(smc, timeout);
                release_sock(sk);
-               cancel_work_sync(&conn->tx_work);
+               cancel_delayed_work_sync(&conn->tx_work);
                lock_sock(sk);
                /* confirm close from peer */
                rc = smc_close_wr(conn);
index 1a16d51e2330bb43de8bdd67c18f8b03c1e3ee92..20b66e79c5d6305dddf120f09249654732842c00 100644 (file)
@@ -25,8 +25,9 @@
 #include "smc_cdc.h"
 #include "smc_close.h"
 
-#define SMC_LGR_NUM_INCR       256
-#define SMC_LGR_FREE_DELAY     (600 * HZ)
+#define SMC_LGR_NUM_INCR               256
+#define SMC_LGR_FREE_DELAY_SERV                (600 * HZ)
+#define SMC_LGR_FREE_DELAY_CLNT                (SMC_LGR_FREE_DELAY_SERV + 10)
 
 static u32 smc_lgr_num;                        /* unique link group number */
 
@@ -107,8 +108,15 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
                __smc_lgr_unregister_conn(conn);
        }
        write_unlock_bh(&lgr->conns_lock);
-       if (reduced && !lgr->conns_num)
-               schedule_delayed_work(&lgr->free_work, SMC_LGR_FREE_DELAY);
+       if (!reduced || lgr->conns_num)
+               return;
+       /* client link group creation always follows the server link group
+        * creation. For client use a somewhat higher removal delay time,
+        * otherwise there is a risk of out-of-sync link groups.
+        */
+       mod_delayed_work(system_wq, &lgr->free_work,
+                        lgr->role == SMC_CLNT ? SMC_LGR_FREE_DELAY_CLNT :
+                                                SMC_LGR_FREE_DELAY_SERV);
 }
 
 static void smc_lgr_free_work(struct work_struct *work)
index 547e0e113b17b19dc93e2606987a3dc0ff4c9c47..0b5852299158a71dea6c4f38b16482d80c078f56 100644 (file)
@@ -380,6 +380,7 @@ static int smc_ib_fill_gid_and_mac(struct smc_ib_device *smcibdev, u8 ibport)
        ndev = smcibdev->ibdev->get_netdev(smcibdev->ibdev, ibport);
        if (ndev) {
                memcpy(&smcibdev->mac, ndev->dev_addr, ETH_ALEN);
+               dev_put(ndev);
        } else if (!rc) {
                memcpy(&smcibdev->mac[ibport - 1][0],
                       &smcibdev->gid[ibport - 1].raw[8], 3);
index 78f7af28ae4f25d71469d54d44f98ef4e2df94eb..31f8453c25c5854340e7f701baf0990d0002376e 100644 (file)
@@ -181,8 +181,10 @@ static int smc_pnet_enter(struct smc_pnetentry *new_pnetelem)
                             sizeof(new_pnetelem->ndev->name)) ||
                    smc_pnet_same_ibname(pnetelem,
                                         new_pnetelem->smcibdev->ibdev->name,
-                                        new_pnetelem->ib_port))
+                                        new_pnetelem->ib_port)) {
+                       dev_put(pnetelem->ndev);
                        goto found;
+               }
        }
        list_add_tail(&new_pnetelem->list, &smc_pnettable.pnetlist);
        rc = 0;
index b17a333e9bb0733893d9e44d92fc7ddf2f75ffbf..3e631ae4b6b65f1ac9f32e5a22d6fdc5b294519f 100644 (file)
@@ -148,6 +148,8 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, size_t len,
                                read_done = sock_intr_errno(timeo);
                                break;
                        }
+                       if (!timeo)
+                               return -EAGAIN;
                }
 
                if (!atomic_read(&conn->bytes_to_rcv)) {
index 3c656beb8820cb16a28f379ee32f2f39a8ce6631..3866573288ddaf67f14943122ed6dbd941e6df3b 100644 (file)
@@ -24,6 +24,8 @@
 #include "smc_cdc.h"
 #include "smc_tx.h"
 
+#define SMC_TX_WORK_DELAY      HZ
+
 /***************************** sndbuf producer *******************************/
 
 /* callback implementation for sk.sk_write_space()
@@ -406,7 +408,8 @@ int smc_tx_sndbuf_nonempty(struct smc_connection *conn)
                                goto out_unlock;
                        }
                        rc = 0;
-                       schedule_work(&conn->tx_work);
+                       schedule_delayed_work(&conn->tx_work,
+                                             SMC_TX_WORK_DELAY);
                }
                goto out_unlock;
        }
@@ -430,7 +433,7 @@ out_unlock:
  */
 static void smc_tx_work(struct work_struct *work)
 {
-       struct smc_connection *conn = container_of(work,
+       struct smc_connection *conn = container_of(to_delayed_work(work),
                                                   struct smc_connection,
                                                   tx_work);
        struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
@@ -468,7 +471,8 @@ void smc_tx_consumer_update(struct smc_connection *conn)
                if (!rc)
                        rc = smc_cdc_msg_send(conn, wr_buf, pend);
                if (rc < 0) {
-                       schedule_work(&conn->tx_work);
+                       schedule_delayed_work(&conn->tx_work,
+                                             SMC_TX_WORK_DELAY);
                        return;
                }
                smc_curs_write(&conn->rx_curs_confirmed,
@@ -487,6 +491,6 @@ void smc_tx_consumer_update(struct smc_connection *conn)
 void smc_tx_init(struct smc_sock *smc)
 {
        smc->sk.sk_write_space = smc_tx_write_space;
-       INIT_WORK(&smc->conn.tx_work, smc_tx_work);
+       INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work);
        spin_lock_init(&smc->conn.send_lock);
 }
index ab56bda667837c3944eebfdfe921a2397fa52414..525d91e0d57e2fb3fa00ac9435df8a43bf0ea719 100644 (file)
@@ -244,7 +244,7 @@ int smc_wr_tx_send(struct smc_link *link, struct smc_wr_tx_pend_priv *priv)
        int rc;
 
        ib_req_notify_cq(link->smcibdev->roce_cq_send,
-                        IB_CQ_SOLICITED_MASK | IB_CQ_REPORT_MISSED_EVENTS);
+                        IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS);
        pend = container_of(priv, struct smc_wr_tx_pend, priv);
        rc = ib_post_send(link->roce_qp, &link->wr_tx_ibs[pend->idx],
                          &failed_wr);
index 5a936a6a31a3245cc6ab0f6e9804d268bc198261..df062e086bdbbda8eb9ec724754937ea42134505 100644 (file)
@@ -401,7 +401,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
        if (unlikely(n != mw->mw_nents))
                goto out_mapmr_err;
 
-       dprintk("RPC:       %s: Using frmr %p to map %u segments (%u bytes)\n",
+       dprintk("RPC:       %s: Using frmr %p to map %u segments (%llu bytes)\n",
                __func__, frmr, mw->mw_nents, mr->length);
 
        key = (u8)(mr->rkey & 0x000000FF);
index 0df8023f480bb69feb4cc2d3e0df6ea95f384e1a..690874293cfc6103a08eecf096a94184f36868f9 100644 (file)
@@ -9987,6 +9987,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
                if (err)
                        return err;
 
+               if (!setup.chandef.chan)
+                       return -EINVAL;
+
                err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
                                              &setup.beacon_rate);
                if (err)
@@ -10903,6 +10906,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
+       if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
+           !tb[NL80211_REKEY_DATA_KCK])
+               return -EINVAL;
        if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
                return -ERANGE;
        if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN)
index 2e3a10e79ca9ed645eaedbf0f8242332e96ba400..061d0c3a420ad58084df157a143e76133f304dc2 100644 (file)
@@ -265,6 +265,8 @@ objtool_args += --no-fp
 endif
 ifdef CONFIG_GCOV_KERNEL
 objtool_args += --no-unreachable
+else
+objtool_args += $(call cc-ifversion, -lt, 0405, --no-unreachable)
 endif
 
 # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
index f9a3d8d23c644a536ce0c9aaeed2c04b580af2f4..8c4fbad2055e59e973a82ce8aa6c00a58047e315 100755 (executable)
@@ -86,6 +86,7 @@ eod
 compile_to_dts() {
 
        dtx="$1"
+       dtc_include="$2"
 
        if [ -d "${dtx}" ] ; then
 
@@ -113,7 +114,7 @@ compile_to_dts() {
                # -----  input is DTS (source)
 
                if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \
-                       | ${DTC} -I dts ) ; then
+                       | ${DTC} ${dtc_include} -I dts ) ; then
                        return
                fi
 
@@ -320,18 +321,13 @@ fi
 
 cpp_flags="\
        -nostdinc                                  \
-       -I${srctree}/arch/${ARCH}/boot/dts         \
        -I${srctree}/scripts/dtc/include-prefixes  \
-       -I${srctree}/drivers/of/testcase-data      \
        -undef -D__DTS__"
 
-dtc_flags="\
-       -i ${srctree}/arch/${ARCH}/boot/dts/ \
-       -i ${srctree}/kernel/dts             \
-       ${dtx_path_1_dtc_include}            \
-       ${dtx_path_2_dtc_include}"
-
-DTC="${DTC} ${dtc_flags} -O dts -qq -f ${dtc_sort} -o -"
+DTC="\
+       ${DTC}                                     \
+       -i ${srctree}/scripts/dtc/include-prefixes \
+       -O dts -qq -f ${dtc_sort} -o -"
 
 
 # -----  do the diff or decompile
@@ -339,11 +335,11 @@ DTC="${DTC} ${dtc_flags} -O dts -qq -f ${dtc_sort} -o -"
 if (( ${cmd_diff} )) ; then
 
        diff ${diff_flags} --label "${dtx_file_1}" --label "${dtx_file_2}" \
-               <(compile_to_dts "${dtx_file_1}") \
-               <(compile_to_dts "${dtx_file_2}")
+               <(compile_to_dts "${dtx_file_1}" "${dtx_path_1_dtc_include}") \
+               <(compile_to_dts "${dtx_file_2}" "${dtx_path_2_dtc_include}")
 
 else
 
-       compile_to_dts "${dtx_file_1}"
+       compile_to_dts "${dtx_file_1}" "${dtx_path_1_dtc_include}"
 
 fi
diff --git a/scripts/mkversion b/scripts/mkversion
deleted file mode 100644 (file)
index c12addc..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-if [ ! -f .version ]
-then
-    echo 1
-else
-    expr 0`cat .version` + 1
-fi
index 71b4a8af9d4dcdf1dcec434b6be98636f468b2dd..73f9f3192b9fbf8770e6ef632723d23e8efb5b63 100644 (file)
@@ -50,8 +50,6 @@ rpm-pkg rpm: FORCE
        $(MAKE) clean
        $(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec
        $(call cmd,src_tar,$(KERNELPATH),kernel.spec)
-       $(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
-       mv -f $(objtree)/.tmp_version $(objtree)/.version
        rpmbuild $(RPMOPTS) --target $(UTS_MACHINE) -ta $(KERNELPATH).tar.gz
        rm $(KERNELPATH).tar.gz kernel.spec
 
@@ -60,9 +58,6 @@ rpm-pkg rpm: FORCE
 binrpm-pkg: FORCE
        $(MAKE) KBUILD_SRC=
        $(CONFIG_SHELL) $(MKSPEC) prebuilt > $(objtree)/binkernel.spec
-       $(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
-       mv -f $(objtree)/.tmp_version $(objtree)/.version
-
        rpmbuild $(RPMOPTS) --define "_builddir $(objtree)" --target \
                $(UTS_MACHINE) -bb $(objtree)/binkernel.spec
        rm binkernel.spec
index aad67000e4dd76796894cbd1975d087c559ecc5c..0bc87473f68f817b81640591f75f18c3b068351c 100755 (executable)
@@ -92,12 +92,10 @@ else
 fi
 sourcename=$KDEB_SOURCENAME
 tmpdir="$objtree/debian/tmp"
-fwdir="$objtree/debian/fwtmp"
 kernel_headers_dir="$objtree/debian/hdrtmp"
 libc_headers_dir="$objtree/debian/headertmp"
 dbg_dir="$objtree/debian/dbgtmp"
 packagename=linux-image-$version
-fwpackagename=linux-firmware-image-$version
 kernel_headers_packagename=linux-headers-$version
 libc_headers_packagename=linux-libc-dev
 dbg_packagename=$packagename-dbg
@@ -126,10 +124,9 @@ esac
 BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)"
 
 # Setup the directory structure
-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
+rm -rf "$tmpdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
 mkdir -m 755 -p "$tmpdir/DEBIAN"
 mkdir -p "$tmpdir/lib" "$tmpdir/boot"
-mkdir -p "$fwdir/lib/firmware/$version/"
 mkdir -p "$kernel_headers_dir/lib/modules/$version/"
 
 # Build and install the kernel
@@ -306,7 +303,6 @@ else
        cat <<EOF >> debian/control
 
 Package: $packagename
-Suggests: $fwpackagename
 Architecture: any
 Description: Linux kernel, version $version
  This package contains the Linux kernel, modules and corresponding other
@@ -345,22 +341,6 @@ Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch}
  This is useful for people who need to build external modules
 EOF
 
-# Do we have firmware? Move it out of the way and build it into a package.
-if [ -e "$tmpdir/lib/firmware" ]; then
-       mv "$tmpdir/lib/firmware"/* "$fwdir/lib/firmware/$version/"
-       rmdir "$tmpdir/lib/firmware"
-
-       cat <<EOF >> debian/control
-
-Package: $fwpackagename
-Architecture: all
-Description: Linux kernel firmware, version $version
- This package contains firmware from the Linux kernel, version $version.
-EOF
-
-       create_package "$fwpackagename" "$fwdir"
-fi
-
 cat <<EOF >> debian/control
 
 Package: $libc_headers_packagename
index bb43f153fd8e70fd48c32a2f92fa6699242501f7..f47f17aae135188eae37db2178db6c9911a80023 100755 (executable)
@@ -27,9 +27,7 @@ __KERNELRELEASE=`echo $KERNELRELEASE | sed -e "s/-/_/g"`
 echo "Name: kernel"
 echo "Summary: The Linux Kernel"
 echo "Version: $__KERNELRELEASE"
-# we need to determine the NEXT version number so that uname and
-# rpm -q will agree
-echo "Release: `. $srctree/scripts/mkversion`"
+echo "Release: $(cat .version 2>/dev/null || echo 1)"
 echo "License: GPL"
 echo "Group: System Environment/Kernel"
 echo "Vendor: The Linux Community"
@@ -77,7 +75,7 @@ fi
 echo "%build"
 
 if ! $PREBUILT; then
-echo "make clean && make %{?_smp_mflags}"
+echo "make clean && make %{?_smp_mflags} KBUILD_BUILD_VERSION=%{release}"
 echo ""
 fi
 
@@ -88,11 +86,8 @@ echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi $RPM_BUILD_ROOT/lib/modules'
 echo "%else"
 echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib/modules'
 echo "%endif"
-echo 'mkdir -p $RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE"
 
-echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} KBUILD_SRC= mod-fw= modules_install'
-echo 'INSTALL_FW_PATH=$RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE"
-echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' firmware_install
+echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} KBUILD_SRC= modules_install'
 echo "%ifarch ia64"
 echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE"
 echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/"
@@ -119,7 +114,7 @@ if ! $PREBUILT; then
 echo 'rm -f $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE/build"
 echo 'rm -f $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE/source"
 echo "mkdir -p "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE"
-echo "EXCLUDES=\"$RCS_TAR_IGNORE --exclude .tmp_versions --exclude=*vmlinux* --exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation --exclude=firmware --exclude .config.old --exclude .missing-syscalls.d\""
+echo "EXCLUDES=\"$RCS_TAR_IGNORE --exclude .tmp_versions --exclude=*vmlinux* --exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation --exclude .config.old --exclude .missing-syscalls.d\""
 echo "tar "'$EXCLUDES'" -cf- . | (cd "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE;tar xvf -)"
 echo 'cd $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE"
 echo "ln -sf /usr/src/kernels/$KERNELRELEASE build"
@@ -154,7 +149,6 @@ echo '%defattr (-, root, root)'
 echo "/lib/modules/$KERNELRELEASE"
 echo "%exclude /lib/modules/$KERNELRELEASE/build"
 echo "%exclude /lib/modules/$KERNELRELEASE/source"
-echo "/lib/firmware/$KERNELRELEASE"
 echo "/boot/*"
 echo ""
 echo "%files headers"
index 9cdec70d72b8ed83c38ec3a271b9495b53975b2e..d5b291e94264f9784438ea38e3242ad7697cb510 100644 (file)
@@ -1,5 +1,6 @@
 #
 # Generated include files
 #
+net_names.h
 capability_names.h
 rlim_names.h
index a16b195274dec2c48d3ee41e3cdad1b6460138c1..dafdd387d42bab8a5184efb51240123fd3a463f5 100644 (file)
@@ -4,11 +4,44 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
 
 apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
               path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
-              resource.o secid.o file.o policy_ns.o label.o
+              resource.o secid.o file.o policy_ns.o label.o mount.o net.o
 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
 
-clean-files := capability_names.h rlim_names.h
+clean-files := capability_names.h rlim_names.h net_names.h
 
+# Build a lower case string table of address family names
+# Transform lines from
+#    #define AF_LOCAL          1       /* POSIX name for AF_UNIX       */
+#    #define AF_INET           2       /* Internet IP Protocol         */
+# to
+#    [1] = "local",
+#    [2] = "inet",
+#
+# and build the securityfs entries for the mapping.
+# Transforms lines from
+#    #define AF_INET           2       /* Internet IP Protocol         */
+# to
+#    #define AA_SFS_AF_MASK "local inet"
+quiet_cmd_make-af = GEN     $@
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
+       sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
+        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
+       echo "};" >> $@ ;\
+       printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
+       sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
+        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
+        $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
+
+# Build a lower case string table of sock type names
+# Transform lines from
+#    SOCK_STREAM       = 1,
+# to
+#    [1] = "stream",
+quiet_cmd_make-sock = GEN     $@
+cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
+       sed $^ >>$@ -r -n \
+       -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
+       echo "};" >> $@
 
 # Build a lower case string table of capability names
 # Transforms lines from
@@ -61,6 +94,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
            tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
 
 $(obj)/capability.o : $(obj)/capability_names.h
+$(obj)/net.o : $(obj)/net_names.h
 $(obj)/resource.o : $(obj)/rlim_names.h
 $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
                            $(src)/Makefile
@@ -68,3 +102,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
 $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
                      $(src)/Makefile
        $(call cmd,make-rlim)
+$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
+                    $(srctree)/include/linux/net.h \
+                    $(src)/Makefile
+       $(call cmd,make-af)
+       $(call cmd,make-sock)
index 853c2ec8e0c9521e53fe2c6edecb0b7913cfad26..518d5928661b518c8f037db26edfed44f6270752 100644 (file)
@@ -32,6 +32,7 @@
 #include "include/audit.h"
 #include "include/context.h"
 #include "include/crypto.h"
+#include "include/ipc.h"
 #include "include/policy_ns.h"
 #include "include/label.h"
 #include "include/policy.h"
@@ -248,8 +249,10 @@ static struct dentry *aafs_create(const char *name, umode_t mode,
 
        inode_lock(dir);
        dentry = lookup_one_len(name, parent, strlen(name));
-       if (IS_ERR(dentry))
+       if (IS_ERR(dentry)) {
+               error = PTR_ERR(dentry);
                goto fail_lock;
+       }
 
        if (d_really_is_positive(dentry)) {
                error = -EEXIST;
@@ -1443,6 +1446,10 @@ void __aafs_profile_migrate_dents(struct aa_profile *old,
 {
        int i;
 
+       AA_BUG(!old);
+       AA_BUG(!new);
+       AA_BUG(!mutex_is_locked(&profiles_ns(old)->lock));
+
        for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
                new->dents[i] = old->dents[i];
                if (new->dents[i])
@@ -1506,6 +1513,9 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
        struct dentry *dent = NULL, *dir;
        int error;
 
+       AA_BUG(!profile);
+       AA_BUG(!mutex_is_locked(&profiles_ns(profile)->lock));
+
        if (!parent) {
                struct aa_profile *p;
                p = aa_deref_parent(profile);
@@ -1731,6 +1741,7 @@ void __aafs_ns_rmdir(struct aa_ns *ns)
 
        if (!ns)
                return;
+       AA_BUG(!mutex_is_locked(&ns->lock));
 
        list_for_each_entry(child, &ns->base.profiles, base.list)
                __aafs_profile_rmdir(child);
@@ -1903,6 +1914,10 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
 {
        struct aa_ns *parent, *next;
 
+       AA_BUG(!root);
+       AA_BUG(!ns);
+       AA_BUG(ns != root && !mutex_is_locked(&ns->parent->lock));
+
        /* is next namespace a child */
        if (!list_empty(&ns->sub_ns)) {
                next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
@@ -1937,6 +1952,9 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
 static struct aa_profile *__first_profile(struct aa_ns *root,
                                          struct aa_ns *ns)
 {
+       AA_BUG(!root);
+       AA_BUG(ns && !mutex_is_locked(&ns->lock));
+
        for (; ns; ns = __next_ns(root, ns)) {
                if (!list_empty(&ns->base.profiles))
                        return list_first_entry(&ns->base.profiles,
@@ -1959,6 +1977,8 @@ static struct aa_profile *__next_profile(struct aa_profile *p)
        struct aa_profile *parent;
        struct aa_ns *ns = p->ns;
 
+       AA_BUG(!mutex_is_locked(&profiles_ns(p)->lock));
+
        /* is next profile a child */
        if (!list_empty(&p->base.profiles))
                return list_first_entry(&p->base.profiles, typeof(*p),
@@ -2127,6 +2147,11 @@ static struct aa_sfs_entry aa_sfs_entry_ptrace[] = {
        { }
 };
 
+static struct aa_sfs_entry aa_sfs_entry_signal[] = {
+       AA_SFS_FILE_STRING("mask", AA_SFS_SIG_MASK),
+       { }
+};
+
 static struct aa_sfs_entry aa_sfs_entry_domain[] = {
        AA_SFS_FILE_BOOLEAN("change_hat",       1),
        AA_SFS_FILE_BOOLEAN("change_hatv",      1),
@@ -2151,9 +2176,14 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
        { }
 };
 
+static struct aa_sfs_entry aa_sfs_entry_mount[] = {
+       AA_SFS_FILE_STRING("mask", "mount umount pivot_root"),
+       { }
+};
+
 static struct aa_sfs_entry aa_sfs_entry_ns[] = {
        AA_SFS_FILE_BOOLEAN("profile",          1),
-       AA_SFS_FILE_BOOLEAN("pivot_root",       1),
+       AA_SFS_FILE_BOOLEAN("pivot_root",       0),
        { }
 };
 
@@ -2172,22 +2202,25 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
        AA_SFS_DIR("policy",                    aa_sfs_entry_policy),
        AA_SFS_DIR("domain",                    aa_sfs_entry_domain),
        AA_SFS_DIR("file",                      aa_sfs_entry_file),
+       AA_SFS_DIR("network",                   aa_sfs_entry_network),
+       AA_SFS_DIR("mount",                     aa_sfs_entry_mount),
        AA_SFS_DIR("namespaces",                aa_sfs_entry_ns),
        AA_SFS_FILE_U64("capability",           VFS_CAP_FLAGS_MASK),
        AA_SFS_DIR("rlimit",                    aa_sfs_entry_rlimit),
        AA_SFS_DIR("caps",                      aa_sfs_entry_caps),
        AA_SFS_DIR("ptrace",                    aa_sfs_entry_ptrace),
+       AA_SFS_DIR("signal",                    aa_sfs_entry_signal),
        AA_SFS_DIR("query",                     aa_sfs_entry_query),
        { }
 };
 
 static struct aa_sfs_entry aa_sfs_entry_apparmor[] = {
-       AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access),
+       AA_SFS_FILE_FOPS(".access", 0666, &aa_sfs_access),
        AA_SFS_FILE_FOPS(".stacked", 0444, &seq_ns_stacked_fops),
        AA_SFS_FILE_FOPS(".ns_stacked", 0444, &seq_ns_nsstacked_fops),
-       AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops),
-       AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops),
-       AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops),
+       AA_SFS_FILE_FOPS(".ns_level", 0444, &seq_ns_level_fops),
+       AA_SFS_FILE_FOPS(".ns_name", 0444, &seq_ns_name_fops),
+       AA_SFS_FILE_FOPS("profiles", 0444, &aa_sfs_profiles_fops),
        AA_SFS_DIR("features", aa_sfs_entry_features),
        { }
 };
index 17a601c67b62c93f26246389b0ee8805850bee05..dd754b7850a82b4d129c11de0c55603de19268ba 100644 (file)
@@ -374,8 +374,8 @@ static const char *next_name(int xtype, const char *name)
  *
  * Returns: refcounted label, or NULL on failure (MAYBE NULL)
  */
-static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
-                                      const char **name)
+struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
+                               const char **name)
 {
        struct aa_label *label = NULL;
        u32 xtype = xindex & AA_X_TYPE_MASK;
index 3382518b87fa507200679cb9ef660329a292debc..db80221891c66f034c1a3138f46d455a2685d102 100644 (file)
@@ -21,6 +21,7 @@
 #include "include/context.h"
 #include "include/file.h"
 #include "include/match.h"
+#include "include/net.h"
 #include "include/path.h"
 #include "include/policy.h"
 #include "include/label.h"
@@ -566,6 +567,32 @@ static int __file_path_perm(const char *op, struct aa_label *label,
        return error;
 }
 
+static int __file_sock_perm(const char *op, struct aa_label *label,
+                           struct aa_label *flabel, struct file *file,
+                           u32 request, u32 denied)
+{
+       struct socket *sock = (struct socket *) file->private_data;
+       int error;
+
+       AA_BUG(!sock);
+
+       /* revalidation due to label out of date. No revocation at this time */
+       if (!denied && aa_label_is_subset(flabel, label))
+               return 0;
+
+       /* TODO: improve to skip profiles cached in flabel */
+       error = aa_sock_file_perm(label, op, request, sock);
+       if (denied) {
+               /* TODO: improve to skip profiles checked above */
+               /* check every profile in file label to is cached */
+               last_error(error, aa_sock_file_perm(flabel, op, request, sock));
+       }
+       if (!error)
+               update_file_ctx(file_ctx(file), label, request);
+
+       return error;
+}
+
 /**
  * aa_file_perm - do permission revalidation check & audit for @file
  * @op: operation being checked
@@ -610,6 +637,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
                error = __file_path_perm(op, label, flabel, file, request,
                                         denied);
 
+       else if (S_ISSOCK(file_inode(file)->i_mode))
+               error = __file_sock_perm(op, label, flabel, file, request,
+                                        denied);
 done:
        rcu_read_unlock();
 
index aaf893f4e4f50c8f35f2e74c18a264f5ee583a39..829082c35faac7a932a568745068a2a3a979c124 100644 (file)
@@ -27,7 +27,9 @@
 #define AA_CLASS_NET           4
 #define AA_CLASS_RLIMITS       5
 #define AA_CLASS_DOMAIN                6
+#define AA_CLASS_MOUNT         7
 #define AA_CLASS_PTRACE                9
+#define AA_CLASS_SIGNAL                10
 #define AA_CLASS_LABEL         16
 
 #define AA_CLASS_LAST          AA_CLASS_LABEL
index c68839a44351e9b184951a6535fa574293c55876..ff4316e1068d6b98ea7cbf44d21e96ff75cf9328 100644 (file)
@@ -71,6 +71,10 @@ enum audit_type {
 #define OP_FMPROT "file_mprotect"
 #define OP_INHERIT "file_inherit"
 
+#define OP_PIVOTROOT "pivotroot"
+#define OP_MOUNT "mount"
+#define OP_UMOUNT "umount"
+
 #define OP_CREATE "create"
 #define OP_POST_CREATE "post_create"
 #define OP_BIND "bind"
@@ -86,6 +90,7 @@ enum audit_type {
 #define OP_SHUTDOWN "socket_shutdown"
 
 #define OP_PTRACE "ptrace"
+#define OP_SIGNAL "signal"
 
 #define OP_EXEC "exec"
 
@@ -116,20 +121,36 @@ struct apparmor_audit_data {
                /* these entries require a custom callback fn */
                struct {
                        struct aa_label *peer;
-                       struct {
-                               const char *target;
-                               kuid_t ouid;
-                       } fs;
+                       union {
+                               struct {
+                                       kuid_t ouid;
+                                       const char *target;
+                               } fs;
+                               struct {
+                                       int type, protocol;
+                                       struct sock *peer_sk;
+                                       void *addr;
+                                       int addrlen;
+                               } net;
+                               int signal;
+                               struct {
+                                       int rlim;
+                                       unsigned long max;
+                               } rlim;
+                       };
                };
                struct {
-                       const char *name;
-                       long pos;
+                       struct aa_profile *profile;
                        const char *ns;
+                       long pos;
                } iface;
                struct {
-                       int rlim;
-                       unsigned long max;
-               } rlim;
+                       const char *src_name;
+                       const char *type;
+                       const char *trans;
+                       const char *data;
+                       unsigned long flags;
+               } mnt;
        };
 };
 
index 24c5976d6143fee013882a92b56bc96ec8105429..ac9862ff7cdf5d7bed9a365a30e8d62c1cfc0c1f 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/binfmts.h>
 #include <linux/types.h>
 
+#include "label.h"
+
 #ifndef __AA_DOMAIN_H
 #define __AA_DOMAIN_H
 
@@ -29,6 +31,9 @@ struct aa_domain {
 #define AA_CHANGE_ONEXEC  4
 #define AA_CHANGE_STACK 8
 
+struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
+                               const char **name);
+
 int apparmor_bprm_set_creds(struct linux_binprm *bprm);
 
 void aa_free_domain_entries(struct aa_domain *domain);
index 656fdb81c8a0a08836b12ed614334222c0648212..5ffc218d1e748aebb6aa777ad129976e87752ddd 100644 (file)
@@ -27,8 +27,14 @@ struct aa_profile;
 
 #define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \
                             AA_MAY_BE_READ | AA_MAY_BE_TRACED)
+#define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE)
+
+#define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \
+       "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \
+       "xcpu xfsz vtalrm prof winch io pwr sys emt lost"
 
 int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
                  u32 request);
+int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig);
 
 #endif /* __AA_IPC_H */
index 9a283b722755786a2e213e591323d101d7b30816..af22dcbbcb8aa165d16d1769aba7e92eb5965ada 100644 (file)
@@ -310,6 +310,7 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp);
 #define FLAG_SHOW_MODE 1
 #define FLAG_VIEW_SUBNS 2
 #define FLAG_HIDDEN_UNCONFINED 4
+#define FLAG_ABS_ROOT 8
 int aa_label_snxprint(char *str, size_t size, struct aa_ns *view,
                      struct aa_label *label, int flags);
 int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label,
diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
new file mode 100644 (file)
index 0000000..25d6067
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor file mediation function definitions.
+ *
+ * Copyright 2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_MOUNT_H
+#define __AA_MOUNT_H
+
+#include <linux/fs.h>
+#include <linux/path.h>
+
+#include "domain.h"
+#include "policy.h"
+
+/* mount perms */
+#define AA_MAY_PIVOTROOT       0x01
+#define AA_MAY_MOUNT           0x02
+#define AA_MAY_UMOUNT          0x04
+#define AA_AUDIT_DATA          0x40
+#define AA_MNT_CONT_MATCH      0x40
+
+#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
+
+int aa_remount(struct aa_label *label, const struct path *path,
+              unsigned long flags, void *data);
+
+int aa_bind_mount(struct aa_label *label, const struct path *path,
+                 const char *old_name, unsigned long flags);
+
+
+int aa_mount_change_type(struct aa_label *label, const struct path *path,
+                        unsigned long flags);
+
+int aa_move_mount(struct aa_label *label, const struct path *path,
+                 const char *old_name);
+
+int aa_new_mount(struct aa_label *label, const char *dev_name,
+                const struct path *path, const char *type, unsigned long flags,
+                void *data);
+
+int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags);
+
+int aa_pivotroot(struct aa_label *label, const struct path *old_path,
+                const struct path *new_path);
+
+#endif /* __AA_MOUNT_H */
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644 (file)
index 0000000..140c8ef
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_NET_H
+#define __AA_NET_H
+
+#include <net/sock.h>
+#include <linux/path.h>
+
+#include "apparmorfs.h"
+#include "label.h"
+#include "perms.h"
+#include "policy.h"
+
+#define AA_MAY_SEND            AA_MAY_WRITE
+#define AA_MAY_RECEIVE         AA_MAY_READ
+
+#define AA_MAY_SHUTDOWN                AA_MAY_DELETE
+
+#define AA_MAY_CONNECT         AA_MAY_OPEN
+#define AA_MAY_ACCEPT          0x00100000
+
+#define AA_MAY_BIND            0x00200000
+#define AA_MAY_LISTEN          0x00400000
+
+#define AA_MAY_SETOPT          0x01000000
+#define AA_MAY_GETOPT          0x02000000
+
+#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE |    \
+                       AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN |   \
+                       AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
+                       AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
+
+#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE |   \
+                     AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
+                     AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD |  \
+                     AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK |       \
+                     AA_MAY_MPROT)
+
+#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
+                      AA_MAY_ACCEPT)
+struct aa_sk_ctx {
+       struct aa_label *label;
+       struct aa_label *peer;
+       struct path path;
+};
+
+#define SK_CTX(X) ((X)->sk_security)
+#define SOCK_ctx(X) SOCK_INODE(X)->i_security
+#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P)                                  \
+       struct lsm_network_audit NAME ## _net = { .sk = (SK),             \
+                                                 .family = (F)};         \
+       DEFINE_AUDIT_DATA(NAME,                                           \
+                         ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
+                                                    LSM_AUDIT_DATA_NONE, \
+                         OP);                                            \
+       NAME.u.net = &(NAME ## _net);                                     \
+       aad(&NAME)->net.type = (T);                                       \
+       aad(&NAME)->net.protocol = (P)
+
+#define DEFINE_AUDIT_SK(NAME, OP, SK)                                  \
+       DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type,  \
+                        (SK)->sk_protocol)
+
+/* struct aa_net - network confinement data
+ * @allow: basic network families permissions
+ * @audit: which network permissions to force audit
+ * @quiet: which network permissions to quiet rejects
+ */
+struct aa_net {
+       u16 allow[AF_MAX];
+       u16 audit[AF_MAX];
+       u16 quiet[AF_MAX];
+};
+
+
+extern struct aa_sfs_entry aa_sfs_entry_network[];
+
+void audit_net_cb(struct audit_buffer *ab, void *va);
+int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
+                      u32 request, u16 family, int type);
+int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
+              int type, int protocol);
+static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
+                                       struct common_audit_data *sa,
+                                       u32 request,
+                                       struct sock *sk)
+{
+       return aa_profile_af_perm(profile, sa, request, sk->sk_family,
+                                 sk->sk_type);
+}
+int aa_sk_perm(const char *op, u32 request, struct sock *sk);
+
+int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
+                     struct socket *sock);
+
+
+static inline void aa_free_net_rules(struct aa_net *new)
+{
+       /* NOP */
+}
+
+#endif /* __AA_NET_H */
index 2b27bb79aec4421665aaa6f2a2490868227bed0f..af04d5a7d73d46146f152c83529a50829b986962 100644 (file)
@@ -135,9 +135,10 @@ extern struct aa_perms allperms;
 
 
 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
-void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
+void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
+                        u32 mask);
 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
-                       u32 chrsmask, const char **names, u32 namesmask);
+                       u32 chrsmask, const char * const *names, u32 namesmask);
 void aa_apply_modes_to_perms(struct aa_profile *profile,
                             struct aa_perms *perms);
 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
index 17fe41a9cac35e6d88f3ae738bf2b068de736ec1..4364088a0b9e2188b6353e815cca6c1b3e70fc25 100644 (file)
@@ -30,6 +30,7 @@
 #include "file.h"
 #include "lib.h"
 #include "label.h"
+#include "net.h"
 #include "perms.h"
 #include "resource.h"
 
@@ -111,6 +112,7 @@ struct aa_data {
  * @policy: general match rules governing policy
  * @file: The set of rules governing basic file access and domain transitions
  * @caps: capabilities for the profile
+ * @net: network controls for the profile
  * @rlimits: rlimits for the profile
  *
  * @dents: dentries for the profiles file entries in apparmorfs
@@ -148,6 +150,7 @@ struct aa_profile {
        struct aa_policydb policy;
        struct aa_file_rules file;
        struct aa_caps caps;
+       struct aa_net net;
        struct aa_rlimit rlimits;
 
        struct aa_loaddata *rawdata;
@@ -220,6 +223,16 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
        return 0;
 }
 
+static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
+                                              u16 AF) {
+       unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
+       u16 be_af = cpu_to_be16(AF);
+
+       if (!state)
+               return 0;
+       return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
+}
+
 /**
  * aa_get_profile - increment refcount on profile @p
  * @p: profile  (MAYBE NULL)
diff --git a/security/apparmor/include/sig_names.h b/security/apparmor/include/sig_names.h
new file mode 100644 (file)
index 0000000..92e62fe
--- /dev/null
@@ -0,0 +1,98 @@
+#include <linux/signal.h>
+
+#define SIGUNKNOWN 0
+#define MAXMAPPED_SIG 35
+/* provide a mapping of arch signal to internal signal # for mediation
+ * those that are always an alias SIGCLD for SIGCLHD and SIGPOLL for SIGIO
+ * map to the same entry those that may/or may not get a separate entry
+ */
+static const int sig_map[MAXMAPPED_SIG] = {
+       [0] = MAXMAPPED_SIG,    /* existence test */
+       [SIGHUP] = 1,
+       [SIGINT] = 2,
+       [SIGQUIT] = 3,
+       [SIGILL] = 4,
+       [SIGTRAP] = 5,          /* -, 5, - */
+       [SIGABRT] = 6,          /*  SIGIOT: -, 6, - */
+       [SIGBUS] = 7,           /* 10, 7, 10 */
+       [SIGFPE] = 8,
+       [SIGKILL] = 9,
+       [SIGUSR1] = 10,         /* 30, 10, 16 */
+       [SIGSEGV] = 11,
+       [SIGUSR2] = 12,         /* 31, 12, 17 */
+       [SIGPIPE] = 13,
+       [SIGALRM] = 14,
+       [SIGTERM] = 15,
+#ifdef SIGSTKFLT
+       [SIGSTKFLT] = 16,       /* -, 16, - */
+#endif
+       [SIGCHLD] = 17,         /* 20, 17, 18.  SIGCHLD -, -, 18 */
+       [SIGCONT] = 18,         /* 19, 18, 25 */
+       [SIGSTOP] = 19,         /* 17, 19, 23 */
+       [SIGTSTP] = 20,         /* 18, 20, 24 */
+       [SIGTTIN] = 21,         /* 21, 21, 26 */
+       [SIGTTOU] = 22,         /* 22, 22, 27 */
+       [SIGURG] = 23,          /* 16, 23, 21 */
+       [SIGXCPU] = 24,         /* 24, 24, 30 */
+       [SIGXFSZ] = 25,         /* 25, 25, 31 */
+       [SIGVTALRM] = 26,       /* 26, 26, 28 */
+       [SIGPROF] = 27,         /* 27, 27, 29 */
+       [SIGWINCH] = 28,        /* 28, 28, 20 */
+       [SIGIO] = 29,           /* SIGPOLL: 23, 29, 22 */
+       [SIGPWR] = 30,          /* 29, 30, 19.  SIGINFO 29, -, - */
+#ifdef SIGSYS
+       [SIGSYS] = 31,          /* 12, 31, 12. often SIG LOST/UNUSED */
+#endif
+#ifdef SIGEMT
+       [SIGEMT] = 32,          /* 7, - , 7 */
+#endif
+#if defined(SIGLOST) && SIGPWR != SIGLOST              /* sparc */
+       [SIGLOST] = 33,         /* unused on Linux */
+#endif
+#if defined(SIGUNUSED) && \
+    defined(SIGLOST) && defined(SIGSYS) && SIGLOST != SIGSYS
+       [SIGUNUSED] = 34,       /* -, 31, - */
+#endif
+};
+
+/* this table is ordered post sig_map[sig] mapping */
+static const char *const sig_names[MAXMAPPED_SIG + 1] = {
+       "unknown",
+       "hup",
+       "int",
+       "quit",
+       "ill",
+       "trap",
+       "abrt",
+       "bus",
+       "fpe",
+       "kill",
+       "usr1",
+       "segv",
+       "usr2",
+       "pipe",
+       "alrm",
+       "term",
+       "stkflt",
+       "chld",
+       "cont",
+       "stop",
+       "stp",
+       "ttin",
+       "ttou",
+       "urg",
+       "xcpu",
+       "xfsz",
+       "vtalrm",
+       "prof",
+       "winch",
+       "io",
+       "pwr",
+       "sys",
+       "emt",
+       "lost",
+       "unused",
+
+       "exists",       /* always last existence test mapped to MAXMAPPED_SIG */
+};
+
index 11e66b5bbc4266c7c9b0f4fa47d13afdf709b47f..66fb9ede9447adc71e3fd27a0b90d306b095c0fe 100644 (file)
@@ -20,6 +20,7 @@
 #include "include/context.h"
 #include "include/policy.h"
 #include "include/ipc.h"
+#include "include/sig_names.h"
 
 /**
  * audit_ptrace_mask - convert mask to permission string
@@ -121,3 +122,101 @@ int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
 }
 
 
+static inline int map_signal_num(int sig)
+{
+       if (sig > SIGRTMAX)
+               return SIGUNKNOWN;
+       else if (sig >= SIGRTMIN)
+               return sig - SIGRTMIN + 128;    /* rt sigs mapped to 128 */
+       else if (sig <= MAXMAPPED_SIG)
+               return sig_map[sig];
+       return SIGUNKNOWN;
+}
+
+/**
+ * audit_file_mask - convert mask to permission string
+ * @buffer: buffer to write string to (NOT NULL)
+ * @mask: permission mask to convert
+ */
+static void audit_signal_mask(struct audit_buffer *ab, u32 mask)
+{
+       if (mask & MAY_READ)
+               audit_log_string(ab, "receive");
+       if (mask & MAY_WRITE)
+               audit_log_string(ab, "send");
+}
+
+/**
+ * audit_cb - call back for signal specific audit fields
+ * @ab: audit_buffer  (NOT NULL)
+ * @va: audit struct to audit values of  (NOT NULL)
+ */
+static void audit_signal_cb(struct audit_buffer *ab, void *va)
+{
+       struct common_audit_data *sa = va;
+
+       if (aad(sa)->request & AA_SIGNAL_PERM_MASK) {
+               audit_log_format(ab, " requested_mask=");
+               audit_signal_mask(ab, aad(sa)->request);
+               if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) {
+                       audit_log_format(ab, " denied_mask=");
+                       audit_signal_mask(ab, aad(sa)->denied);
+               }
+       }
+       if (aad(sa)->signal <= MAXMAPPED_SIG)
+               audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]);
+       else
+               audit_log_format(ab, " signal=rtmin+%d",
+                                aad(sa)->signal - 128);
+       audit_log_format(ab, " peer=");
+       aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
+                       FLAGS_NONE, GFP_ATOMIC);
+}
+
+/* TODO: update to handle compound name&name2, conditionals */
+static void profile_match_signal(struct aa_profile *profile, const char *label,
+                                int signal, struct aa_perms *perms)
+{
+       unsigned int state;
+
+       /* TODO: secondary cache check <profile, profile, perm> */
+       state = aa_dfa_next(profile->policy.dfa,
+                           profile->policy.start[AA_CLASS_SIGNAL],
+                           signal);
+       state = aa_dfa_match(profile->policy.dfa, state, label);
+       aa_compute_perms(profile->policy.dfa, state, perms);
+}
+
+static int profile_signal_perm(struct aa_profile *profile,
+                              struct aa_profile *peer, u32 request,
+                              struct common_audit_data *sa)
+{
+       struct aa_perms perms;
+
+       if (profile_unconfined(profile) ||
+           !PROFILE_MEDIATES(profile, AA_CLASS_SIGNAL))
+               return 0;
+
+       aad(sa)->peer = &peer->label;
+       profile_match_signal(profile, peer->base.hname, aad(sa)->signal,
+                            &perms);
+       aa_apply_modes_to_perms(profile, &perms);
+       return aa_check_perms(profile, &perms, request, sa, audit_signal_cb);
+}
+
+static int aa_signal_cross_perm(struct aa_profile *sender,
+                               struct aa_profile *target,
+                               struct common_audit_data *sa)
+{
+       return xcheck(profile_signal_perm(sender, target, MAY_WRITE, sa),
+                     profile_signal_perm(target, sender, MAY_READ, sa));
+}
+
+int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig)
+{
+       DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SIGNAL);
+
+       aad(&sa)->signal = map_signal_num(sig);
+       return xcheck_labels_profiles(sender, target, aa_signal_cross_perm,
+                                     &sa);
+}
index e052eaba1cf6ccb003c1e3ae364798bc44b1d292..c5b99b954580c940d3cc3659a48c10b22752c1f0 100644 (file)
@@ -49,7 +49,7 @@ static void free_proxy(struct aa_proxy *proxy)
                /* p->label will not updated any more as p is dead */
                aa_put_label(rcu_dereference_protected(proxy->label, true));
                memset(proxy, 0, sizeof(*proxy));
-               proxy->label = (struct aa_label *) PROXY_POISON;
+               RCU_INIT_POINTER(proxy->label, (struct aa_label *)PROXY_POISON);
                kfree(proxy);
        }
 }
@@ -1450,9 +1450,11 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp)
  * cached label name is present and visible
  * @label->hname only exists if label is namespace hierachical
  */
-static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label)
+static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label,
+                                  int flags)
 {
-       if (label->hname && labels_ns(label) == ns)
+       if (label->hname && (!ns || labels_ns(label) == ns) &&
+           !(flags & ~FLAG_SHOW_MODE))
                return true;
 
        return false;
@@ -1495,7 +1497,7 @@ static int aa_profile_snxprint(char *str, size_t size, struct aa_ns *view,
                view = profiles_ns(profile);
 
        if (view != profile->ns &&
-           (!prev_ns || (prev_ns && *prev_ns != profile->ns))) {
+           (!prev_ns || (*prev_ns != profile->ns))) {
                if (prev_ns)
                        *prev_ns = profile->ns;
                ns_name = aa_ns_name(view, profile->ns,
@@ -1605,8 +1607,13 @@ int aa_label_snxprint(char *str, size_t size, struct aa_ns *ns,
        AA_BUG(!str && size != 0);
        AA_BUG(!label);
 
-       if (!ns)
+       if (flags & FLAG_ABS_ROOT) {
+               ns = root_ns;
+               len = snprintf(str, size, "=");
+               update_for_len(total, len, size, str);
+       } else if (!ns) {
                ns = labels_ns(label);
+       }
 
        label_for_each(i, label, profile) {
                if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) {
@@ -1710,10 +1717,8 @@ void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns,
        AA_BUG(!ab);
        AA_BUG(!label);
 
-       if (!ns)
-               ns = labels_ns(label);
-
-       if (!use_label_hname(ns, label) || display_mode(ns, label, flags)) {
+       if (!use_label_hname(ns, label, flags) ||
+           display_mode(ns, label, flags)) {
                len  = aa_label_asxprint(&name, ns, label, flags, gfp);
                if (len == -1) {
                        AA_DEBUG("label print error");
@@ -1738,10 +1743,7 @@ void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns,
        AA_BUG(!f);
        AA_BUG(!label);
 
-       if (!ns)
-               ns = labels_ns(label);
-
-       if (!use_label_hname(ns, label)) {
+       if (!use_label_hname(ns, label, flags)) {
                char *str;
                int len;
 
@@ -1764,10 +1766,7 @@ void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags,
 {
        AA_BUG(!label);
 
-       if (!ns)
-               ns = labels_ns(label);
-
-       if (!use_label_hname(ns, label)) {
+       if (!use_label_hname(ns, label, flags)) {
                char *str;
                int len;
 
@@ -1874,6 +1873,9 @@ struct aa_label *aa_label_parse(struct aa_label *base, const char *str,
                if (*str == '&')
                        str++;
        }
+       if (*str == '=')
+               base = &root_ns->unconfined->label;
+
        error = vec_setup(profile, vec, len, gfp);
        if (error)
                return ERR_PTR(error);
index 08ca26bcca7703c7f74e1531879eea4dd3bf2ac9..8818621b5d956023d9fc799fbff00a0b073fabc8 100644 (file)
@@ -211,7 +211,8 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
        *str = '\0';
 }
 
-void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
+void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
+                        u32 mask)
 {
        const char *fmt = "%s";
        unsigned int i, perm = 1;
@@ -229,7 +230,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
 }
 
 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
-                       u32 chrsmask, const char **names, u32 namesmask)
+                       u32 chrsmask, const char * const *names, u32 namesmask)
 {
        char str[33];
 
index 7a82c0f61452d3fe3e2821bbcbda29a643572500..72b915dfcaf7eeeed1a2d428777878c81e5f4f80 100644 (file)
 #include "include/context.h"
 #include "include/file.h"
 #include "include/ipc.h"
+#include "include/net.h"
 #include "include/path.h"
 #include "include/label.h"
 #include "include/policy.h"
 #include "include/policy_ns.h"
 #include "include/procattr.h"
+#include "include/mount.h"
 
 /* Flag indicating whether initialization completed */
 int apparmor_initialized;
@@ -511,6 +513,65 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
                           !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
 }
 
+static int apparmor_sb_mount(const char *dev_name, const struct path *path,
+                            const char *type, unsigned long flags, void *data)
+{
+       struct aa_label *label;
+       int error = 0;
+
+       /* Discard magic */
+       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
+               flags &= ~MS_MGC_MSK;
+
+       flags &= ~AA_MS_IGNORE_MASK;
+
+       label = __begin_current_label_crit_section();
+       if (!unconfined(label)) {
+               if (flags & MS_REMOUNT)
+                       error = aa_remount(label, path, flags, data);
+               else if (flags & MS_BIND)
+                       error = aa_bind_mount(label, path, dev_name, flags);
+               else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
+                                 MS_UNBINDABLE))
+                       error = aa_mount_change_type(label, path, flags);
+               else if (flags & MS_MOVE)
+                       error = aa_move_mount(label, path, dev_name);
+               else
+                       error = aa_new_mount(label, dev_name, path, type,
+                                            flags, data);
+       }
+       __end_current_label_crit_section(label);
+
+       return error;
+}
+
+static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
+{
+       struct aa_label *label;
+       int error = 0;
+
+       label = __begin_current_label_crit_section();
+       if (!unconfined(label))
+               error = aa_umount(label, mnt, flags);
+       __end_current_label_crit_section(label);
+
+       return error;
+}
+
+static int apparmor_sb_pivotroot(const struct path *old_path,
+                                const struct path *new_path)
+{
+       struct aa_label *label;
+       int error = 0;
+
+       label = aa_get_current_label();
+       if (!unconfined(label))
+               error = aa_pivotroot(label, old_path, new_path);
+       aa_put_label(label);
+
+       return error;
+}
+
 static int apparmor_getprocattr(struct task_struct *task, char *name,
                                char **value)
 {
@@ -656,12 +717,398 @@ static int apparmor_task_setrlimit(struct task_struct *task,
        return error;
 }
 
+static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
+                             int sig, u32 secid)
+{
+       struct aa_label *cl, *tl;
+       int error;
+
+       if (secid)
+               /* TODO: after secid to label mapping is done.
+                *  Dealing with USB IO specific behavior
+                */
+               return 0;
+       cl = __begin_current_label_crit_section();
+       tl = aa_get_task_label(target);
+       error = aa_may_signal(cl, tl, sig);
+       aa_put_label(tl);
+       __end_current_label_crit_section(cl);
+
+       return error;
+}
+
+/**
+ * apparmor_sk_alloc_security - allocate and attach the sk_security field
+ */
+static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
+{
+       struct aa_sk_ctx *ctx;
+
+       ctx = kzalloc(sizeof(*ctx), flags);
+       if (!ctx)
+               return -ENOMEM;
+
+       SK_CTX(sk) = ctx;
+
+       return 0;
+}
+
+/**
+ * apparmor_sk_free_security - free the sk_security field
+ */
+static void apparmor_sk_free_security(struct sock *sk)
+{
+       struct aa_sk_ctx *ctx = SK_CTX(sk);
+
+       SK_CTX(sk) = NULL;
+       aa_put_label(ctx->label);
+       aa_put_label(ctx->peer);
+       path_put(&ctx->path);
+       kfree(ctx);
+}
+
+/**
+ * apparmor_clone_security - clone the sk_security field
+ */
+static void apparmor_sk_clone_security(const struct sock *sk,
+                                      struct sock *newsk)
+{
+       struct aa_sk_ctx *ctx = SK_CTX(sk);
+       struct aa_sk_ctx *new = SK_CTX(newsk);
+
+       new->label = aa_get_label(ctx->label);
+       new->peer = aa_get_label(ctx->peer);
+       new->path = ctx->path;
+       path_get(&new->path);
+}
+
+static int aa_sock_create_perm(struct aa_label *label, int family, int type,
+                              int protocol)
+{
+       AA_BUG(!label);
+       AA_BUG(in_interrupt());
+
+       return aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, family, type,
+                         protocol);
+}
+
+
+/**
+ * apparmor_socket_create - check perms before creating a new socket
+ */
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+       struct aa_label *label;
+       int error = 0;
+
+       label = begin_current_label_crit_section();
+       if (!(kern || unconfined(label)))
+               error = aa_sock_create_perm(label, family, type, protocol);
+       end_current_label_crit_section(label);
+
+       return error;
+}
+
+/**
+ * apparmor_socket_post_create - setup the per-socket security struct
+ *
+ * Note:
+ * -   kernel sockets currently labeled unconfined but we may want to
+ *     move to a special kernel label
+ * -   socket may not have sk here if created with sock_create_lite or
+ *     sock_alloc. These should be accept cases which will be handled in
+ *     sock_graft.
+ */
+static int apparmor_socket_post_create(struct socket *sock, int family,
+                                      int type, int protocol, int kern)
+{
+       struct aa_label *label;
+
+       if (kern) {
+               struct aa_ns *ns = aa_get_current_ns();
+
+               label = aa_get_label(ns_unconfined(ns));
+               aa_put_ns(ns);
+       } else
+               label = aa_get_current_label();
+
+       if (sock->sk) {
+               struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
+
+               aa_put_label(ctx->label);
+               ctx->label = aa_get_label(label);
+       }
+       aa_put_label(label);
+
+       return 0;
+}
+
+/**
+ * apparmor_socket_bind - check perms before bind addr to socket
+ */
+static int apparmor_socket_bind(struct socket *sock,
+                               struct sockaddr *address, int addrlen)
+{
+       AA_BUG(!sock);
+       AA_BUG(!sock->sk);
+       AA_BUG(!address);
+       AA_BUG(in_interrupt());
+
+       return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk);
+}
+
+/**
+ * apparmor_socket_connect - check perms before connecting @sock to @address
+ */
+static int apparmor_socket_connect(struct socket *sock,
+                                  struct sockaddr *address, int addrlen)
+{
+       AA_BUG(!sock);
+       AA_BUG(!sock->sk);
+       AA_BUG(!address);
+       AA_BUG(in_interrupt());
+
+       return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
+}
+
+/**
+ * apparmor_socket_list - check perms before allowing listen
+ */
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+       AA_BUG(!sock);
+       AA_BUG(!sock->sk);
+       AA_BUG(in_interrupt());
+
+       return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk);
+}
+
+/**
+ * apparmor_socket_accept - check perms before accepting a new connection.
+ *
+ * Note: while @newsock is created and has some information, the accept
+ *       has not been done.
+ */
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+       AA_BUG(!sock);
+       AA_BUG(!sock->sk);
+       AA_BUG(!newsock);
+       AA_BUG(in_interrupt());
+
+       return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk);
+}
+
+static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock,
+                           struct msghdr *msg, int size)
+{
+       AA_BUG(!sock);
+       AA_BUG(!sock->sk);
+       AA_BUG(!msg);
+       AA_BUG(in_interrupt());
+
+       return aa_sk_perm(op, request, sock->sk);
+}
+
+/**
+ * apparmor_socket_sendmsg - check perms before sending msg to another socket
+ */
+static int apparmor_socket_sendmsg(struct socket *sock,
+                                  struct msghdr *msg, int size)
+{
+       return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
+}
+
+/**
+ * apparmor_socket_recvmsg - check perms before receiving a message
+ */
+static int apparmor_socket_recvmsg(struct socket *sock,
+                                  struct msghdr *msg, int size, int flags)
+{
+       return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size);
+}
+
+/* revaliation, get/set attr, shutdown */
+static int aa_sock_perm(const char *op, u32 request, struct socket *sock)
+{
+       AA_BUG(!sock);
+       AA_BUG(!sock->sk);
+       AA_BUG(in_interrupt());
+
+       return aa_sk_perm(op, request, sock->sk);
+}
+
+/**
+ * apparmor_socket_getsockname - check perms before getting the local address
+ */
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+       return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock);
+}
+
+/**
+ * apparmor_socket_getpeername - check perms before getting remote address
+ */
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+       return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock);
+}
+
+/* revaliation, get/set attr, opt */
+static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock,
+                           int level, int optname)
+{
+       AA_BUG(!sock);
+       AA_BUG(!sock->sk);
+       AA_BUG(in_interrupt());
+
+       return aa_sk_perm(op, request, sock->sk);
+}
+
+/**
+ * apparmor_getsockopt - check perms before getting socket options
+ */
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+                                     int optname)
+{
+       return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock,
+                               level, optname);
+}
+
+/**
+ * apparmor_setsockopt - check perms before setting socket options
+ */
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+                                     int optname)
+{
+       return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock,
+                               level, optname);
+}
+
+/**
+ * apparmor_socket_shutdown - check perms before shutting down @sock conn
+ */
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+       return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock);
+}
+
+/**
+ * apparmor_socket_sock_recv_skb - check perms before associating skb to sk
+ *
+ * Note: can not sleep may be called with locks held
+ *
+ * dont want protocol specific in __skb_recv_datagram()
+ * to deny an incoming connection  socket_sock_rcv_skb()
+ */
+static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+       return 0;
+}
+
+
+static struct aa_label *sk_peer_label(struct sock *sk)
+{
+       struct aa_sk_ctx *ctx = SK_CTX(sk);
+
+       if (ctx->peer)
+               return ctx->peer;
+
+       return ERR_PTR(-ENOPROTOOPT);
+}
+
+/**
+ * apparmor_socket_getpeersec_stream - get security context of peer
+ *
+ * Note: for tcp only valid if using ipsec or cipso on lan
+ */
+static int apparmor_socket_getpeersec_stream(struct socket *sock,
+                                            char __user *optval,
+                                            int __user *optlen,
+                                            unsigned int len)
+{
+       char *name;
+       int slen, error = 0;
+       struct aa_label *label;
+       struct aa_label *peer;
+
+       label = begin_current_label_crit_section();
+       peer = sk_peer_label(sock->sk);
+       if (IS_ERR(peer)) {
+               error = PTR_ERR(peer);
+               goto done;
+       }
+       slen = aa_label_asxprint(&name, labels_ns(label), peer,
+                                FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
+                                FLAG_HIDDEN_UNCONFINED, GFP_KERNEL);
+       /* don't include terminating \0 in slen, it breaks some apps */
+       if (slen < 0) {
+               error = -ENOMEM;
+       } else {
+               if (slen > len) {
+                       error = -ERANGE;
+               } else if (copy_to_user(optval, name, slen)) {
+                       error = -EFAULT;
+                       goto out;
+               }
+               if (put_user(slen, optlen))
+                       error = -EFAULT;
+out:
+               kfree(name);
+
+       }
+
+done:
+       end_current_label_crit_section(label);
+
+       return error;
+}
+
+/**
+ * apparmor_socket_getpeersec_dgram - get security label of packet
+ * @sock: the peer socket
+ * @skb: packet data
+ * @secid: pointer to where to put the secid of the packet
+ *
+ * Sets the netlabel socket state on sk from parent
+ */
+static int apparmor_socket_getpeersec_dgram(struct socket *sock,
+                                           struct sk_buff *skb, u32 *secid)
+
+{
+       /* TODO: requires secid support */
+       return -ENOPROTOOPT;
+}
+
+/**
+ * apparmor_sock_graft - Initialize newly created socket
+ * @sk: child sock
+ * @parent: parent socket
+ *
+ * Note: could set off of SOCK_CTX(parent) but need to track inode and we can
+ *       just set sk security information off of current creating process label
+ *       Labeling of sk for accept case - probably should be sock based
+ *       instead of task, because of the case where an implicitly labeled
+ *       socket is shared by different tasks.
+ */
+static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
+{
+       struct aa_sk_ctx *ctx = SK_CTX(sk);
+
+       if (!ctx->label)
+               ctx->label = aa_get_current_label();
+}
+
 static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
        LSM_HOOK_INIT(capget, apparmor_capget),
        LSM_HOOK_INIT(capable, apparmor_capable),
 
+       LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
+       LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
+       LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
+
        LSM_HOOK_INIT(path_link, apparmor_path_link),
        LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
        LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
@@ -686,6 +1133,30 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
        LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
 
+       LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
+       LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
+       LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
+
+       LSM_HOOK_INIT(socket_create, apparmor_socket_create),
+       LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create),
+       LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
+       LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
+       LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
+       LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
+       LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
+       LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
+       LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
+       LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
+       LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
+       LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
+       LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
+       LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb),
+       LSM_HOOK_INIT(socket_getpeersec_stream,
+                     apparmor_socket_getpeersec_stream),
+       LSM_HOOK_INIT(socket_getpeersec_dgram,
+                     apparmor_socket_getpeersec_dgram),
+       LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
+
        LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
        LSM_HOOK_INIT(cred_free, apparmor_cred_free),
        LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
@@ -696,6 +1167,7 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds),
 
        LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
+       LSM_HOOK_INIT(task_kill, apparmor_task_kill),
 };
 
 /*
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
new file mode 100644 (file)
index 0000000..82a64b5
--- /dev/null
@@ -0,0 +1,696 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor mediation of files
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/domain.h"
+#include "include/file.h"
+#include "include/match.h"
+#include "include/mount.h"
+#include "include/path.h"
+#include "include/policy.h"
+
+
+static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
+{
+       if (flags & MS_RDONLY)
+               audit_log_format(ab, "ro");
+       else
+               audit_log_format(ab, "rw");
+       if (flags & MS_NOSUID)
+               audit_log_format(ab, ", nosuid");
+       if (flags & MS_NODEV)
+               audit_log_format(ab, ", nodev");
+       if (flags & MS_NOEXEC)
+               audit_log_format(ab, ", noexec");
+       if (flags & MS_SYNCHRONOUS)
+               audit_log_format(ab, ", sync");
+       if (flags & MS_REMOUNT)
+               audit_log_format(ab, ", remount");
+       if (flags & MS_MANDLOCK)
+               audit_log_format(ab, ", mand");
+       if (flags & MS_DIRSYNC)
+               audit_log_format(ab, ", dirsync");
+       if (flags & MS_NOATIME)
+               audit_log_format(ab, ", noatime");
+       if (flags & MS_NODIRATIME)
+               audit_log_format(ab, ", nodiratime");
+       if (flags & MS_BIND)
+               audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
+       if (flags & MS_MOVE)
+               audit_log_format(ab, ", move");
+       if (flags & MS_SILENT)
+               audit_log_format(ab, ", silent");
+       if (flags & MS_POSIXACL)
+               audit_log_format(ab, ", acl");
+       if (flags & MS_UNBINDABLE)
+               audit_log_format(ab, flags & MS_REC ? ", runbindable" :
+                                ", unbindable");
+       if (flags & MS_PRIVATE)
+               audit_log_format(ab, flags & MS_REC ? ", rprivate" :
+                                ", private");
+       if (flags & MS_SLAVE)
+               audit_log_format(ab, flags & MS_REC ? ", rslave" :
+                                ", slave");
+       if (flags & MS_SHARED)
+               audit_log_format(ab, flags & MS_REC ? ", rshared" :
+                                ", shared");
+       if (flags & MS_RELATIME)
+               audit_log_format(ab, ", relatime");
+       if (flags & MS_I_VERSION)
+               audit_log_format(ab, ", iversion");
+       if (flags & MS_STRICTATIME)
+               audit_log_format(ab, ", strictatime");
+       if (flags & MS_NOUSER)
+               audit_log_format(ab, ", nouser");
+}
+
+/**
+ * audit_cb - call back for mount specific audit fields
+ * @ab: audit_buffer  (NOT NULL)
+ * @va: audit struct to audit values of  (NOT NULL)
+ */
+static void audit_cb(struct audit_buffer *ab, void *va)
+{
+       struct common_audit_data *sa = va;
+
+       if (aad(sa)->mnt.type) {
+               audit_log_format(ab, " fstype=");
+               audit_log_untrustedstring(ab, aad(sa)->mnt.type);
+       }
+       if (aad(sa)->mnt.src_name) {
+               audit_log_format(ab, " srcname=");
+               audit_log_untrustedstring(ab, aad(sa)->mnt.src_name);
+       }
+       if (aad(sa)->mnt.trans) {
+               audit_log_format(ab, " trans=");
+               audit_log_untrustedstring(ab, aad(sa)->mnt.trans);
+       }
+       if (aad(sa)->mnt.flags) {
+               audit_log_format(ab, " flags=\"");
+               audit_mnt_flags(ab, aad(sa)->mnt.flags);
+               audit_log_format(ab, "\"");
+       }
+       if (aad(sa)->mnt.data) {
+               audit_log_format(ab, " options=");
+               audit_log_untrustedstring(ab, aad(sa)->mnt.data);
+       }
+}
+
+/**
+ * audit_mount - handle the auditing of mount operations
+ * @profile: the profile being enforced  (NOT NULL)
+ * @op: operation being mediated (NOT NULL)
+ * @name: name of object being mediated (MAYBE NULL)
+ * @src_name: src_name of object being mediated (MAYBE_NULL)
+ * @type: type of filesystem (MAYBE_NULL)
+ * @trans: name of trans (MAYBE NULL)
+ * @flags: filesystem idependent mount flags
+ * @data: filesystem mount flags
+ * @request: permissions requested
+ * @perms: the permissions computed for the request (NOT NULL)
+ * @info: extra information message (MAYBE NULL)
+ * @error: 0 if operation allowed else failure error code
+ *
+ * Returns: %0 or error on failure
+ */
+static int audit_mount(struct aa_profile *profile, const char *op,
+                      const char *name, const char *src_name,
+                      const char *type, const char *trans,
+                      unsigned long flags, const void *data, u32 request,
+                      struct aa_perms *perms, const char *info, int error)
+{
+       int audit_type = AUDIT_APPARMOR_AUTO;
+       DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
+
+       if (likely(!error)) {
+               u32 mask = perms->audit;
+
+               if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
+                       mask = 0xffff;
+
+               /* mask off perms that are not being force audited */
+               request &= mask;
+
+               if (likely(!request))
+                       return 0;
+               audit_type = AUDIT_APPARMOR_AUDIT;
+       } else {
+               /* only report permissions that were denied */
+               request = request & ~perms->allow;
+
+               if (request & perms->kill)
+                       audit_type = AUDIT_APPARMOR_KILL;
+
+               /* quiet known rejects, assumes quiet and kill do not overlap */
+               if ((request & perms->quiet) &&
+                   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+                   AUDIT_MODE(profile) != AUDIT_ALL)
+                       request &= ~perms->quiet;
+
+               if (!request)
+                       return error;
+       }
+
+       aad(&sa)->name = name;
+       aad(&sa)->mnt.src_name = src_name;
+       aad(&sa)->mnt.type = type;
+       aad(&sa)->mnt.trans = trans;
+       aad(&sa)->mnt.flags = flags;
+       if (data && (perms->audit & AA_AUDIT_DATA))
+               aad(&sa)->mnt.data = data;
+       aad(&sa)->info = info;
+       aad(&sa)->error = error;
+
+       return aa_audit(audit_type, profile, &sa, audit_cb);
+}
+
+/**
+ * match_mnt_flags - Do an ordered match on mount flags
+ * @dfa: dfa to match against
+ * @state: state to start in
+ * @flags: mount flags to match against
+ *
+ * Mount flags are encoded as an ordered match. This is done instead of
+ * checking against a simple bitmask, to allow for logical operations
+ * on the flags.
+ *
+ * Returns: next state after flags match
+ */
+static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
+                                   unsigned long flags)
+{
+       unsigned int i;
+
+       for (i = 0; i <= 31 ; ++i) {
+               if ((1 << i) & flags)
+                       state = aa_dfa_next(dfa, state, i + 1);
+       }
+
+       return state;
+}
+
+/**
+ * compute_mnt_perms - compute mount permission associated with @state
+ * @dfa: dfa to match against (NOT NULL)
+ * @state: state match finished in
+ *
+ * Returns: mount permissions
+ */
+static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa,
+                                          unsigned int state)
+{
+       struct aa_perms perms;
+
+       perms.kill = 0;
+       perms.allow = dfa_user_allow(dfa, state);
+       perms.audit = dfa_user_audit(dfa, state);
+       perms.quiet = dfa_user_quiet(dfa, state);
+       perms.xindex = dfa_user_xindex(dfa, state);
+
+       return perms;
+}
+
+static const char * const mnt_info_table[] = {
+       "match succeeded",
+       "failed mntpnt match",
+       "failed srcname match",
+       "failed type match",
+       "failed flags match",
+       "failed data match"
+};
+
+/*
+ * Returns 0 on success else element that match failed in, this is the
+ * index into the mnt_info_table above
+ */
+static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
+                       const char *mntpnt, const char *devname,
+                       const char *type, unsigned long flags,
+                       void *data, bool binary, struct aa_perms *perms)
+{
+       unsigned int state;
+
+       AA_BUG(!dfa);
+       AA_BUG(!perms);
+
+       state = aa_dfa_match(dfa, start, mntpnt);
+       state = aa_dfa_null_transition(dfa, state);
+       if (!state)
+               return 1;
+
+       if (devname)
+               state = aa_dfa_match(dfa, state, devname);
+       state = aa_dfa_null_transition(dfa, state);
+       if (!state)
+               return 2;
+
+       if (type)
+               state = aa_dfa_match(dfa, state, type);
+       state = aa_dfa_null_transition(dfa, state);
+       if (!state)
+               return 3;
+
+       state = match_mnt_flags(dfa, state, flags);
+       if (!state)
+               return 4;
+       *perms = compute_mnt_perms(dfa, state);
+       if (perms->allow & AA_MAY_MOUNT)
+               return 0;
+
+       /* only match data if not binary and the DFA flags data is expected */
+       if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
+               state = aa_dfa_null_transition(dfa, state);
+               if (!state)
+                       return 4;
+
+               state = aa_dfa_match(dfa, state, data);
+               if (!state)
+                       return 5;
+               *perms = compute_mnt_perms(dfa, state);
+               if (perms->allow & AA_MAY_MOUNT)
+                       return 0;
+       }
+
+       /* failed at end of flags match */
+       return 4;
+}
+
+
+static int path_flags(struct aa_profile *profile, const struct path *path)
+{
+       AA_BUG(!profile);
+       AA_BUG(!path);
+
+       return profile->path_flags |
+               (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0);
+}
+
+/**
+ * match_mnt_path_str - handle path matching for mount
+ * @profile: the confining profile
+ * @mntpath: for the mntpnt (NOT NULL)
+ * @buffer: buffer to be used to lookup mntpath
+ * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR)
+ * @type: string for the dev type (MAYBE NULL)
+ * @flags: mount flags to match
+ * @data: fs mount data (MAYBE NULL)
+ * @binary: whether @data is binary
+ * @devinfo: error str if (IS_ERR(@devname))
+ *
+ * Returns: 0 on success else error
+ */
+static int match_mnt_path_str(struct aa_profile *profile,
+                             const struct path *mntpath, char *buffer,
+                             const char *devname, const char *type,
+                             unsigned long flags, void *data, bool binary,
+                             const char *devinfo)
+{
+       struct aa_perms perms = { };
+       const char *mntpnt = NULL, *info = NULL;
+       int pos, error;
+
+       AA_BUG(!profile);
+       AA_BUG(!mntpath);
+       AA_BUG(!buffer);
+
+       error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
+                            &mntpnt, &info, profile->disconnected);
+       if (error)
+               goto audit;
+       if (IS_ERR(devname)) {
+               error = PTR_ERR(devname);
+               devname = NULL;
+               info = devinfo;
+               goto audit;
+       }
+
+       error = -EACCES;
+       pos = do_match_mnt(profile->policy.dfa,
+                          profile->policy.start[AA_CLASS_MOUNT],
+                          mntpnt, devname, type, flags, data, binary, &perms);
+       if (pos) {
+               info = mnt_info_table[pos];
+               goto audit;
+       }
+       error = 0;
+
+audit:
+       return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL,
+                          flags, data, AA_MAY_MOUNT, &perms, info, error);
+}
+
+/**
+ * match_mnt - handle path matching for mount
+ * @profile: the confining profile
+ * @mntpath: for the mntpnt (NOT NULL)
+ * @buffer: buffer to be used to lookup mntpath
+ * @devpath: path devname/src_name (MAYBE NULL)
+ * @devbuffer: buffer to be used to lookup devname/src_name
+ * @type: string for the dev type (MAYBE NULL)
+ * @flags: mount flags to match
+ * @data: fs mount data (MAYBE NULL)
+ * @binary: whether @data is binary
+ *
+ * Returns: 0 on success else error
+ */
+static int match_mnt(struct aa_profile *profile, const struct path *path,
+                    char *buffer, struct path *devpath, char *devbuffer,
+                    const char *type, unsigned long flags, void *data,
+                    bool binary)
+{
+       const char *devname = NULL, *info = NULL;
+       int error = -EACCES;
+
+       AA_BUG(!profile);
+       AA_BUG(devpath && !devbuffer);
+
+       if (devpath) {
+               error = aa_path_name(devpath, path_flags(profile, devpath),
+                                    devbuffer, &devname, &info,
+                                    profile->disconnected);
+               if (error)
+                       devname = ERR_PTR(error);
+       }
+
+       return match_mnt_path_str(profile, path, buffer, devname, type, flags,
+                                 data, binary, info);
+}
+
+int aa_remount(struct aa_label *label, const struct path *path,
+              unsigned long flags, void *data)
+{
+       struct aa_profile *profile;
+       char *buffer = NULL;
+       bool binary;
+       int error;
+
+       AA_BUG(!label);
+       AA_BUG(!path);
+
+       binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
+
+       get_buffers(buffer);
+       error = fn_for_each_confined(label, profile,
+                       match_mnt(profile, path, buffer, NULL, NULL, NULL,
+                                 flags, data, binary));
+       put_buffers(buffer);
+
+       return error;
+}
+
+int aa_bind_mount(struct aa_label *label, const struct path *path,
+                 const char *dev_name, unsigned long flags)
+{
+       struct aa_profile *profile;
+       char *buffer = NULL, *old_buffer = NULL;
+       struct path old_path;
+       int error;
+
+       AA_BUG(!label);
+       AA_BUG(!path);
+
+       if (!dev_name || !*dev_name)
+               return -EINVAL;
+
+       flags &= MS_REC | MS_BIND;
+
+       error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
+       if (error)
+               return error;
+
+       get_buffers(buffer, old_buffer);
+       error = fn_for_each_confined(label, profile,
+                       match_mnt(profile, path, buffer, &old_path, old_buffer,
+                                 NULL, flags, NULL, false));
+       put_buffers(buffer, old_buffer);
+       path_put(&old_path);
+
+       return error;
+}
+
+int aa_mount_change_type(struct aa_label *label, const struct path *path,
+                        unsigned long flags)
+{
+       struct aa_profile *profile;
+       char *buffer = NULL;
+       int error;
+
+       AA_BUG(!label);
+       AA_BUG(!path);
+
+       /* These are the flags allowed by do_change_type() */
+       flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
+                 MS_UNBINDABLE);
+
+       get_buffers(buffer);
+       error = fn_for_each_confined(label, profile,
+                       match_mnt(profile, path, buffer, NULL, NULL, NULL,
+                                 flags, NULL, false));
+       put_buffers(buffer);
+
+       return error;
+}
+
+int aa_move_mount(struct aa_label *label, const struct path *path,
+                 const char *orig_name)
+{
+       struct aa_profile *profile;
+       char *buffer = NULL, *old_buffer = NULL;
+       struct path old_path;
+       int error;
+
+       AA_BUG(!label);
+       AA_BUG(!path);
+
+       if (!orig_name || !*orig_name)
+               return -EINVAL;
+
+       error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
+       if (error)
+               return error;
+
+       get_buffers(buffer, old_buffer);
+       error = fn_for_each_confined(label, profile,
+                       match_mnt(profile, path, buffer, &old_path, old_buffer,
+                                 NULL, MS_MOVE, NULL, false));
+       put_buffers(buffer, old_buffer);
+       path_put(&old_path);
+
+       return error;
+}
+
+int aa_new_mount(struct aa_label *label, const char *dev_name,
+                const struct path *path, const char *type, unsigned long flags,
+                void *data)
+{
+       struct aa_profile *profile;
+       char *buffer = NULL, *dev_buffer = NULL;
+       bool binary = true;
+       int error;
+       int requires_dev = 0;
+       struct path tmp_path, *dev_path = NULL;
+
+       AA_BUG(!label);
+       AA_BUG(!path);
+
+       if (type) {
+               struct file_system_type *fstype;
+
+               fstype = get_fs_type(type);
+               if (!fstype)
+                       return -ENODEV;
+               binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
+               requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
+               put_filesystem(fstype);
+
+               if (requires_dev) {
+                       if (!dev_name || !*dev_name)
+                               return -ENOENT;
+
+                       error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path);
+                       if (error)
+                               return error;
+                       dev_path = &tmp_path;
+               }
+       }
+
+       get_buffers(buffer, dev_buffer);
+       if (dev_path) {
+               error = fn_for_each_confined(label, profile,
+                       match_mnt(profile, path, buffer, dev_path, dev_buffer,
+                                 type, flags, data, binary));
+       } else {
+               error = fn_for_each_confined(label, profile,
+                       match_mnt_path_str(profile, path, buffer, dev_name,
+                                          type, flags, data, binary, NULL));
+       }
+       put_buffers(buffer, dev_buffer);
+       if (dev_path)
+               path_put(dev_path);
+
+       return error;
+}
+
+static int profile_umount(struct aa_profile *profile, struct path *path,
+                         char *buffer)
+{
+       struct aa_perms perms = { };
+       const char *name = NULL, *info = NULL;
+       unsigned int state;
+       int error;
+
+       AA_BUG(!profile);
+       AA_BUG(!path);
+
+       error = aa_path_name(path, path_flags(profile, path), buffer, &name,
+                            &info, profile->disconnected);
+       if (error)
+               goto audit;
+
+       state = aa_dfa_match(profile->policy.dfa,
+                            profile->policy.start[AA_CLASS_MOUNT],
+                            name);
+       perms = compute_mnt_perms(profile->policy.dfa, state);
+       if (AA_MAY_UMOUNT & ~perms.allow)
+               error = -EACCES;
+
+audit:
+       return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
+                          AA_MAY_UMOUNT, &perms, info, error);
+}
+
+int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
+{
+       struct aa_profile *profile;
+       char *buffer = NULL;
+       int error;
+       struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
+
+       AA_BUG(!label);
+       AA_BUG(!mnt);
+
+       get_buffers(buffer);
+       error = fn_for_each_confined(label, profile,
+                       profile_umount(profile, &path, buffer));
+       put_buffers(buffer);
+
+       return error;
+}
+
+/* helper fn for transition on pivotroot
+ *
+ * Returns: label for transition or ERR_PTR. Does not return NULL
+ */
+static struct aa_label *build_pivotroot(struct aa_profile *profile,
+                                       const struct path *new_path,
+                                       char *new_buffer,
+                                       const struct path *old_path,
+                                       char *old_buffer)
+{
+       const char *old_name, *new_name = NULL, *info = NULL;
+       const char *trans_name = NULL;
+       struct aa_perms perms = { };
+       unsigned int state;
+       int error;
+
+       AA_BUG(!profile);
+       AA_BUG(!new_path);
+       AA_BUG(!old_path);
+
+       if (profile_unconfined(profile))
+               return aa_get_newest_label(&profile->label);
+
+       error = aa_path_name(old_path, path_flags(profile, old_path),
+                            old_buffer, &old_name, &info,
+                            profile->disconnected);
+       if (error)
+               goto audit;
+       error = aa_path_name(new_path, path_flags(profile, new_path),
+                            new_buffer, &new_name, &info,
+                            profile->disconnected);
+       if (error)
+               goto audit;
+
+       error = -EACCES;
+       state = aa_dfa_match(profile->policy.dfa,
+                            profile->policy.start[AA_CLASS_MOUNT],
+                            new_name);
+       state = aa_dfa_null_transition(profile->policy.dfa, state);
+       state = aa_dfa_match(profile->policy.dfa, state, old_name);
+       perms = compute_mnt_perms(profile->policy.dfa, state);
+
+       if (AA_MAY_PIVOTROOT & perms.allow)
+               error = 0;
+
+audit:
+       error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
+                           NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
+                           &perms, info, error);
+       if (error)
+               return ERR_PTR(error);
+
+       return aa_get_newest_label(&profile->label);
+}
+
+int aa_pivotroot(struct aa_label *label, const struct path *old_path,
+                const struct path *new_path)
+{
+       struct aa_profile *profile;
+       struct aa_label *target = NULL;
+       char *old_buffer = NULL, *new_buffer = NULL, *info = NULL;
+       int error;
+
+       AA_BUG(!label);
+       AA_BUG(!old_path);
+       AA_BUG(!new_path);
+
+       get_buffers(old_buffer, new_buffer);
+       target = fn_label_build(label, profile, GFP_ATOMIC,
+                       build_pivotroot(profile, new_path, new_buffer,
+                                       old_path, old_buffer));
+       if (!target) {
+               info = "label build failed";
+               error = -ENOMEM;
+               goto fail;
+       } else if (!IS_ERR(target)) {
+               error = aa_replace_current_label(target);
+               if (error) {
+                       /* TODO: audit target */
+                       aa_put_label(target);
+                       goto out;
+               }
+       } else
+               /* already audited error */
+               error = PTR_ERR(target);
+out:
+       put_buffers(old_buffer, new_buffer);
+
+       return error;
+
+fail:
+       /* TODO: add back in auditing of new_name and old_name */
+       error = fn_for_each(label, profile,
+                       audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */,
+                                   NULL /* old_name */,
+                                   NULL, NULL,
+                                   0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
+                                   error));
+       goto out;
+}
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
new file mode 100644 (file)
index 0000000..33d5443
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2017 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/label.h"
+#include "include/net.h"
+#include "include/policy.h"
+
+#include "net_names.h"
+
+
+struct aa_sfs_entry aa_sfs_entry_network[] = {
+       AA_SFS_FILE_STRING("af_mask",   AA_SFS_AF_MASK),
+       { }
+};
+
+static const char * const net_mask_names[] = {
+       "unknown",
+       "send",
+       "receive",
+       "unknown",
+
+       "create",
+       "shutdown",
+       "connect",
+       "unknown",
+
+       "setattr",
+       "getattr",
+       "setcred",
+       "getcred",
+
+       "chmod",
+       "chown",
+       "chgrp",
+       "lock",
+
+       "mmap",
+       "mprot",
+       "unknown",
+       "unknown",
+
+       "accept",
+       "bind",
+       "listen",
+       "unknown",
+
+       "setopt",
+       "getopt",
+       "unknown",
+       "unknown",
+
+       "unknown",
+       "unknown",
+       "unknown",
+       "unknown",
+};
+
+
+/* audit callback for net specific fields */
+void audit_net_cb(struct audit_buffer *ab, void *va)
+{
+       struct common_audit_data *sa = va;
+
+       audit_log_format(ab, " family=");
+       if (address_family_names[sa->u.net->family])
+               audit_log_string(ab, address_family_names[sa->u.net->family]);
+       else
+               audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
+       audit_log_format(ab, " sock_type=");
+       if (sock_type_names[aad(sa)->net.type])
+               audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
+       else
+               audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
+       audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
+
+       if (aad(sa)->request & NET_PERMS_MASK) {
+               audit_log_format(ab, " requested_mask=");
+               aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
+                                  net_mask_names, NET_PERMS_MASK);
+
+               if (aad(sa)->denied & NET_PERMS_MASK) {
+                       audit_log_format(ab, " denied_mask=");
+                       aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
+                                          net_mask_names, NET_PERMS_MASK);
+               }
+       }
+       if (aad(sa)->peer) {
+               audit_log_format(ab, " peer=");
+               aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
+                               FLAGS_NONE, GFP_ATOMIC);
+       }
+}
+
+
+/* Generic af perm */
+int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
+                      u32 request, u16 family, int type)
+{
+       struct aa_perms perms = { };
+
+       AA_BUG(family >= AF_MAX);
+       AA_BUG(type < 0 || type >= SOCK_MAX);
+
+       if (profile_unconfined(profile))
+               return 0;
+
+       perms.allow = (profile->net.allow[family] & (1 << type)) ?
+               ALL_PERMS_MASK : 0;
+       perms.audit = (profile->net.audit[family] & (1 << type)) ?
+               ALL_PERMS_MASK : 0;
+       perms.quiet = (profile->net.quiet[family] & (1 << type)) ?
+               ALL_PERMS_MASK : 0;
+       aa_apply_modes_to_perms(profile, &perms);
+
+       return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
+}
+
+int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
+              int type, int protocol)
+{
+       struct aa_profile *profile;
+       DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
+
+       return fn_for_each_confined(label, profile,
+                       aa_profile_af_perm(profile, &sa, request, family,
+                                          type));
+}
+
+static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
+                           struct sock *sk)
+{
+       struct aa_profile *profile;
+       DEFINE_AUDIT_SK(sa, op, sk);
+
+       AA_BUG(!label);
+       AA_BUG(!sk);
+
+       if (unconfined(label))
+               return 0;
+
+       return fn_for_each_confined(label, profile,
+                       aa_profile_af_sk_perm(profile, &sa, request, sk));
+}
+
+int aa_sk_perm(const char *op, u32 request, struct sock *sk)
+{
+       struct aa_label *label;
+       int error;
+
+       AA_BUG(!sk);
+       AA_BUG(in_interrupt());
+
+       /* TODO: switch to begin_current_label ???? */
+       label = begin_current_label_crit_section();
+       error = aa_label_sk_perm(label, op, request, sk);
+       end_current_label_crit_section(label);
+
+       return error;
+}
+
+
+int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
+                     struct socket *sock)
+{
+       AA_BUG(!label);
+       AA_BUG(!sock);
+       AA_BUG(!sock->sk);
+
+       return aa_label_sk_perm(label, op, request, sock->sk);
+}
index 244ea4a4a8f0f73fdfacccd8c49cd55e1f7c695e..4243b0c3f0e4acc6d66c70ea878f32d548bebdd4 100644 (file)
@@ -289,85 +289,6 @@ fail:
        return NULL;
 }
 
-/**
- * aa_new_null_profile - create or find a null-X learning profile
- * @parent: profile that caused this profile to be created (NOT NULL)
- * @hat: true if the null- learning profile is a hat
- * @base: name to base the null profile off of
- * @gfp: type of allocation
- *
- * Find/Create a null- complain mode profile used in learning mode.  The
- * name of the profile is unique and follows the format of parent//null-XXX.
- * where XXX is based on the @name or if that fails or is not supplied
- * a unique number
- *
- * null profiles are added to the profile list but the list does not
- * hold a count on them so that they are automatically released when
- * not in use.
- *
- * Returns: new refcounted profile else NULL on failure
- */
-struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
-                                      const char *base, gfp_t gfp)
-{
-       struct aa_profile *profile;
-       char *name;
-
-       AA_BUG(!parent);
-
-       if (base) {
-               name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base),
-                              gfp);
-               if (name) {
-                       sprintf(name, "%s//null-%s", parent->base.hname, base);
-                       goto name;
-               }
-               /* fall through to try shorter uniq */
-       }
-
-       name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp);
-       if (!name)
-               return NULL;
-       sprintf(name, "%s//null-%x", parent->base.hname,
-               atomic_inc_return(&parent->ns->uniq_null));
-
-name:
-       /* lookup to see if this is a dup creation */
-       profile = aa_find_child(parent, basename(name));
-       if (profile)
-               goto out;
-
-       profile = aa_alloc_profile(name, NULL, gfp);
-       if (!profile)
-               goto fail;
-
-       profile->mode = APPARMOR_COMPLAIN;
-       profile->label.flags |= FLAG_NULL;
-       if (hat)
-               profile->label.flags |= FLAG_HAT;
-       profile->path_flags = parent->path_flags;
-
-       /* released on free_profile */
-       rcu_assign_pointer(profile->parent, aa_get_profile(parent));
-       profile->ns = aa_get_ns(parent->ns);
-       profile->file.dfa = aa_get_dfa(nulldfa);
-       profile->policy.dfa = aa_get_dfa(nulldfa);
-
-       mutex_lock(&profile->ns->lock);
-       __add_profile(&parent->base.profiles, profile);
-       mutex_unlock(&profile->ns->lock);
-
-       /* refcount released by caller */
-out:
-       kfree(name);
-
-       return profile;
-
-fail:
-       aa_free_profile(profile);
-       return NULL;
-}
-
 /* TODO: profile accounting - setup in remove */
 
 /**
@@ -558,6 +479,93 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
        return profile;
 }
 
+/**
+ * aa_new_null_profile - create or find a null-X learning profile
+ * @parent: profile that caused this profile to be created (NOT NULL)
+ * @hat: true if the null- learning profile is a hat
+ * @base: name to base the null profile off of
+ * @gfp: type of allocation
+ *
+ * Find/Create a null- complain mode profile used in learning mode.  The
+ * name of the profile is unique and follows the format of parent//null-XXX.
+ * where XXX is based on the @name or if that fails or is not supplied
+ * a unique number
+ *
+ * null profiles are added to the profile list but the list does not
+ * hold a count on them so that they are automatically released when
+ * not in use.
+ *
+ * Returns: new refcounted profile else NULL on failure
+ */
+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
+                                      const char *base, gfp_t gfp)
+{
+       struct aa_profile *p, *profile;
+       const char *bname;
+       char *name;
+
+       AA_BUG(!parent);
+
+       if (base) {
+               name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base),
+                              gfp);
+               if (name) {
+                       sprintf(name, "%s//null-%s", parent->base.hname, base);
+                       goto name;
+               }
+               /* fall through to try shorter uniq */
+       }
+
+       name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp);
+       if (!name)
+               return NULL;
+       sprintf(name, "%s//null-%x", parent->base.hname,
+               atomic_inc_return(&parent->ns->uniq_null));
+
+name:
+       /* lookup to see if this is a dup creation */
+       bname = basename(name);
+       profile = aa_find_child(parent, bname);
+       if (profile)
+               goto out;
+
+       profile = aa_alloc_profile(name, NULL, gfp);
+       if (!profile)
+               goto fail;
+
+       profile->mode = APPARMOR_COMPLAIN;
+       profile->label.flags |= FLAG_NULL;
+       if (hat)
+               profile->label.flags |= FLAG_HAT;
+       profile->path_flags = parent->path_flags;
+
+       /* released on free_profile */
+       rcu_assign_pointer(profile->parent, aa_get_profile(parent));
+       profile->ns = aa_get_ns(parent->ns);
+       profile->file.dfa = aa_get_dfa(nulldfa);
+       profile->policy.dfa = aa_get_dfa(nulldfa);
+
+       mutex_lock(&profile->ns->lock);
+       p = __find_child(&parent->base.profiles, bname);
+       if (p) {
+               aa_free_profile(profile);
+               profile = aa_get_profile(p);
+       } else {
+               __add_profile(&parent->base.profiles, profile);
+       }
+       mutex_unlock(&profile->ns->lock);
+
+       /* refcount released by caller */
+out:
+       kfree(name);
+
+       return profile;
+
+fail:
+       aa_free_profile(profile);
+       return NULL;
+}
+
 /**
  * replacement_allowed - test to see if replacement is allowed
  * @profile: profile to test if it can be replaced  (MAYBE NULL)
index 351d3bab3a3d2565aa970fe7011453c8fb721ea4..62a3589c62ab624156c0c01eaa8cadd72276866a 100644 (file)
@@ -112,6 +112,8 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name)
        ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR |
                FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED;
        ns->unconfined->mode = APPARMOR_UNCONFINED;
+       ns->unconfined->file.dfa = aa_get_dfa(nulldfa);
+       ns->unconfined->policy.dfa = aa_get_dfa(nulldfa);
 
        /* ns and ns->unconfined share ns->unconfined refcount */
        ns->unconfined->ns = ns;
index c600f4dd1783252a1fc429379cb1cca8b9728c9b..5a2aec358322a930a5e6473a9e22acd64462298b 100644 (file)
@@ -85,9 +85,9 @@ static void audit_cb(struct audit_buffer *ab, void *va)
                audit_log_format(ab, " ns=");
                audit_log_untrustedstring(ab, aad(sa)->iface.ns);
        }
-       if (aad(sa)->iface.name) {
+       if (aad(sa)->name) {
                audit_log_format(ab, " name=");
-               audit_log_untrustedstring(ab, aad(sa)->iface.name);
+               audit_log_untrustedstring(ab, aad(sa)->name);
        }
        if (aad(sa)->iface.pos)
                audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos);
@@ -114,9 +114,9 @@ static int audit_iface(struct aa_profile *new, const char *ns_name,
                aad(&sa)->iface.pos = e->pos - e->start;
        aad(&sa)->iface.ns = ns_name;
        if (new)
-               aad(&sa)->iface.name = new->base.hname;
+               aad(&sa)->name = new->base.hname;
        else
-               aad(&sa)->iface.name = name;
+               aad(&sa)->name = name;
        aad(&sa)->info = info;
        aad(&sa)->error = error;
 
@@ -275,6 +275,19 @@ fail:
        return 0;
 }
 
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
+{
+       if (unpack_nameX(e, AA_U16, name)) {
+               if (!inbounds(e, sizeof(u16)))
+                       return 0;
+               if (data)
+                       *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
+               e->pos += sizeof(u16);
+               return 1;
+       }
+       return 0;
+}
+
 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
 {
        if (unpack_nameX(e, AA_U32, name)) {
@@ -448,7 +461,7 @@ fail:
  */
 static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
 {
-       void *pos = e->pos;
+       void *saved_pos = e->pos;
 
        /* exec table is optional */
        if (unpack_nameX(e, AA_STRUCT, "xtable")) {
@@ -511,7 +524,7 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
 
 fail:
        aa_free_domain_entries(&profile->file.trans);
-       e->pos = pos;
+       e->pos = saved_pos;
        return 0;
 }
 
@@ -583,7 +596,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
 {
        struct aa_profile *profile = NULL;
        const char *tmpname, *tmpns = NULL, *name = NULL;
-       size_t ns_len;
+       const char *info = "failed to unpack profile";
+       size_t size = 0, ns_len;
        struct rhashtable_params params = { 0 };
        char *key = NULL;
        struct aa_data *data;
@@ -604,8 +618,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
        tmpname = aa_splitn_fqname(name, strlen(name), &tmpns, &ns_len);
        if (tmpns) {
                *ns_name = kstrndup(tmpns, ns_len, GFP_KERNEL);
-               if (!*ns_name)
+               if (!*ns_name) {
+                       info = "out of memory";
                        goto fail;
+               }
                name = tmpname;
        }
 
@@ -624,12 +640,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
        if (IS_ERR(profile->xmatch)) {
                error = PTR_ERR(profile->xmatch);
                profile->xmatch = NULL;
+               info = "bad xmatch";
                goto fail;
        }
        /* xmatch_len is not optional if xmatch is set */
        if (profile->xmatch) {
-               if (!unpack_u32(e, &tmp, NULL))
+               if (!unpack_u32(e, &tmp, NULL)) {
+                       info = "missing xmatch len";
                        goto fail;
+               }
                profile->xmatch_len = tmp;
        }
 
@@ -637,8 +656,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
        (void) unpack_str(e, &profile->disconnected, "disconnected");
 
        /* per profile debug flags (complain, audit) */
-       if (!unpack_nameX(e, AA_STRUCT, "flags"))
+       if (!unpack_nameX(e, AA_STRUCT, "flags")) {
+               info = "profile missing flags";
                goto fail;
+       }
+       info = "failed to unpack profile flags";
        if (!unpack_u32(e, &tmp, NULL))
                goto fail;
        if (tmp & PACKED_FLAG_HAT)
@@ -667,6 +689,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
                /* set a default value if path_flags field is not present */
                profile->path_flags = PATH_MEDIATE_DELETED;
 
+       info = "failed to unpack profile capabilities";
        if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL))
                goto fail;
        if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
@@ -676,6 +699,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
        if (!unpack_u32(e, &tmpcap.cap[0], NULL))
                goto fail;
 
+       info = "failed to unpack upper profile capabilities";
        if (unpack_nameX(e, AA_STRUCT, "caps64")) {
                /* optional upper half of 64 bit caps */
                if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL))
@@ -690,6 +714,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
                        goto fail;
        }
 
+       info = "failed to unpack extended profile capabilities";
        if (unpack_nameX(e, AA_STRUCT, "capsx")) {
                /* optional extended caps mediation mask */
                if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
@@ -700,11 +725,46 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
                        goto fail;
        }
 
-       if (!unpack_rlimits(e, profile))
+       if (!unpack_rlimits(e, profile)) {
+               info = "failed to unpack profile rlimits";
                goto fail;
+       }
+
+       size = unpack_array(e, "net_allowed_af");
+       if (size) {
+
+               for (i = 0; i < size; i++) {
+                       /* discard extraneous rules that this kernel will
+                        * never request
+                        */
+                       if (i >= AF_MAX) {
+                               u16 tmp;
+
+                               if (!unpack_u16(e, &tmp, NULL) ||
+                                   !unpack_u16(e, &tmp, NULL) ||
+                                   !unpack_u16(e, &tmp, NULL))
+                                       goto fail;
+                               continue;
+                       }
+                       if (!unpack_u16(e, &profile->net.allow[i], NULL))
+                               goto fail;
+                       if (!unpack_u16(e, &profile->net.audit[i], NULL))
+                               goto fail;
+                       if (!unpack_u16(e, &profile->net.quiet[i], NULL))
+                               goto fail;
+               }
+               if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+                       goto fail;
+       }
+       if (VERSION_LT(e->version, v7)) {
+               /* pre v7 policy always allowed these */
+               profile->net.allow[AF_UNIX] = 0xffff;
+               profile->net.allow[AF_NETLINK] = 0xffff;
+       }
 
        if (unpack_nameX(e, AA_STRUCT, "policydb")) {
                /* generic policy dfa - optional and may be NULL */
+               info = "failed to unpack policydb";
                profile->policy.dfa = unpack_dfa(e);
                if (IS_ERR(profile->policy.dfa)) {
                        error = PTR_ERR(profile->policy.dfa);
@@ -734,6 +794,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
        if (IS_ERR(profile->file.dfa)) {
                error = PTR_ERR(profile->file.dfa);
                profile->file.dfa = NULL;
+               info = "failed to unpack profile file rules";
                goto fail;
        } else if (profile->file.dfa) {
                if (!unpack_u32(e, &profile->file.start, "dfa_start"))
@@ -746,10 +807,13 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
        } else
                profile->file.dfa = aa_get_dfa(nulldfa);
 
-       if (!unpack_trans_table(e, profile))
+       if (!unpack_trans_table(e, profile)) {
+               info = "failed to unpack profile transition table";
                goto fail;
+       }
 
        if (unpack_nameX(e, AA_STRUCT, "data")) {
+               info = "out of memory";
                profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL);
                if (!profile->data)
                        goto fail;
@@ -761,8 +825,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
                params.hashfn = strhash;
                params.obj_cmpfn = datacmp;
 
-               if (rhashtable_init(profile->data, &params))
+               if (rhashtable_init(profile->data, &params)) {
+                       info = "failed to init key, value hash table";
                        goto fail;
+               }
 
                while (unpack_strdup(e, &key, NULL)) {
                        data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -784,12 +850,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
                                               profile->data->p);
                }
 
-               if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+               if (!unpack_nameX(e, AA_STRUCTEND, NULL)) {
+                       info = "failed to unpack end of key, value data table";
                        goto fail;
+               }
        }
 
-       if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+       if (!unpack_nameX(e, AA_STRUCTEND, NULL)) {
+               info = "failed to unpack end of profile";
                goto fail;
+       }
 
        return profile;
 
@@ -798,8 +868,7 @@ fail:
                name = NULL;
        else if (!name)
                name = "unknown";
-       audit_iface(profile, NULL, name, "failed to unpack profile", e,
-                   error);
+       audit_iface(profile, NULL, name, info, e, error);
        aa_free_profile(profile);
 
        return ERR_PTR(error);
@@ -832,7 +901,7 @@ static int verify_header(struct aa_ext *e, int required, const char **ns)
         * if not specified use previous version
         * Mask off everything that is not kernel abi version
         */
-       if (VERSION_LT(e->version, v5) && VERSION_GT(e->version, v7)) {
+       if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v7)) {
                audit_iface(NULL, NULL, NULL, "unsupported interface version",
                            e, error);
                return error;
index 6bf72b175b49caf336e7ef8f3d83cf256c955120..c25e0d27537f87ea7d7d216b9448f47b83e26608 100644 (file)
@@ -294,10 +294,10 @@ int cap_capset(struct cred *new,
  *
  * Determine if an inode having a change applied that's marked ATTR_KILL_PRIV
  * affects the security markings on that inode, and if it is, should
- * inode_killpriv() be invoked or the change rejected?
+ * inode_killpriv() be invoked or the change rejected.
  *
- * Returns 0 if granted; +ve if granted, but inode_killpriv() is required; and
- * -ve to deny the change.
+ * Returns 1 if security.capability has a value, meaning inode_killpriv()
+ * is required, 0 otherwise, meaning inode_killpriv() is not required.
  */
 int cap_inode_need_killpriv(struct dentry *dentry)
 {
index a7a23b5541f85a4994e0cc83d7d132e8a5681938..91eafada3164ec9dc77074565c156988c4101554 100644 (file)
@@ -45,10 +45,8 @@ config BIG_KEYS
        bool "Large payload keys"
        depends on KEYS
        depends on TMPFS
-       depends on (CRYPTO_ANSI_CPRNG = y || CRYPTO_DRBG = y)
        select CRYPTO_AES
-       select CRYPTO_ECB
-       select CRYPTO_RNG
+       select CRYPTO_GCM
        help
          This option provides support for holding large keys within the kernel
          (for example Kerberos ticket caches).  The data may be stored out to
index 6acb00f6f22cdcd223426756a49deebf53b86595..e607830b6154ce4c8dbcd5563fb0d3607f680c8f 100644 (file)
@@ -1,5 +1,6 @@
 /* Large capacity key type
  *
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
  * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
 #include <linux/shmem_fs.h>
 #include <linux/err.h>
 #include <linux/scatterlist.h>
+#include <linux/random.h>
 #include <keys/user-type.h>
 #include <keys/big_key-type.h>
-#include <crypto/rng.h>
-#include <crypto/skcipher.h>
+#include <crypto/aead.h>
 
 /*
  * Layout of key payload words.
@@ -49,7 +50,12 @@ enum big_key_op {
 /*
  * Key size for big_key data encryption
  */
-#define ENC_KEY_SIZE   16
+#define ENC_KEY_SIZE 32
+
+/*
+ * Authentication tag length
+ */
+#define ENC_AUTHTAG_SIZE 16
 
 /*
  * big_key defined keys take an arbitrary string as the description and an
@@ -64,57 +70,62 @@ struct key_type key_type_big_key = {
        .destroy                = big_key_destroy,
        .describe               = big_key_describe,
        .read                   = big_key_read,
+       /* no ->update(); don't add it without changing big_key_crypt() nonce */
 };
 
 /*
- * Crypto names for big_key data encryption
+ * Crypto names for big_key data authenticated encryption
  */
-static const char big_key_rng_name[] = "stdrng";
-static const char big_key_alg_name[] = "ecb(aes)";
+static const char big_key_alg_name[] = "gcm(aes)";
 
 /*
- * Crypto algorithms for big_key data encryption
+ * Crypto algorithms for big_key data authenticated encryption
  */
-static struct crypto_rng *big_key_rng;
-static struct crypto_skcipher *big_key_skcipher;
+static struct crypto_aead *big_key_aead;
 
 /*
- * Generate random key to encrypt big_key data
+ * Since changing the key affects the entire object, we need a mutex.
  */
-static inline int big_key_gen_enckey(u8 *key)
-{
-       return crypto_rng_get_bytes(big_key_rng, key, ENC_KEY_SIZE);
-}
+static DEFINE_MUTEX(big_key_aead_lock);
 
 /*
  * Encrypt/decrypt big_key data
  */
 static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
 {
-       int ret = -EINVAL;
+       int ret;
        struct scatterlist sgio;
-       SKCIPHER_REQUEST_ON_STACK(req, big_key_skcipher);
-
-       if (crypto_skcipher_setkey(big_key_skcipher, key, ENC_KEY_SIZE)) {
+       struct aead_request *aead_req;
+       /* We always use a zero nonce. The reason we can get away with this is
+        * because we're using a different randomly generated key for every
+        * different encryption. Notably, too, key_type_big_key doesn't define
+        * an .update function, so there's no chance we'll wind up reusing the
+        * key to encrypt updated data. Simply put: one key, one encryption.
+        */
+       u8 zero_nonce[crypto_aead_ivsize(big_key_aead)];
+
+       aead_req = aead_request_alloc(big_key_aead, GFP_KERNEL);
+       if (!aead_req)
+               return -ENOMEM;
+
+       memset(zero_nonce, 0, sizeof(zero_nonce));
+       sg_init_one(&sgio, data, datalen + (op == BIG_KEY_ENC ? ENC_AUTHTAG_SIZE : 0));
+       aead_request_set_crypt(aead_req, &sgio, &sgio, datalen, zero_nonce);
+       aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
+       aead_request_set_ad(aead_req, 0);
+
+       mutex_lock(&big_key_aead_lock);
+       if (crypto_aead_setkey(big_key_aead, key, ENC_KEY_SIZE)) {
                ret = -EAGAIN;
                goto error;
        }
-
-       skcipher_request_set_tfm(req, big_key_skcipher);
-       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
-                                     NULL, NULL);
-
-       sg_init_one(&sgio, data, datalen);
-       skcipher_request_set_crypt(req, &sgio, &sgio, datalen, NULL);
-
        if (op == BIG_KEY_ENC)
-               ret = crypto_skcipher_encrypt(req);
+               ret = crypto_aead_encrypt(aead_req);
        else
-               ret = crypto_skcipher_decrypt(req);
-
-       skcipher_request_zero(req);
-
+               ret = crypto_aead_decrypt(aead_req);
 error:
+       mutex_unlock(&big_key_aead_lock);
+       aead_request_free(aead_req);
        return ret;
 }
 
@@ -146,16 +157,13 @@ int big_key_preparse(struct key_preparsed_payload *prep)
                 *
                 * File content is stored encrypted with randomly generated key.
                 */
-               size_t enclen = ALIGN(datalen, crypto_skcipher_blocksize(big_key_skcipher));
+               size_t enclen = datalen + ENC_AUTHTAG_SIZE;
                loff_t pos = 0;
 
-               /* prepare aligned data to encrypt */
                data = kmalloc(enclen, GFP_KERNEL);
                if (!data)
                        return -ENOMEM;
-
                memcpy(data, prep->data, datalen);
-               memset(data + datalen, 0x00, enclen - datalen);
 
                /* generate random key */
                enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL);
@@ -163,13 +171,12 @@ int big_key_preparse(struct key_preparsed_payload *prep)
                        ret = -ENOMEM;
                        goto error;
                }
-
-               ret = big_key_gen_enckey(enckey);
-               if (ret)
+               ret = get_random_bytes_wait(enckey, ENC_KEY_SIZE);
+               if (unlikely(ret))
                        goto err_enckey;
 
                /* encrypt aligned data */
-               ret = big_key_crypt(BIG_KEY_ENC, data, enclen, enckey);
+               ret = big_key_crypt(BIG_KEY_ENC, data, datalen, enckey);
                if (ret)
                        goto err_enckey;
 
@@ -195,7 +202,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
                *path = file->f_path;
                path_get(path);
                fput(file);
-               kfree(data);
+               kzfree(data);
        } else {
                /* Just store the data in a buffer */
                void *data = kmalloc(datalen, GFP_KERNEL);
@@ -211,9 +218,9 @@ int big_key_preparse(struct key_preparsed_payload *prep)
 err_fput:
        fput(file);
 err_enckey:
-       kfree(enckey);
+       kzfree(enckey);
 error:
-       kfree(data);
+       kzfree(data);
        return ret;
 }
 
@@ -227,7 +234,7 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
 
                path_put(path);
        }
-       kfree(prep->payload.data[big_key_data]);
+       kzfree(prep->payload.data[big_key_data]);
 }
 
 /*
@@ -259,7 +266,7 @@ void big_key_destroy(struct key *key)
                path->mnt = NULL;
                path->dentry = NULL;
        }
-       kfree(key->payload.data[big_key_data]);
+       kzfree(key->payload.data[big_key_data]);
        key->payload.data[big_key_data] = NULL;
 }
 
@@ -295,7 +302,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
                struct file *file;
                u8 *data;
                u8 *enckey = (u8 *)key->payload.data[big_key_data];
-               size_t enclen = ALIGN(datalen, crypto_skcipher_blocksize(big_key_skcipher));
+               size_t enclen = datalen + ENC_AUTHTAG_SIZE;
                loff_t pos = 0;
 
                data = kmalloc(enclen, GFP_KERNEL);
@@ -328,7 +335,7 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
 err_fput:
                fput(file);
 error:
-               kfree(data);
+               kzfree(data);
        } else {
                ret = datalen;
                if (copy_to_user(buffer, key->payload.data[big_key_data],
@@ -344,47 +351,31 @@ error:
  */
 static int __init big_key_init(void)
 {
-       struct crypto_skcipher *cipher;
-       struct crypto_rng *rng;
        int ret;
 
-       rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
-       if (IS_ERR(rng)) {
-               pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng));
-               return PTR_ERR(rng);
-       }
-
-       big_key_rng = rng;
-
-       /* seed RNG */
-       ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
-       if (ret) {
-               pr_err("Can't reset rng: %d\n", ret);
-               goto error_rng;
-       }
-
        /* init block cipher */
-       cipher = crypto_alloc_skcipher(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(cipher)) {
-               ret = PTR_ERR(cipher);
+       big_key_aead = crypto_alloc_aead(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(big_key_aead)) {
+               ret = PTR_ERR(big_key_aead);
                pr_err("Can't alloc crypto: %d\n", ret);
-               goto error_rng;
+               return ret;
+       }
+       ret = crypto_aead_setauthsize(big_key_aead, ENC_AUTHTAG_SIZE);
+       if (ret < 0) {
+               pr_err("Can't set crypto auth tag len: %d\n", ret);
+               goto free_aead;
        }
-
-       big_key_skcipher = cipher;
 
        ret = register_key_type(&key_type_big_key);
        if (ret < 0) {
                pr_err("Can't register type: %d\n", ret);
-               goto error_cipher;
+               goto free_aead;
        }
 
        return 0;
 
-error_cipher:
-       crypto_free_skcipher(big_key_skcipher);
-error_rng:
-       crypto_free_rng(big_key_rng);
+free_aead:
+       crypto_free_aead(big_key_aead);
        return ret;
 }
 
index 1c02c65470384aa076e2de6885ecba356eb44342..503adbae7b0dd0b096aa7fd672fddb0d3513d115 100644 (file)
@@ -141,7 +141,7 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
 extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx);
 extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx);
 
-extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
+extern struct key *find_keyring_by_name(const char *name, bool uid_keyring);
 
 extern int install_user_keyrings(void);
 extern int install_thread_keyring_to_cred(struct cred *);
index 83da68d98b40b452a1c8b37121a6ca270387d4f6..eb914a838840df416f26af2c0cd73f87c60a5032 100644 (file)
@@ -54,10 +54,10 @@ void __key_check(const struct key *key)
 struct key_user *key_user_lookup(kuid_t uid)
 {
        struct key_user *candidate = NULL, *user;
-       struct rb_node *parent = NULL;
-       struct rb_node **p;
+       struct rb_node *parent, **p;
 
 try_again:
+       parent = NULL;
        p = &key_user_tree.rb_node;
        spin_lock(&key_user_lock);
 
@@ -302,6 +302,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
                key->flags |= 1 << KEY_FLAG_IN_QUOTA;
        if (flags & KEY_ALLOC_BUILT_IN)
                key->flags |= 1 << KEY_FLAG_BUILTIN;
+       if (flags & KEY_ALLOC_UID_KEYRING)
+               key->flags |= 1 << KEY_FLAG_UID_KEYRING;
 
 #ifdef KEY_DEBUGGING
        key->magic = KEY_DEBUG_MAGIC;
index ab0b337c84b4c02e4856719398edb94d1caf101a..365ff85d7e27122db220fad6d633f8e0b352209f 100644 (file)
@@ -766,12 +766,17 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
 
        key = key_ref_to_ptr(key_ref);
 
+       if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
+               ret = -ENOKEY;
+               goto error2;
+       }
+
        /* see if we can read it directly */
        ret = key_permission(key_ref, KEY_NEED_READ);
        if (ret == 0)
                goto can_read_key;
        if (ret != -EACCES)
-               goto error;
+               goto error2;
 
        /* we can't; see if it's searchable from this process's keyrings
         * - we automatically take account of the fact that it may be
@@ -1406,11 +1411,9 @@ long keyctl_assume_authority(key_serial_t id)
        }
 
        ret = keyctl_change_reqkey_auth(authkey);
-       if (ret < 0)
-               goto error;
+       if (ret == 0)
+               ret = authkey->serial;
        key_put(authkey);
-
-       ret = authkey->serial;
 error:
        return ret;
 }
index de81793f9920787101dec77eca28ddfbe91ebbc7..4fa82a8a9c0e6cb778a08874724ea546cd602ade 100644 (file)
@@ -423,7 +423,7 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m)
 }
 
 struct keyring_read_iterator_context {
-       size_t                  qty;
+       size_t                  buflen;
        size_t                  count;
        key_serial_t __user     *buffer;
 };
@@ -435,9 +435,9 @@ static int keyring_read_iterator(const void *object, void *data)
        int ret;
 
        kenter("{%s,%d},,{%zu/%zu}",
-              key->type->name, key->serial, ctx->count, ctx->qty);
+              key->type->name, key->serial, ctx->count, ctx->buflen);
 
-       if (ctx->count >= ctx->qty)
+       if (ctx->count >= ctx->buflen)
                return 1;
 
        ret = put_user(key->serial, ctx->buffer);
@@ -472,16 +472,12 @@ static long keyring_read(const struct key *keyring,
                return 0;
 
        /* Calculate how much data we could return */
-       ctx.qty = nr_keys * sizeof(key_serial_t);
-
        if (!buffer || !buflen)
-               return ctx.qty;
-
-       if (buflen > ctx.qty)
-               ctx.qty = buflen;
+               return nr_keys * sizeof(key_serial_t);
 
        /* Copy the IDs of the subscribed keys into the buffer */
        ctx.buffer = (key_serial_t __user *)buffer;
+       ctx.buflen = buflen;
        ctx.count = 0;
        ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx);
        if (ret < 0) {
@@ -1101,15 +1097,15 @@ found:
 /*
  * Find a keyring with the specified name.
  *
- * All named keyrings in the current user namespace are searched, provided they
- * grant Search permission directly to the caller (unless this check is
- * skipped).  Keyrings whose usage points have reached zero or who have been
- * revoked are skipped.
+ * Only keyrings that have nonzero refcount, are not revoked, and are owned by a
+ * user in the current user namespace are considered.  If @uid_keyring is %true,
+ * the keyring additionally must have been allocated as a user or user session
+ * keyring; otherwise, it must grant Search permission directly to the caller.
  *
  * Returns a pointer to the keyring with the keyring's refcount having being
  * incremented on success.  -ENOKEY is returned if a key could not be found.
  */
-struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
+struct key *find_keyring_by_name(const char *name, bool uid_keyring)
 {
        struct key *keyring;
        int bucket;
@@ -1137,10 +1133,15 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
                        if (strcmp(keyring->description, name) != 0)
                                continue;
 
-                       if (!skip_perm_check &&
-                           key_permission(make_key_ref(keyring, 0),
-                                          KEY_NEED_SEARCH) < 0)
-                               continue;
+                       if (uid_keyring) {
+                               if (!test_bit(KEY_FLAG_UID_KEYRING,
+                                             &keyring->flags))
+                                       continue;
+                       } else {
+                               if (key_permission(make_key_ref(keyring, 0),
+                                                  KEY_NEED_SEARCH) < 0)
+                                       continue;
+                       }
 
                        /* we've got a match but we might end up racing with
                         * key_cleanup() if the keyring is currently 'dead'
index bf08d02b6646ae2077b15903471bfb4575b04f5a..de834309d100206bedca18c84493af6fdb665d7a 100644 (file)
@@ -187,7 +187,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
        struct keyring_search_context ctx = {
                .index_key.type         = key->type,
                .index_key.description  = key->description,
-               .cred                   = current_cred(),
+               .cred                   = m->file->f_cred,
                .match_data.cmp         = lookup_user_key_possessed,
                .match_data.raw_data    = key,
                .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
@@ -207,11 +207,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
                }
        }
 
-       /* check whether the current task is allowed to view the key (assuming
-        * non-possession)
-        * - the caller holds a spinlock, and thus the RCU read lock, making our
-        *   access to __current_cred() safe
-        */
+       /* check whether the current task is allowed to view the key */
        rc = key_task_permission(key_ref, ctx.cred, KEY_NEED_VIEW);
        if (rc < 0)
                return 0;
index 86bced9fdbdf22eb60170584d87730e1179a2744..293d3598153bf0c8611f319f4c1d7c50f364e600 100644 (file)
@@ -77,7 +77,8 @@ int install_user_keyrings(void)
                if (IS_ERR(uid_keyring)) {
                        uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID,
                                                    cred, user_keyring_perm,
-                                                   KEY_ALLOC_IN_QUOTA,
+                                                   KEY_ALLOC_UID_KEYRING |
+                                                       KEY_ALLOC_IN_QUOTA,
                                                    NULL, NULL);
                        if (IS_ERR(uid_keyring)) {
                                ret = PTR_ERR(uid_keyring);
@@ -94,7 +95,8 @@ int install_user_keyrings(void)
                        session_keyring =
                                keyring_alloc(buf, user->uid, INVALID_GID,
                                              cred, user_keyring_perm,
-                                             KEY_ALLOC_IN_QUOTA,
+                                             KEY_ALLOC_UID_KEYRING |
+                                                 KEY_ALLOC_IN_QUOTA,
                                              NULL, NULL);
                        if (IS_ERR(session_keyring)) {
                                ret = PTR_ERR(session_keyring);
index afe9d22ab3611f2dc621db0092e1b102e005be78..6ebf1af8fce963eeb0cc4c423c153318096e65a6 100644 (file)
@@ -120,6 +120,18 @@ static void request_key_auth_revoke(struct key *key)
        }
 }
 
+static void free_request_key_auth(struct request_key_auth *rka)
+{
+       if (!rka)
+               return;
+       key_put(rka->target_key);
+       key_put(rka->dest_keyring);
+       if (rka->cred)
+               put_cred(rka->cred);
+       kfree(rka->callout_info);
+       kfree(rka);
+}
+
 /*
  * Destroy an instantiation authorisation token key.
  */
@@ -129,15 +141,7 @@ static void request_key_auth_destroy(struct key *key)
 
        kenter("{%d}", key->serial);
 
-       if (rka->cred) {
-               put_cred(rka->cred);
-               rka->cred = NULL;
-       }
-
-       key_put(rka->target_key);
-       key_put(rka->dest_keyring);
-       kfree(rka->callout_info);
-       kfree(rka);
+       free_request_key_auth(rka);
 }
 
 /*
@@ -151,22 +155,18 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
        const struct cred *cred = current->cred;
        struct key *authkey = NULL;
        char desc[20];
-       int ret;
+       int ret = -ENOMEM;
 
        kenter("%d,", target->serial);
 
        /* allocate a auth record */
-       rka = kmalloc(sizeof(*rka), GFP_KERNEL);
-       if (!rka) {
-               kleave(" = -ENOMEM");
-               return ERR_PTR(-ENOMEM);
-       }
-       rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
-       if (!rka->callout_info) {
-               kleave(" = -ENOMEM");
-               kfree(rka);
-               return ERR_PTR(-ENOMEM);
-       }
+       rka = kzalloc(sizeof(*rka), GFP_KERNEL);
+       if (!rka)
+               goto error;
+       rka->callout_info = kmemdup(callout_info, callout_len, GFP_KERNEL);
+       if (!rka->callout_info)
+               goto error_free_rka;
+       rka->callout_len = callout_len;
 
        /* see if the calling process is already servicing the key request of
         * another process */
@@ -176,8 +176,12 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 
                /* if the auth key has been revoked, then the key we're
                 * servicing is already instantiated */
-               if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))
-                       goto auth_key_revoked;
+               if (test_bit(KEY_FLAG_REVOKED,
+                            &cred->request_key_auth->flags)) {
+                       up_read(&cred->request_key_auth->sem);
+                       ret = -EKEYREVOKED;
+                       goto error_free_rka;
+               }
 
                irka = cred->request_key_auth->payload.data[0];
                rka->cred = get_cred(irka->cred);
@@ -193,8 +197,6 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
 
        rka->target_key = key_get(target);
        rka->dest_keyring = key_get(dest_keyring);
-       memcpy(rka->callout_info, callout_info, callout_len);
-       rka->callout_len = callout_len;
 
        /* allocate the auth key */
        sprintf(desc, "%x", target->serial);
@@ -205,32 +207,22 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
                            KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA, NULL);
        if (IS_ERR(authkey)) {
                ret = PTR_ERR(authkey);
-               goto error_alloc;
+               goto error_free_rka;
        }
 
        /* construct the auth key */
        ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);
        if (ret < 0)
-               goto error_inst;
+               goto error_put_authkey;
 
        kleave(" = {%d,%d}", authkey->serial, refcount_read(&authkey->usage));
        return authkey;
 
-auth_key_revoked:
-       up_read(&cred->request_key_auth->sem);
-       kfree(rka->callout_info);
-       kfree(rka);
-       kleave("= -EKEYREVOKED");
-       return ERR_PTR(-EKEYREVOKED);
-
-error_inst:
-       key_revoke(authkey);
+error_put_authkey:
        key_put(authkey);
-error_alloc:
-       key_put(rka->target_key);
-       key_put(rka->dest_keyring);
-       kfree(rka->callout_info);
-       kfree(rka);
+error_free_rka:
+       free_request_key_auth(rka);
+error:
        kleave("= %d", ret);
        return ERR_PTR(ret);
 }
index 69d09c39bbcd00858121ebf9f6bb1f7a57ff20e1..cd7359e23d869465d1cb70b637c64c85283e37ac 100644 (file)
@@ -88,6 +88,12 @@ struct kvm_s390_io_adapter_req {
 /* kvm attributes for KVM_S390_VM_TOD */
 #define KVM_S390_VM_TOD_LOW            0
 #define KVM_S390_VM_TOD_HIGH           1
+#define KVM_S390_VM_TOD_EXT            2
+
+struct kvm_s390_vm_tod_clock {
+       __u8  epoch_idx;
+       __u64 tod;
+};
 
 /* kvm attributes for KVM_S390_VM_CPU_MODEL */
 /* processor related attributes are r/w */
index 8ea315a11fe0d4461abe7aeea2738be97a79b189..2519c6c801c917d7a30b3826c86679edf18616d5 100644 (file)
 
 #define X86_FEATURE_HW_PSTATE  ( 7*32+ 8) /* AMD HW-PState */
 #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
+#define X86_FEATURE_SME                ( 7*32+10) /* AMD Secure Memory Encryption */
 
 #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
 #define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
 #define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
 #define X86_FEATURE_AVIC       (15*32+13) /* Virtual Interrupt Controller */
 #define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */
+#define X86_FEATURE_VGIF       (15*32+16) /* Virtual GIF */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
 #define X86_FEATURE_AVX512VBMI  (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
index 5dff775af7cd6456f7177d9ce5888ae78dc6bc10..c10c9128f54e6b7296014a74e7a253a1eedaacd9 100644 (file)
 # define DISABLE_K6_MTRR       (1<<(X86_FEATURE_K6_MTRR & 31))
 # define DISABLE_CYRIX_ARR     (1<<(X86_FEATURE_CYRIX_ARR & 31))
 # define DISABLE_CENTAUR_MCR   (1<<(X86_FEATURE_CENTAUR_MCR & 31))
+# define DISABLE_PCID          0
 #else
 # define DISABLE_VME           0
 # define DISABLE_K6_MTRR       0
 # define DISABLE_CYRIX_ARR     0
 # define DISABLE_CENTAUR_MCR   0
+# define DISABLE_PCID          (1<<(X86_FEATURE_PCID & 31))
 #endif /* CONFIG_X86_64 */
 
 #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
@@ -49,7 +51,7 @@
 #define DISABLED_MASK1 0
 #define DISABLED_MASK2 0
 #define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR)
-#define DISABLED_MASK4 0
+#define DISABLED_MASK4 (DISABLE_PCID)
 #define DISABLED_MASK5 0
 #define DISABLED_MASK6 0
 #define DISABLED_MASK7 0
diff --git a/tools/include/asm-generic/hugetlb_encode.h b/tools/include/asm-generic/hugetlb_encode.h
new file mode 100644 (file)
index 0000000..e4732d3
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _ASM_GENERIC_HUGETLB_ENCODE_H_
+#define _ASM_GENERIC_HUGETLB_ENCODE_H_
+
+/*
+ * Several system calls take a flag to request "hugetlb" huge pages.
+ * Without further specification, these system calls will use the
+ * system's default huge page size.  If a system supports multiple
+ * huge page sizes, the desired huge page size can be specified in
+ * bits [26:31] of the flag arguments.  The value in these 6 bits
+ * will encode the log2 of the huge page size.
+ *
+ * The following definitions are associated with this huge page size
+ * encoding in flag arguments.  System call specific header files
+ * that use this encoding should include this file.  They can then
+ * provide definitions based on these with their own specific prefix.
+ * for example:
+ * #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
+ */
+
+#define HUGETLB_FLAG_ENCODE_SHIFT      26
+#define HUGETLB_FLAG_ENCODE_MASK       0x3f
+
+#define HUGETLB_FLAG_ENCODE_64KB       (16 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_512KB      (19 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_1MB                (20 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_2MB                (21 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_8MB                (23 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_16MB       (24 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_256MB      (28 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_1GB                (30 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_2GB                (31 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_16GB       (34 << HUGETLB_FLAG_ENCODE_SHIFT)
+
+#endif /* _ASM_GENERIC_HUGETLB_ENCODE_H_ */
index 8c27db0c5c08ce84fc7299bd9bff2cee571b9397..203268f9231e155d72307995989feab4857defe7 100644 (file)
                                           overrides the coredump filter bits */
 #define MADV_DODUMP    17              /* Clear the MADV_DONTDUMP flag */
 
+#define MADV_WIPEONFORK 18             /* Zero memory on fork, child only */
+#define MADV_KEEPONFORK 19             /* Undo MADV_WIPEONFORK */
+
 /* compatibility flags */
 #define MAP_FILE       0
 
-/*
- * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
- * This gives us 6 bits, which is enough until someone invents 128 bit address
- * spaces.
- *
- * Assume these are all power of twos.
- * When 0 use the default page size.
- */
-#define MAP_HUGE_SHIFT 26
-#define MAP_HUGE_MASK  0x3f
-
 #define PKEY_DISABLE_ACCESS    0x1
 #define PKEY_DISABLE_WRITE     0x2
 #define PKEY_ACCESS_MASK       (PKEY_DISABLE_ACCESS |\
index 101593ab10ac795808db33848092eb62ac542560..97677cd6964db099689f96f11b9731c748bebcfa 100644 (file)
@@ -700,6 +700,7 @@ struct drm_prime_handle {
 
 struct drm_syncobj_create {
        __u32 handle;
+#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0)
        __u32 flags;
 };
 
@@ -718,6 +719,24 @@ struct drm_syncobj_handle {
        __u32 pad;
 };
 
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
+struct drm_syncobj_wait {
+       __u64 handles;
+       /* absolute timeout */
+       __s64 timeout_nsec;
+       __u32 count_handles;
+       __u32 flags;
+       __u32 first_signaled; /* only valid when not waiting all */
+       __u32 pad;
+};
+
+struct drm_syncobj_array {
+       __u64 handles;
+       __u32 count_handles;
+       __u32 pad;
+};
+
 #if defined(__cplusplus)
 }
 #endif
@@ -840,6 +859,9 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_DESTROY      DRM_IOWR(0xC0, struct drm_syncobj_destroy)
 #define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle)
 #define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle)
+#define DRM_IOCTL_SYNCOBJ_WAIT         DRM_IOWR(0xC3, struct drm_syncobj_wait)
+#define DRM_IOCTL_SYNCOBJ_RESET                DRM_IOWR(0xC4, struct drm_syncobj_array)
+#define DRM_IOCTL_SYNCOBJ_SIGNAL       DRM_IOWR(0xC5, struct drm_syncobj_array)
 
 /**
  * Device specific ioctls should only be in their respective headers
index 7ccbd6a2bbe07b387b43bb8b4ac5eba0f52d1cd0..6598fb76d2c27741d2c916f914b70c5f472911f9 100644 (file)
@@ -260,6 +260,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_CONTEXT_GETPARAM  0x34
 #define DRM_I915_GEM_CONTEXT_SETPARAM  0x35
 #define DRM_I915_PERF_OPEN             0x36
+#define DRM_I915_PERF_ADD_CONFIG       0x37
+#define DRM_I915_PERF_REMOVE_CONFIG    0x38
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -315,6 +317,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM    DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
 #define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM    DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
 #define DRM_IOCTL_I915_PERF_OPEN       DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
+#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
+#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG      DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -431,6 +435,11 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_HAS_EXEC_BATCH_FIRST         48
 
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
+ * drm_i915_gem_exec_fence structures.  See I915_EXEC_FENCE_ARRAY.
+ */
+#define I915_PARAM_HAS_EXEC_FENCE_ARRAY  49
+
 typedef struct drm_i915_getparam {
        __s32 param;
        /*
@@ -812,6 +821,17 @@ struct drm_i915_gem_exec_object2 {
        __u64 rsvd2;
 };
 
+struct drm_i915_gem_exec_fence {
+       /**
+        * User's handle for a drm_syncobj to wait on or signal.
+        */
+       __u32 handle;
+
+#define I915_EXEC_FENCE_WAIT            (1<<0)
+#define I915_EXEC_FENCE_SIGNAL          (1<<1)
+       __u32 flags;
+};
+
 struct drm_i915_gem_execbuffer2 {
        /**
         * List of gem_exec_object2 structs
@@ -826,7 +846,11 @@ struct drm_i915_gem_execbuffer2 {
        __u32 DR1;
        __u32 DR4;
        __u32 num_cliprects;
-       /** This is a struct drm_clip_rect *cliprects */
+       /**
+        * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
+        * is not set.  If I915_EXEC_FENCE_ARRAY is set, then this is a
+        * struct drm_i915_gem_exec_fence *fences.
+        */
        __u64 cliprects_ptr;
 #define I915_EXEC_RING_MASK              (7<<0)
 #define I915_EXEC_DEFAULT                (0<<0)
@@ -927,7 +951,14 @@ struct drm_i915_gem_execbuffer2 {
  * element).
  */
 #define I915_EXEC_BATCH_FIRST          (1<<18)
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_BATCH_FIRST<<1))
+
+/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr
+ * define an array of i915_gem_exec_fence structures which specify a set of
+ * dma fences to wait upon or signal.
+ */
+#define I915_EXEC_FENCE_ARRAY   (1<<19)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
 
 #define I915_EXEC_CONTEXT_ID_MASK      (0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
@@ -1467,6 +1498,22 @@ enum drm_i915_perf_record_type {
        DRM_I915_PERF_RECORD_MAX /* non-ABI */
 };
 
+/**
+ * Structure to upload perf dynamic configuration into the kernel.
+ */
+struct drm_i915_perf_oa_config {
+       /** String formatted like "%08x-%04x-%04x-%04x-%012x" */
+       char uuid[36];
+
+       __u32 n_mux_regs;
+       __u32 n_boolean_regs;
+       __u32 n_flex_regs;
+
+       __u64 __user mux_regs_ptr;
+       __u64 __user boolean_regs_ptr;
+       __u64 __user flex_regs_ptr;
+};
+
 #if defined(__cplusplus)
 }
 #endif
index 461811e5714092f17619902593b9ac47e8572a6d..43ab5c402f98f3c2dc15ccc49ec475530a39e401 100644 (file)
@@ -143,12 +143,6 @@ enum bpf_attach_type {
 
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
 
-enum bpf_sockmap_flags {
-       BPF_SOCKMAP_UNSPEC,
-       BPF_SOCKMAP_STRPARSER,
-       __MAX_BPF_SOCKMAP_FLAG
-};
-
 /* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command
  * to the given target_fd cgroup the descendent cgroup will be able to
  * override effective bpf program that was inherited from this cgroup
@@ -368,9 +362,20 @@ union bpf_attr {
  * int bpf_redirect(ifindex, flags)
  *     redirect to another netdev
  *     @ifindex: ifindex of the net device
- *     @flags: bit 0 - if set, redirect to ingress instead of egress
- *             other bits - reserved
- *     Return: TC_ACT_REDIRECT
+ *     @flags:
+ *       cls_bpf:
+ *          bit 0 - if set, redirect to ingress instead of egress
+ *          other bits - reserved
+ *       xdp_bpf:
+ *         all bits - reserved
+ *     Return: cls_bpf: TC_ACT_REDIRECT on success or TC_ACT_SHOT on error
+ *            xdp_bfp: XDP_REDIRECT on success or XDP_ABORT on error
+ * int bpf_redirect_map(map, key, flags)
+ *     redirect to endpoint in map
+ *     @map: pointer to dev map
+ *     @key: index in map to lookup
+ *     @flags: --
+ *     Return: XDP_REDIRECT on success or XDP_ABORT on error
  *
  * u32 bpf_get_route_realm(skb)
  *     retrieve a dst's tclassid
@@ -632,7 +637,7 @@ union bpf_attr {
        FN(skb_adjust_room),            \
        FN(redirect_map),               \
        FN(sk_redirect_map),            \
-       FN(sock_map_update),
+       FN(sock_map_update),            \
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
@@ -753,20 +758,23 @@ struct bpf_sock {
        __u32 family;
        __u32 type;
        __u32 protocol;
+       __u32 mark;
+       __u32 priority;
 };
 
 #define XDP_PACKET_HEADROOM 256
 
 /* User return codes for XDP prog type.
  * A valid XDP program must return one of these defined values. All other
- * return codes are reserved for future use. Unknown return codes will result
- * in packet drop.
+ * return codes are reserved for future use. Unknown return codes will
+ * result in packet drops and a warning via bpf_warn_invalid_xdp_action().
  */
 enum xdp_action {
        XDP_ABORTED = 0,
        XDP_DROP,
        XDP_PASS,
        XDP_TX,
+       XDP_REDIRECT,
 };
 
 /* user accessible metadata for XDP packet hook
index 6cd63c18708ae1d23dbc280ed49aed55f817a2f5..83888758741184f969f3b8fd1738e38bdc24da78 100644 (file)
@@ -711,7 +711,8 @@ struct kvm_ppc_one_seg_page_size {
 struct kvm_ppc_smmu_info {
        __u64 flags;
        __u32 slb_size;
-       __u32 pad;
+       __u16 data_keys;        /* # storage keys supported for data */
+       __u16 instr_keys;       /* # storage keys supported for instructions */
        struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
 };
 
index 81d8edf11789aaae96a25da00b8a8f3ec0ed83aa..a937480d7cd345f4e1b12c2e409f58c0489e8a4e 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef _UAPI_LINUX_MMAN_H
 #define _UAPI_LINUX_MMAN_H
 
-#include <uapi/asm/mman.h>
+#include <asm/mman.h>
+#include <asm-generic/hugetlb_encode.h>
 
 #define MREMAP_MAYMOVE 1
 #define MREMAP_FIXED   2
 #define OVERCOMMIT_ALWAYS              1
 #define OVERCOMMIT_NEVER               2
 
+/*
+ * Huge page size encoding when MAP_HUGETLB is specified, and a huge page
+ * size other than the default is desired.  See hugetlb_encode.h.
+ * All known huge page size encodings are provided here.  It is the
+ * responsibility of the application to know which sizes are supported on
+ * the running system.  See mmap(2) man page for details.
+ */
+#define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
+#define MAP_HUGE_MASK  HUGETLB_FLAG_ENCODE_MASK
+
+#define MAP_HUGE_64KB  HUGETLB_FLAG_ENCODE_64KB
+#define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
+#define MAP_HUGE_1MB   HUGETLB_FLAG_ENCODE_1MB
+#define MAP_HUGE_2MB   HUGETLB_FLAG_ENCODE_2MB
+#define MAP_HUGE_8MB   HUGETLB_FLAG_ENCODE_8MB
+#define MAP_HUGE_16MB  HUGETLB_FLAG_ENCODE_16MB
+#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
+#define MAP_HUGE_1GB   HUGETLB_FLAG_ENCODE_1GB
+#define MAP_HUGE_2GB   HUGETLB_FLAG_ENCODE_2GB
+#define MAP_HUGE_16GB  HUGETLB_FLAG_ENCODE_16GB
+
 #endif /* _UAPI_LINUX_MMAN_H */
index 6a1af43862df759239b8848921b0492e23b95e6b..3995735a878fe796f36513b2bb22b20deaf642d1 100644 (file)
@@ -194,10 +194,10 @@ they mean, and suggestions for how to fix them.
    If it's a GCC-compiled .c file, the error may be because the function
    uses an inline asm() statement which has a "call" instruction.  An
    asm() statement with a call instruction must declare the use of the
-   stack pointer in its output operand.  For example, on x86_64:
+   stack pointer in its output operand.  On x86_64, this means adding
+   the ASM_CALL_CONSTRAINT as an output constraint:
 
-     register void *__sp asm("rsp");
-     asm volatile("call func" : "+r" (__sp));
+     asm volatile("call func" : ASM_CALL_CONSTRAINT);
 
    Otherwise the stack frame may not get created before the call.
 
index 0e8c8ec4fd4e6ac1d101b2514d43d870762c293b..34a579f806e390337bdee738ae507364c02e7ad7 100644 (file)
@@ -208,14 +208,14 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
                break;
 
        case 0x89:
-               if (rex == 0x48 && modrm == 0xe5) {
+               if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {
 
-                       /* mov %rsp, %rbp */
+                       /* mov %rsp, reg */
                        *type = INSN_STACK;
                        op->src.type = OP_SRC_REG;
                        op->src.reg = CFI_SP;
                        op->dest.type = OP_DEST_REG;
-                       op->dest.reg = CFI_BP;
+                       op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
                        break;
                }
 
@@ -284,11 +284,16 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
        case 0x8d:
                if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
 
-                       /* lea disp(%rsp), reg */
                        *type = INSN_STACK;
-                       op->src.type = OP_SRC_ADD;
+                       if (!insn.displacement.value) {
+                               /* lea (%rsp), reg */
+                               op->src.type = OP_SRC_REG;
+                       } else {
+                               /* lea disp(%rsp), reg */
+                               op->src.type = OP_SRC_ADD;
+                               op->src.offset = insn.displacement.value;
+                       }
                        op->src.reg = CFI_SP;
-                       op->src.offset = insn.displacement.value;
                        op->dest.type = OP_DEST_REG;
                        op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
 
index f744617c9946d7eaaa293b3aba5b63dddf19278b..a0c518ecf085135711e8b06488381f53127d9fee 100644 (file)
@@ -1203,24 +1203,39 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
                switch (op->src.type) {
 
                case OP_SRC_REG:
-                       if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP) {
+                       if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
+                           cfa->base == CFI_SP &&
+                           regs[CFI_BP].base == CFI_CFA &&
+                           regs[CFI_BP].offset == -cfa->offset) {
+
+                               /* mov %rsp, %rbp */
+                               cfa->base = op->dest.reg;
+                               state->bp_scratch = false;
+                       }
 
-                               if (cfa->base == CFI_SP &&
-                                   regs[CFI_BP].base == CFI_CFA &&
-                                   regs[CFI_BP].offset == -cfa->offset) {
+                       else if (op->src.reg == CFI_SP &&
+                                op->dest.reg == CFI_BP && state->drap) {
 
-                                       /* mov %rsp, %rbp */
-                                       cfa->base = op->dest.reg;
-                                       state->bp_scratch = false;
-                               }
+                               /* drap: mov %rsp, %rbp */
+                               regs[CFI_BP].base = CFI_BP;
+                               regs[CFI_BP].offset = -state->stack_size;
+                               state->bp_scratch = false;
+                       }
 
-                               else if (state->drap) {
+                       else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
 
-                                       /* drap: mov %rsp, %rbp */
-                                       regs[CFI_BP].base = CFI_BP;
-                                       regs[CFI_BP].offset = -state->stack_size;
-                                       state->bp_scratch = false;
-                               }
+                               /*
+                                * mov %rsp, %reg
+                                *
+                                * This is needed for the rare case where GCC
+                                * does:
+                                *
+                                *   mov    %rsp, %rax
+                                *   ...
+                                *   mov    %rax, %rsp
+                                */
+                               state->vals[op->dest.reg].base = CFI_CFA;
+                               state->vals[op->dest.reg].offset = -state->stack_size;
                        }
 
                        else if (op->dest.reg == cfa->base) {
index 6e9f980a7d26fdc4384fdb15d96baaca09846117..24460155c82c9b2305a2484d037be9017a00becb 100644 (file)
@@ -175,19 +175,20 @@ static int read_sections(struct elf *elf)
                        return -1;
                }
 
-               sec->data = elf_getdata(s, NULL);
-               if (!sec->data) {
-                       WARN_ELF("elf_getdata");
-                       return -1;
-               }
-
-               if (sec->data->d_off != 0 ||
-                   sec->data->d_size != sec->sh.sh_size) {
-                       WARN("unexpected data attributes for %s", sec->name);
-                       return -1;
+               if (sec->sh.sh_size != 0) {
+                       sec->data = elf_getdata(s, NULL);
+                       if (!sec->data) {
+                               WARN_ELF("elf_getdata");
+                               return -1;
+                       }
+                       if (sec->data->d_off != 0 ||
+                           sec->data->d_size != sec->sh.sh_size) {
+                               WARN("unexpected data attributes for %s",
+                                    sec->name);
+                               return -1;
+                       }
                }
-
-               sec->len = sec->data->d_size;
+               sec->len = sec->sh.sh_size;
        }
 
        /* sanity check, one more call to elf_nextscn() should return NULL */
@@ -508,6 +509,7 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base)
        strcat(relaname, base->name);
 
        sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0);
+       free(relaname);
        if (!sec)
                return NULL;
 
@@ -561,6 +563,7 @@ int elf_write(struct elf *elf)
        struct section *sec;
        Elf_Scn *s;
 
+       /* Update section headers for changed sections: */
        list_for_each_entry(sec, &elf->sections, list) {
                if (sec->changed) {
                        s = elf_getscn(elf->elf, sec->idx);
@@ -568,13 +571,17 @@ int elf_write(struct elf *elf)
                                WARN_ELF("elf_getscn");
                                return -1;
                        }
-                       if (!gelf_update_shdr (s, &sec->sh)) {
+                       if (!gelf_update_shdr(s, &sec->sh)) {
                                WARN_ELF("gelf_update_shdr");
                                return -1;
                        }
                }
        }
 
+       /* Make sure the new section header entries get updated properly. */
+       elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY);
+
+       /* Write all changes to the file. */
        if (elf_update(elf->elf, ELF_C_WRITE) < 0) {
                WARN_ELF("elf_update");
                return -1;
index 62072822dc85d986671b6b15587229f81cfe19ec..627b7cada1442b65dbbcc600661f35caf8429cdc 100644 (file)
@@ -1,34 +1,8 @@
 tools/perf
-tools/arch/alpha/include/asm/barrier.h
-tools/arch/arm/include/asm/barrier.h
-tools/arch/arm64/include/asm/barrier.h
-tools/arch/ia64/include/asm/barrier.h
-tools/arch/mips/include/asm/barrier.h
-tools/arch/powerpc/include/asm/barrier.h
-tools/arch/s390/include/asm/barrier.h
-tools/arch/sh/include/asm/barrier.h
-tools/arch/sparc/include/asm/barrier.h
-tools/arch/sparc/include/asm/barrier_32.h
-tools/arch/sparc/include/asm/barrier_64.h
-tools/arch/tile/include/asm/barrier.h
-tools/arch/x86/include/asm/barrier.h
-tools/arch/x86/include/asm/cmpxchg.h
-tools/arch/x86/include/asm/cpufeatures.h
-tools/arch/x86/include/asm/disabled-features.h
-tools/arch/x86/include/asm/required-features.h
-tools/arch/x86/include/uapi/asm/svm.h
-tools/arch/x86/include/uapi/asm/vmx.h
-tools/arch/x86/include/uapi/asm/kvm.h
-tools/arch/x86/include/uapi/asm/kvm_perf.h
-tools/arch/x86/lib/memcpy_64.S
-tools/arch/x86/lib/memset_64.S
-tools/arch/s390/include/uapi/asm/kvm_perf.h
-tools/arch/s390/include/uapi/asm/sie.h
-tools/arch/xtensa/include/asm/barrier.h
+tools/arch
 tools/scripts
 tools/build
-tools/arch/x86/include/asm/atomic.h
-tools/arch/x86/include/asm/rmwcc.h
+tools/include
 tools/lib/traceevent
 tools/lib/api
 tools/lib/bpf
@@ -42,60 +16,3 @@ tools/lib/find_bit.c
 tools/lib/bitmap.c
 tools/lib/str_error_r.c
 tools/lib/vsprintf.c
-tools/include/asm/alternative-asm.h
-tools/include/asm/atomic.h
-tools/include/asm/barrier.h
-tools/include/asm/bug.h
-tools/include/asm-generic/atomic-gcc.h
-tools/include/asm-generic/barrier.h
-tools/include/asm-generic/bitops/arch_hweight.h
-tools/include/asm-generic/bitops/atomic.h
-tools/include/asm-generic/bitops/const_hweight.h
-tools/include/asm-generic/bitops/__ffs.h
-tools/include/asm-generic/bitops/__ffz.h
-tools/include/asm-generic/bitops/__fls.h
-tools/include/asm-generic/bitops/find.h
-tools/include/asm-generic/bitops/fls64.h
-tools/include/asm-generic/bitops/fls.h
-tools/include/asm-generic/bitops/hweight.h
-tools/include/asm-generic/bitops.h
-tools/include/linux/atomic.h
-tools/include/linux/bitops.h
-tools/include/linux/compiler.h
-tools/include/linux/compiler-gcc.h
-tools/include/linux/coresight-pmu.h
-tools/include/linux/bug.h
-tools/include/linux/filter.h
-tools/include/linux/hash.h
-tools/include/linux/kernel.h
-tools/include/linux/list.h
-tools/include/linux/log2.h
-tools/include/uapi/asm-generic/fcntl.h
-tools/include/uapi/asm-generic/ioctls.h
-tools/include/uapi/asm-generic/mman-common.h
-tools/include/uapi/asm-generic/mman.h
-tools/include/uapi/drm/drm.h
-tools/include/uapi/drm/i915_drm.h
-tools/include/uapi/linux/bpf.h
-tools/include/uapi/linux/bpf_common.h
-tools/include/uapi/linux/fcntl.h
-tools/include/uapi/linux/hw_breakpoint.h
-tools/include/uapi/linux/kvm.h
-tools/include/uapi/linux/mman.h
-tools/include/uapi/linux/perf_event.h
-tools/include/uapi/linux/sched.h
-tools/include/uapi/linux/stat.h
-tools/include/uapi/linux/vhost.h
-tools/include/uapi/sound/asound.h
-tools/include/linux/poison.h
-tools/include/linux/rbtree.h
-tools/include/linux/rbtree_augmented.h
-tools/include/linux/refcount.h
-tools/include/linux/string.h
-tools/include/linux/stringify.h
-tools/include/linux/types.h
-tools/include/linux/err.h
-tools/include/linux/bitmap.h
-tools/include/linux/time64.h
-tools/arch/*/include/uapi/asm/mman.h
-tools/arch/*/include/uapi/asm/perf_regs.h
index bd518b623d7a203e576653705866f910409fa144..5bd7b9260cc0858c36730ee367aecc56df6c91bb 100644 (file)
@@ -1,5 +1,4 @@
 libperf-y += header.o
-libperf-y += sym-handling.o
 libperf-y += kvm-stat.o
 
 libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/s390/util/sym-handling.c b/tools/perf/arch/s390/util/sym-handling.c
deleted file mode 100644 (file)
index e103f6e..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Architecture specific ELF symbol handling and relocation mapping.
- *
- * Copyright 2017 IBM Corp.
- * Author(s): Thomas Richter <tmricht@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (version 2 only)
- * as published by the Free Software Foundation.
- */
-
-#include "symbol.h"
-
-#ifdef HAVE_LIBELF_SUPPORT
-bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
-{
-       if (ehdr.e_type == ET_EXEC)
-               return false;
-       return ehdr.e_type == ET_REL || ehdr.e_type == ET_DYN;
-}
-
-void arch__adjust_sym_map_offset(GElf_Sym *sym,
-                                GElf_Shdr *shdr __maybe_unused,
-                                struct map *map)
-{
-       if (map->type == MAP__FUNCTION)
-               sym->st_value += map->start;
-}
-#endif
index 510b513e0f01fe96e110b9eab45db527b8c86104..be09d77cade02edde9973597219ac8b4ee50d3bc 100644 (file)
@@ -65,8 +65,6 @@ static int parse_callchain_mode(const char *value)
                callchain_param.mode = CHAIN_FOLDED;
                return 0;
        }
-
-       pr_err("Invalid callchain mode: %s\n", value);
        return -1;
 }
 
@@ -82,8 +80,6 @@ static int parse_callchain_order(const char *value)
                callchain_param.order_set = true;
                return 0;
        }
-
-       pr_err("Invalid callchain order: %s\n", value);
        return -1;
 }
 
@@ -105,8 +101,6 @@ static int parse_callchain_sort_key(const char *value)
                callchain_param.branch_callstack = 1;
                return 0;
        }
-
-       pr_err("Invalid callchain sort key: %s\n", value);
        return -1;
 }
 
@@ -124,8 +118,6 @@ static int parse_callchain_value(const char *value)
                callchain_param.value = CCVAL_COUNT;
                return 0;
        }
-
-       pr_err("Invalid callchain config key: %s\n", value);
        return -1;
 }
 
@@ -319,12 +311,27 @@ int perf_callchain_config(const char *var, const char *value)
 
                return ret;
        }
-       if (!strcmp(var, "print-type"))
-               return parse_callchain_mode(value);
-       if (!strcmp(var, "order"))
-               return parse_callchain_order(value);
-       if (!strcmp(var, "sort-key"))
-               return parse_callchain_sort_key(value);
+       if (!strcmp(var, "print-type")){
+               int ret;
+               ret = parse_callchain_mode(value);
+               if (ret == -1)
+                       pr_err("Invalid callchain mode: %s\n", value);
+               return ret;
+       }
+       if (!strcmp(var, "order")){
+               int ret;
+               ret = parse_callchain_order(value);
+               if (ret == -1)
+                       pr_err("Invalid callchain order: %s\n", value);
+               return ret;
+       }
+       if (!strcmp(var, "sort-key")){
+               int ret;
+               ret = parse_callchain_sort_key(value);
+               if (ret == -1)
+                       pr_err("Invalid callchain sort key: %s\n", value);
+               return ret;
+       }
        if (!strcmp(var, "threshold")) {
                callchain_param.min_percent = strtod(value, &endptr);
                if (value == endptr) {
index 4bb89373eb52893e7a3c7206da85af1e72afdfc3..0dccdb89572cdb455724a6a48a86d96821fc53e2 100644 (file)
@@ -271,12 +271,17 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
        return evsel;
 }
 
+static bool perf_event_can_profile_kernel(void)
+{
+       return geteuid() == 0 || perf_event_paranoid() == -1;
+}
+
 struct perf_evsel *perf_evsel__new_cycles(bool precise)
 {
        struct perf_event_attr attr = {
                .type   = PERF_TYPE_HARDWARE,
                .config = PERF_COUNT_HW_CPU_CYCLES,
-               .exclude_kernel = geteuid() != 0,
+               .exclude_kernel = !perf_event_can_profile_kernel(),
        };
        struct perf_evsel *evsel;
 
index 5c39f420111e5f679fa4a486383174d9c10d68b5..9cf781f0d8a2d797c88bf0bef5cab8759a6cbf96 100644 (file)
@@ -810,12 +810,6 @@ static u64 ref_reloc(struct kmap *kmap)
 void __weak arch__sym_update(struct symbol *s __maybe_unused,
                GElf_Sym *sym __maybe_unused) { }
 
-void __weak arch__adjust_sym_map_offset(GElf_Sym *sym, GElf_Shdr *shdr,
-                                      struct map *map __maybe_unused)
-{
-       sym->st_value -= shdr->sh_addr - shdr->sh_offset;
-}
-
 int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
                  struct symsrc *runtime_ss, int kmodule)
 {
@@ -996,7 +990,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
 
                        /* Adjust symbol to map to file offset */
                        if (adjust_kernel_syms)
-                               arch__adjust_sym_map_offset(&sym, &shdr, map);
+                               sym.st_value -= shdr.sh_addr - shdr.sh_offset;
 
                        if (strcmp(section_name,
                                   (curr_dso->short_name +
index 2bd6a1f01a1cc5b5bb15ee0aae59ae921ebe2a86..aad99e7e179bbb8f95bd39cf0d659d136ed2ef6d 100644 (file)
@@ -344,9 +344,6 @@ int setup_intlist(struct intlist **list, const char *list_str,
 #ifdef HAVE_LIBELF_SUPPORT
 bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
 void arch__sym_update(struct symbol *s, GElf_Sym *sym);
-void arch__adjust_sym_map_offset(GElf_Sym *sym,
-                                GElf_Shdr *shdr __maybe_unused,
-                                struct map *map __maybe_unused);
 #endif
 
 #define SYMBOL_A 0
index 19e5db90394c2bf03ec1c08810c270cb965f65c8..6eea7cff3d4e96473644fcd7c034a8a32abfcb10 100644 (file)
@@ -15,9 +15,9 @@
 
 #include "syscalltbl.h"
 #include <stdlib.h>
+#include <linux/compiler.h>
 
 #ifdef HAVE_SYSCALL_TABLE
-#include <linux/compiler.h>
 #include <string.h>
 #include "string2.h"
 #include "util.h"
index d20791c3f4990bdced0308989205db61f07087a0..bef419d4266df97a207d6aa3033ae3998ff7dc16 100644 (file)
@@ -1527,9 +1527,6 @@ static void nfit_test1_setup(struct nfit_test *t)
        set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
        set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
        set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
-       set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
-       set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
-       set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
 }
 
 static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
index 26ce4f7168be534de2eef4be6650de9617b03b33..ff805643b5f723a1eb5420f50f88819e529b7299 100644 (file)
@@ -52,6 +52,10 @@ override LDFLAGS =
 override MAKEFLAGS =
 endif
 
+ifneq ($(KBUILD_SRC),)
+override LDFLAGS =
+endif
+
 BUILD := $(O)
 ifndef BUILD
   BUILD := $(KBUILD_OUTPUT)
@@ -62,32 +66,32 @@ endif
 
 export BUILD
 all:
-       for TARGET in $(TARGETS); do            \
+       @for TARGET in $(TARGETS); do           \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
                mkdir $$BUILD_TARGET  -p;       \
                make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
        done;
 
 run_tests: all
-       for TARGET in $(TARGETS); do \
+       @for TARGET in $(TARGETS); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
                make OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests;\
        done;
 
 hotplug:
-       for TARGET in $(TARGETS_HOTPLUG); do \
+       @for TARGET in $(TARGETS_HOTPLUG); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
                make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
        done;
 
 run_hotplug: hotplug
-       for TARGET in $(TARGETS_HOTPLUG); do \
+       @for TARGET in $(TARGETS_HOTPLUG); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
                make OUTPUT=$$BUILD_TARGET -C $$TARGET run_full_test;\
        done;
 
 clean_hotplug:
-       for TARGET in $(TARGETS_HOTPLUG); do \
+       @for TARGET in $(TARGETS_HOTPLUG); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
                make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
        done;
@@ -103,7 +107,7 @@ install:
 ifdef INSTALL_PATH
        @# Ask all targets to install their files
        mkdir -p $(INSTALL_PATH)
-       for TARGET in $(TARGETS); do \
+       @for TARGET in $(TARGETS); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
                make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
        done;
@@ -128,7 +132,7 @@ else
 endif
 
 clean:
-       for TARGET in $(TARGETS); do \
+       @for TARGET in $(TARGETS); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
                make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
        done;
index 20ecbaa0d85d72b860678caf49c3e421105802b8..6c53a8906eff4c4fe6d98863050132d928de50f8 100644 (file)
@@ -12,6 +12,7 @@ static inline unsigned int bpf_num_possible_cpus(void)
        unsigned int start, end, possible_cpus = 0;
        char buff[128];
        FILE *fp;
+       int n;
 
        fp = fopen(fcpu, "r");
        if (!fp) {
@@ -20,17 +21,17 @@ static inline unsigned int bpf_num_possible_cpus(void)
        }
 
        while (fgets(buff, sizeof(buff), fp)) {
-               if (sscanf(buff, "%u-%u", &start, &end) == 2) {
-                       possible_cpus = start == 0 ? end + 1 : 0;
-                       break;
+               n = sscanf(buff, "%u-%u", &start, &end);
+               if (n == 0) {
+                       printf("Failed to retrieve # possible CPUs!\n");
+                       exit(1);
+               } else if (n == 1) {
+                       end = start;
                }
+               possible_cpus = start == 0 ? end + 1 : 0;
+               break;
        }
-
        fclose(fp);
-       if (!possible_cpus) {
-               printf("Failed to retrieve # possible CPUs!\n");
-               exit(1);
-       }
 
        return possible_cpus;
 }
index 6b214b7b10fb7c1c7ad6330c3769fbd1c46838d7..247b0a1899d70f55a5a02e2aac35a3136854652d 100644 (file)
@@ -2,14 +2,14 @@
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
 
+TEST_GEN_PROGS := step_after_suspend_test
+
 ifeq ($(ARCH),x86)
-TEST_GEN_PROGS := breakpoint_test
+TEST_GEN_PROGS += breakpoint_test
 endif
 ifneq (,$(filter $(ARCH),aarch64 arm64))
-TEST_GEN_PROGS := breakpoint_test_arm64
+TEST_GEN_PROGS += breakpoint_test_arm64
 endif
 
-TEST_GEN_PROGS += step_after_suspend_test
-
 include ../lib.mk
 
index 2a1cb990874613c5ee9da2d371b95899d8eaa81a..a4fd4c851a5b7f27520801858d8f1f24e34ba56e 100644 (file)
@@ -1,6 +1,8 @@
 #!/bin/sh
 # description: Register/unregister many kprobe events
 
+[ -f kprobe_events ] || exit_unsupported # this is configurable
+
 # ftrace fentry skip size depends on the machine architecture.
 # Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le
 case `uname -m` in
index 7c647f619d63faf3eff4c135c1b302565b7f78d5..f0c0369ccb7972d6deffb12534d1c64cc913a382 100644 (file)
@@ -7,14 +7,17 @@ TEST_PROGS := run.sh
 include ../lib.mk
 
 all:
-       for DIR in $(SUBDIRS); do               \
+       @for DIR in $(SUBDIRS); do              \
                BUILD_TARGET=$(OUTPUT)/$$DIR;   \
                mkdir $$BUILD_TARGET  -p;       \
                make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
+               if [ -e $$DIR/$(TEST_PROGS) ]; then
+                       rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/;
+               fi
        done
 
 override define RUN_TESTS
-       $(OUTPUT)/run.sh
+       @cd $(OUTPUT); ./run.sh
 endef
 
 override define INSTALL_RULE
@@ -33,7 +36,7 @@ override define EMIT_TESTS
 endef
 
 override define CLEAN
-       for DIR in $(SUBDIRS); do               \
+       @for DIR in $(SUBDIRS); do              \
                BUILD_TARGET=$(OUTPUT)/$$DIR;   \
                mkdir $$BUILD_TARGET  -p;       \
                make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
index 849a90ffe8dd2d311b9b66bed9058fefdf28ba7d..a97e24edde39ed9d9d51441b01547856641b9606 100644 (file)
@@ -1,7 +1,9 @@
 CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
 LDLIBS := $(LDLIBS) -lm
 
+ifeq (,$(filter $(ARCH),x86))
 TEST_GEN_FILES := msr aperf
+endif
 
 TEST_PROGS := run.sh
 
index 7868c106b8b1b80c41a8af739c8def48fd378bd8..d3ab48f91cd6a6ef1742653256e15418933de2cf 100755 (executable)
 
 EVALUATE_ONLY=0
 
-max_cpus=$(($(nproc)-1))
+if ! uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ | grep -q x86; then
+       echo "$0 # Skipped: Test can only run on x86 architectures."
+       exit 0
+fi
 
-# compile programs
-gcc aperf.c -Wall -D_GNU_SOURCE -o aperf  -lm
-[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1
-gcc -o msr msr.c -lm
-[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1
+max_cpus=$(($(nproc)-1))
 
 function run_test () {
 
index 693616651da5cbc27a779868e64697df80582ef3..f65886af7c0cac60e4502e8973b4a602fe67c7b6 100644 (file)
@@ -6,7 +6,14 @@ ifeq (0,$(MAKELEVEL))
 OUTPUT := $(shell pwd)
 endif
 
+# The following are built by lib.mk common compile rules.
+# TEST_CUSTOM_PROGS should be used by tests that require
+# custom build rule and prevent common build rule use.
+# TEST_PROGS are for test shell scripts.
+# TEST_CUSTOM_PROGS and TEST_PROGS will be run by common run_tests
+# and install targets. Common clean doesn't touch them.
 TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS))
+TEST_GEN_PROGS_EXTENDED := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS_EXTENDED))
 TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
 
 all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
@@ -20,17 +27,28 @@ define RUN_TESTS
                test_num=`echo $$test_num+1 | bc`;      \
                echo "selftests: $$BASENAME_TEST";      \
                echo "========================================";        \
-               if [ ! -x $$BASENAME_TEST ]; then       \
+               if [ ! -x $$TEST ]; then        \
                        echo "selftests: Warning: file $$BASENAME_TEST is not executable, correct this.";\
                        echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; \
                else                                    \
-                       cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests:  $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
+                       cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests:  $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
                fi;                                     \
        done;
 endef
 
 run_tests: all
-       $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_PROGS))
+ifneq ($(KBUILD_SRC),)
+       @if [ "X$(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)" != "X" ]; then
+               @rsync -aq $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(OUTPUT)
+       fi
+       @if [ "X$(TEST_PROGS)" != "X" ]; then
+               $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(OUTPUT)/$(TEST_PROGS))
+       else
+               $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS))
+       fi
+else
+       $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS))
+endif
 
 define INSTALL_RULE
        @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then                                        \
@@ -38,10 +56,10 @@ define INSTALL_RULE
                echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/";    \
                rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/;           \
        fi
-       @if [ "X$(TEST_GEN_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then                                    \
+       @if [ "X$(TEST_GEN_PROGS)$(TEST_CUSTOM_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then                                        \
                mkdir -p ${INSTALL_PATH};                                                                               \
-               echo "rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/";        \
-               rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/;               \
+               echo "rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/";   \
+               rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/;          \
        fi
 endef
 
@@ -53,15 +71,20 @@ else
 endif
 
 define EMIT_TESTS
-       @for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \
+       @for TEST in $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS); do \
                BASENAME_TEST=`basename $$TEST`;        \
-               echo "(./$$BASENAME_TEST && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \
+               echo "(./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \
        done;
 endef
 
 emit_tests:
        $(EMIT_TESTS)
 
+# define if isn't already. It is undefined in make O= case.
+ifeq ($(RM),)
+RM := rm -f
+endif
+
 define CLEAN
        $(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN)
 endef
@@ -69,6 +92,15 @@ endef
 clean:
        $(CLEAN)
 
+# When make O= with kselftest target from main level
+# the following aren't defined.
+#
+ifneq ($(KBUILD_SRC),)
+LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+COMPILE.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
+LINK.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+endif
+
 $(OUTPUT)/%:%.c
        $(LINK.c) $^ $(LDLIBS) -o $@
 
old mode 100644 (file)
new mode 100755 (executable)
index 79a664aeb8d76509a2f8e46aadf742571765a26a..0f5e347b068d3bb22d07ddd8308cc55fc263aebb 100644 (file)
@@ -5,8 +5,8 @@ TEST_GEN_PROGS := mq_open_tests mq_perf_tests
 include ../lib.mk
 
 override define RUN_TESTS
-       @./mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]"
-       @./mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
+       $(OUTPUT)/mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]"
+       $(OUTPUT)//mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
 endef
 
 override define EMIT_TESTS
index 9801253e48021035b650a88e3d3d0c2affea8675..c612d6e38c6282cad7b56396e1d3e2c1c9d3a46c 100644 (file)
@@ -6,3 +6,4 @@ reuseport_bpf
 reuseport_bpf_cpu
 reuseport_bpf_numa
 reuseport_dualstack
+reuseaddr_conflict
index de1f5772b878ee1f4aee9e1452d1f0e83696af62..d86bca991f456a70206c790f733b0032bc7ad224 100644 (file)
@@ -5,9 +5,9 @@ CFLAGS += -I../../../../usr/include/
 
 TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
 TEST_GEN_FILES =  socket
-TEST_GEN_FILES += psock_fanout psock_tpacket
-TEST_GEN_FILES += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
-TEST_GEN_FILES += reuseport_dualstack msg_zerocopy
+TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
+TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
+TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict
 
 include ../lib.mk
 
index 40232af5b023ee251bfc369fd73860d912809891..3ab6ec4039059cf127345652bccf6c34d5c4d273 100644 (file)
@@ -55,7 +55,7 @@
 #include <unistd.h>
 
 #ifndef SO_EE_ORIGIN_ZEROCOPY
-#define SO_EE_ORIGIN_ZEROCOPY          SO_EE_ORIGIN_UPAGE
+#define SO_EE_ORIGIN_ZEROCOPY          5
 #endif
 
 #ifndef SO_ZEROCOPY
index 4e00568d70c2c398651675ad763f646453b45b3b..90cb903c33815bcecc3a64a9f153c779476a6848 100755 (executable)
@@ -178,7 +178,7 @@ if [ "$(id -u)" -ne 0 ];then
        exit 0
 fi
 
-ip -Version 2>/dev/null >/dev/null
+ip link show 2>/dev/null >/dev/null
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without the ip tool"
        exit 0
diff --git a/tools/testing/selftests/net/reuseaddr_conflict.c b/tools/testing/selftests/net/reuseaddr_conflict.c
new file mode 100644 (file)
index 0000000..7c5b126
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Test for the regression introduced by
+ *
+ * b9470c27607b ("inet: kill smallest_size and smallest_port")
+ *
+ * If we open an ipv4 socket on a port with reuseaddr we shouldn't reset the tb
+ * when we open the ipv6 conterpart, which is what was happening previously.
+ */
+#include <errno.h>
+#include <error.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define PORT 9999
+
+int open_port(int ipv6, int any)
+{
+       int fd = -1;
+       int reuseaddr = 1;
+       int v6only = 1;
+       int addrlen;
+       int ret = -1;
+       struct sockaddr *addr;
+       int family = ipv6 ? AF_INET6 : AF_INET;
+
+       struct sockaddr_in6 addr6 = {
+               .sin6_family = AF_INET6,
+               .sin6_port = htons(PORT),
+               .sin6_addr = in6addr_any
+       };
+       struct sockaddr_in addr4 = {
+               .sin_family = AF_INET,
+               .sin_port = htons(PORT),
+               .sin_addr.s_addr = any ? htonl(INADDR_ANY) : inet_addr("127.0.0.1"),
+       };
+
+
+       if (ipv6) {
+               addr = (struct sockaddr*)&addr6;
+               addrlen = sizeof(addr6);
+       } else {
+               addr = (struct sockaddr*)&addr4;
+               addrlen = sizeof(addr4);
+       }
+
+       if ((fd = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+               perror("socket");
+               goto out;
+       }
+
+       if (ipv6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&v6only,
+                              sizeof(v6only)) < 0) {
+               perror("setsockopt IPV6_V6ONLY");
+               goto out;
+       }
+
+       if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
+                      sizeof(reuseaddr)) < 0) {
+               perror("setsockopt SO_REUSEADDR");
+               goto out;
+       }
+
+       if (bind(fd, addr, addrlen) < 0) {
+               perror("bind");
+               goto out;
+       }
+
+       if (any)
+               return fd;
+
+       if (listen(fd, 1) < 0) {
+               perror("listen");
+               goto out;
+       }
+       return fd;
+out:
+       close(fd);
+       return ret;
+}
+
+int main(void)
+{
+       int listenfd;
+       int fd1, fd2;
+
+       fprintf(stderr, "Opening 127.0.0.1:%d\n", PORT);
+       listenfd = open_port(0, 0);
+       if (listenfd < 0)
+               error(1, errno, "Couldn't open listen socket");
+       fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
+       fd1 = open_port(0, 1);
+       if (fd1 >= 0)
+               error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
+       fprintf(stderr, "Opening in6addr_any:%d\n", PORT);
+       fd1 = open_port(1, 1);
+       if (fd1 < 0)
+               error(1, errno, "Couldn't open ipv6 reuseport");
+       fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
+       fd2 = open_port(0, 1);
+       if (fd2 >= 0)
+               error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
+       close(fd1);
+       fprintf(stderr, "Opening INADDR_ANY:%d after closing ipv6 socket\n", PORT);
+       fd1 = open_port(0, 1);
+       if (fd1 >= 0)
+               error(1, 0, "Was allowed to create an ipv4 reuseport on an already bound non-reuseport socket with no ipv6");
+       fprintf(stderr, "Success");
+       return 0;
+}
index aeb0c805f3ca0f9471ae0f211e5633aa9d7a52f8..553d870b4ca983252a19dbe3a52ddb23e492a06a 100644 (file)
@@ -1,8 +1,16 @@
-TEST_GEN_PROGS := seccomp_bpf
-CFLAGS += -Wl,-no-as-needed -Wall
-LDFLAGS += -lpthread
+all:
 
 include ../lib.mk
 
-$(TEST_GEN_PROGS): seccomp_bpf.c ../kselftest_harness.h
-       $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
+.PHONY: all clean
+
+BINARIES := seccomp_bpf seccomp_benchmark
+CFLAGS += -Wl,-no-as-needed -Wall
+
+seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@
+
+TEST_PROGS += $(BINARIES)
+EXTRA_CLEAN := $(BINARIES)
+
+all: $(BINARIES)
diff --git a/tools/testing/selftests/seccomp/seccomp_benchmark.c b/tools/testing/selftests/seccomp/seccomp_benchmark.c
new file mode 100644 (file)
index 0000000..5838c86
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Strictly speaking, this is not a test. But it can report during test
+ * runs so relative performace can be measured.
+ */
+#define _GNU_SOURCE
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+
+#define ARRAY_SIZE(a)    (sizeof(a) / sizeof(a[0]))
+
+unsigned long long timing(clockid_t clk_id, unsigned long long samples)
+{
+       pid_t pid, ret;
+       unsigned long long i;
+       struct timespec start, finish;
+
+       pid = getpid();
+       assert(clock_gettime(clk_id, &start) == 0);
+       for (i = 0; i < samples; i++) {
+               ret = syscall(__NR_getpid);
+               assert(pid == ret);
+       }
+       assert(clock_gettime(clk_id, &finish) == 0);
+
+       i = finish.tv_sec - start.tv_sec;
+       i *= 1000000000;
+       i += finish.tv_nsec - start.tv_nsec;
+
+       printf("%lu.%09lu - %lu.%09lu = %llu\n",
+               finish.tv_sec, finish.tv_nsec,
+               start.tv_sec, start.tv_nsec,
+               i);
+
+       return i;
+}
+
+unsigned long long calibrate(void)
+{
+       unsigned long long i;
+
+       printf("Calibrating reasonable sample size...\n");
+
+       for (i = 5; ; i++) {
+               unsigned long long samples = 1 << i;
+
+               /* Find something that takes more than 5 seconds to run. */
+               if (timing(CLOCK_REALTIME, samples) / 1000000000ULL > 5)
+                       return samples;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       struct sock_filter filter[] = {
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+       };
+       struct sock_fprog prog = {
+               .len = (unsigned short)ARRAY_SIZE(filter),
+               .filter = filter,
+       };
+       long ret;
+       unsigned long long samples;
+       unsigned long long native, filtered;
+
+       if (argc > 1)
+               samples = strtoull(argv[1], NULL, 0);
+       else
+               samples = calibrate();
+
+       printf("Benchmarking %llu samples...\n", samples);
+
+       native = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;
+       printf("getpid native: %llu ns\n", native);
+
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       assert(ret == 0);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+       assert(ret == 0);
+
+       filtered = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;
+       printf("getpid RET_ALLOW: %llu ns\n", filtered);
+
+       printf("Estimated seccomp overhead per syscall: %llu ns\n",
+               filtered - native);
+
+       if (filtered == native)
+               printf("Trying running again with more samples.\n");
+
+       return 0;
+}
index 4d6f92a9df6b4aaa0bec897b108bf7cafcae41ef..24dbf634e2dd8c869a7201e7d89efe4102fa6373 100644 (file)
@@ -6,10 +6,18 @@
  */
 
 #include <sys/types.h>
-#include <asm/siginfo.h>
-#define __have_siginfo_t 1
-#define __have_sigval_t 1
-#define __have_sigevent_t 1
+
+/*
+ * glibc 2.26 and later have SIGSYS in siginfo_t. Before that,
+ * we need to use the kernel's siginfo.h file and trick glibc
+ * into accepting it.
+ */
+#if !__GLIBC_PREREQ(2, 26)
+# include <asm/siginfo.h>
+# define __have_siginfo_t 1
+# define __have_sigval_t 1
+# define __have_sigevent_t 1
+#endif
 
 #include <errno.h>
 #include <linux/filter.h>
 #define SECCOMP_MODE_FILTER 2
 #endif
 
-#ifndef SECCOMP_RET_KILL
-#define SECCOMP_RET_KILL        0x00000000U /* kill the task immediately */
-#define SECCOMP_RET_TRAP        0x00030000U /* disallow and force a SIGSYS */
-#define SECCOMP_RET_ERRNO       0x00050000U /* returns an errno */
-#define SECCOMP_RET_TRACE       0x7ff00000U /* pass to a tracer or disallow */
-#define SECCOMP_RET_ALLOW       0x7fff0000U /* allow */
-
-/* Masks for the return value sections. */
-#define SECCOMP_RET_ACTION      0x7fff0000U
-#define SECCOMP_RET_DATA        0x0000ffffU
-
+#ifndef SECCOMP_RET_ALLOW
 struct seccomp_data {
        int nr;
        __u32 arch;
@@ -87,6 +85,70 @@ struct seccomp_data {
 };
 #endif
 
+#ifndef SECCOMP_RET_KILL_PROCESS
+#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
+#define SECCOMP_RET_KILL_THREAD         0x00000000U /* kill the thread */
+#endif
+#ifndef SECCOMP_RET_KILL
+#define SECCOMP_RET_KILL        SECCOMP_RET_KILL_THREAD
+#define SECCOMP_RET_TRAP        0x00030000U /* disallow and force a SIGSYS */
+#define SECCOMP_RET_ERRNO       0x00050000U /* returns an errno */
+#define SECCOMP_RET_TRACE       0x7ff00000U /* pass to a tracer or disallow */
+#define SECCOMP_RET_ALLOW       0x7fff0000U /* allow */
+#endif
+#ifndef SECCOMP_RET_LOG
+#define SECCOMP_RET_LOG                 0x7ffc0000U /* allow after logging */
+#endif
+
+#ifndef __NR_seccomp
+# if defined(__i386__)
+#  define __NR_seccomp 354
+# elif defined(__x86_64__)
+#  define __NR_seccomp 317
+# elif defined(__arm__)
+#  define __NR_seccomp 383
+# elif defined(__aarch64__)
+#  define __NR_seccomp 277
+# elif defined(__hppa__)
+#  define __NR_seccomp 338
+# elif defined(__powerpc__)
+#  define __NR_seccomp 358
+# elif defined(__s390__)
+#  define __NR_seccomp 348
+# else
+#  warning "seccomp syscall number unknown for this architecture"
+#  define __NR_seccomp 0xffff
+# endif
+#endif
+
+#ifndef SECCOMP_SET_MODE_STRICT
+#define SECCOMP_SET_MODE_STRICT 0
+#endif
+
+#ifndef SECCOMP_SET_MODE_FILTER
+#define SECCOMP_SET_MODE_FILTER 1
+#endif
+
+#ifndef SECCOMP_GET_ACTION_AVAIL
+#define SECCOMP_GET_ACTION_AVAIL 2
+#endif
+
+#ifndef SECCOMP_FILTER_FLAG_TSYNC
+#define SECCOMP_FILTER_FLAG_TSYNC 1
+#endif
+
+#ifndef SECCOMP_FILTER_FLAG_LOG
+#define SECCOMP_FILTER_FLAG_LOG 2
+#endif
+
+#ifndef seccomp
+int seccomp(unsigned int op, unsigned int flags, void *args)
+{
+       errno = 0;
+       return syscall(__NR_seccomp, op, flags, args);
+}
+#endif
+
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
 #elif __BYTE_ORDER == __BIG_ENDIAN
@@ -136,7 +198,7 @@ TEST(no_new_privs_support)
        }
 }
 
-/* Tests kernel support by checking for a copy_from_user() fault on NULL. */
+/* Tests kernel support by checking for a copy_from_user() fault on NULL. */
 TEST(mode_filter_support)
 {
        long ret;
@@ -342,6 +404,28 @@ TEST(empty_prog)
        EXPECT_EQ(EINVAL, errno);
 }
 
+TEST(log_all)
+{
+       struct sock_filter filter[] = {
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
+       };
+       struct sock_fprog prog = {
+               .len = (unsigned short)ARRAY_SIZE(filter),
+               .filter = filter,
+       };
+       long ret;
+       pid_t parent = getppid();
+
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+       ASSERT_EQ(0, ret);
+
+       /* getppid() should succeed and be logged (no check for logging) */
+       EXPECT_EQ(parent, syscall(__NR_getppid));
+}
+
 TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS)
 {
        struct sock_filter filter[] = {
@@ -520,6 +604,117 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS)
        close(fd);
 }
 
+/* This is a thread task to die via seccomp filter violation. */
+void *kill_thread(void *data)
+{
+       bool die = (bool)data;
+
+       if (die) {
+               prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
+               return (void *)SIBLING_EXIT_FAILURE;
+       }
+
+       return (void *)SIBLING_EXIT_UNKILLED;
+}
+
+/* Prepare a thread that will kill itself or both of us. */
+void kill_thread_or_group(struct __test_metadata *_metadata, bool kill_process)
+{
+       pthread_t thread;
+       void *status;
+       /* Kill only when calling __NR_prctl. */
+       struct sock_filter filter_thread[] = {
+               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+                       offsetof(struct seccomp_data, nr)),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+       };
+       struct sock_fprog prog_thread = {
+               .len = (unsigned short)ARRAY_SIZE(filter_thread),
+               .filter = filter_thread,
+       };
+       struct sock_filter filter_process[] = {
+               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+                       offsetof(struct seccomp_data, nr)),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_PROCESS),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+       };
+       struct sock_fprog prog_process = {
+               .len = (unsigned short)ARRAY_SIZE(filter_process),
+               .filter = filter_process,
+       };
+
+       ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+               TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+       }
+
+       ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0,
+                            kill_process ? &prog_process : &prog_thread));
+
+       /*
+        * Add the KILL_THREAD rule again to make sure that the KILL_PROCESS
+        * flag cannot be downgraded by a new filter.
+        */
+       ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog_thread));
+
+       /* Start a thread that will exit immediately. */
+       ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)false));
+       ASSERT_EQ(0, pthread_join(thread, &status));
+       ASSERT_EQ(SIBLING_EXIT_UNKILLED, (unsigned long)status);
+
+       /* Start a thread that will die immediately. */
+       ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)true));
+       ASSERT_EQ(0, pthread_join(thread, &status));
+       ASSERT_NE(SIBLING_EXIT_FAILURE, (unsigned long)status);
+
+       /*
+        * If we get here, only the spawned thread died. Let the parent know
+        * the whole process didn't die (i.e. this thread, the spawner,
+        * stayed running).
+        */
+       exit(42);
+}
+
+TEST(KILL_thread)
+{
+       int status;
+       pid_t child_pid;
+
+       child_pid = fork();
+       ASSERT_LE(0, child_pid);
+       if (child_pid == 0) {
+               kill_thread_or_group(_metadata, false);
+               _exit(38);
+       }
+
+       ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
+
+       /* If only the thread was killed, we'll see exit 42. */
+       ASSERT_TRUE(WIFEXITED(status));
+       ASSERT_EQ(42, WEXITSTATUS(status));
+}
+
+TEST(KILL_process)
+{
+       int status;
+       pid_t child_pid;
+
+       child_pid = fork();
+       ASSERT_LE(0, child_pid);
+       if (child_pid == 0) {
+               kill_thread_or_group(_metadata, true);
+               _exit(38);
+       }
+
+       ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
+
+       /* If the entire process was killed, we'll see SIGSYS. */
+       ASSERT_TRUE(WIFSIGNALED(status));
+       ASSERT_EQ(SIGSYS, WTERMSIG(status));
+}
+
 /* TODO(wad) add 64-bit versus 32-bit arg tests. */
 TEST(arg_out_of_range)
 {
@@ -541,26 +736,30 @@ TEST(arg_out_of_range)
        EXPECT_EQ(EINVAL, errno);
 }
 
+#define ERRNO_FILTER(name, errno)                                      \
+       struct sock_filter _read_filter_##name[] = {                    \
+               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,                          \
+                       offsetof(struct seccomp_data, nr)),             \
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),       \
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | errno),     \
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),             \
+       };                                                              \
+       struct sock_fprog prog_##name = {                               \
+               .len = (unsigned short)ARRAY_SIZE(_read_filter_##name), \
+               .filter = _read_filter_##name,                          \
+       }
+
+/* Make sure basic errno values are correctly passed through a filter. */
 TEST(ERRNO_valid)
 {
-       struct sock_filter filter[] = {
-               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-                       offsetof(struct seccomp_data, nr)),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | E2BIG),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-       };
-       struct sock_fprog prog = {
-               .len = (unsigned short)ARRAY_SIZE(filter),
-               .filter = filter,
-       };
+       ERRNO_FILTER(valid, E2BIG);
        long ret;
        pid_t parent = getppid();
 
        ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
        ASSERT_EQ(0, ret);
 
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_valid);
        ASSERT_EQ(0, ret);
 
        EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -568,26 +767,17 @@ TEST(ERRNO_valid)
        EXPECT_EQ(E2BIG, errno);
 }
 
+/* Make sure an errno of zero is correctly handled by the arch code. */
 TEST(ERRNO_zero)
 {
-       struct sock_filter filter[] = {
-               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-                       offsetof(struct seccomp_data, nr)),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 0),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-       };
-       struct sock_fprog prog = {
-               .len = (unsigned short)ARRAY_SIZE(filter),
-               .filter = filter,
-       };
+       ERRNO_FILTER(zero, 0);
        long ret;
        pid_t parent = getppid();
 
        ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
        ASSERT_EQ(0, ret);
 
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_zero);
        ASSERT_EQ(0, ret);
 
        EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -595,26 +785,21 @@ TEST(ERRNO_zero)
        EXPECT_EQ(0, read(0, NULL, 0));
 }
 
+/*
+ * The SECCOMP_RET_DATA mask is 16 bits wide, but errno is smaller.
+ * This tests that the errno value gets capped correctly, fixed by
+ * 580c57f10768 ("seccomp: cap SECCOMP_RET_ERRNO data to MAX_ERRNO").
+ */
 TEST(ERRNO_capped)
 {
-       struct sock_filter filter[] = {
-               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-                       offsetof(struct seccomp_data, nr)),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 4096),
-               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-       };
-       struct sock_fprog prog = {
-               .len = (unsigned short)ARRAY_SIZE(filter),
-               .filter = filter,
-       };
+       ERRNO_FILTER(capped, 4096);
        long ret;
        pid_t parent = getppid();
 
        ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
        ASSERT_EQ(0, ret);
 
-       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_capped);
        ASSERT_EQ(0, ret);
 
        EXPECT_EQ(parent, syscall(__NR_getppid));
@@ -622,6 +807,37 @@ TEST(ERRNO_capped)
        EXPECT_EQ(4095, errno);
 }
 
+/*
+ * Filters are processed in reverse order: last applied is executed first.
+ * Since only the SECCOMP_RET_ACTION mask is tested for return values, the
+ * SECCOMP_RET_DATA mask results will follow the most recently applied
+ * matching filter return (and not the lowest or highest value).
+ */
+TEST(ERRNO_order)
+{
+       ERRNO_FILTER(first,  11);
+       ERRNO_FILTER(second, 13);
+       ERRNO_FILTER(third,  12);
+       long ret;
+       pid_t parent = getppid();
+
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_first);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_second);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_third);
+       ASSERT_EQ(0, ret);
+
+       EXPECT_EQ(parent, syscall(__NR_getppid));
+       EXPECT_EQ(-1, read(0, NULL, 0));
+       EXPECT_EQ(12, errno);
+}
+
 FIXTURE_DATA(TRAP) {
        struct sock_fprog prog;
 };
@@ -676,7 +892,7 @@ TEST_F_SIGNAL(TRAP, ign, SIGSYS)
        syscall(__NR_getpid);
 }
 
-static struct siginfo TRAP_info;
+static siginfo_t TRAP_info;
 static volatile int TRAP_nr;
 static void TRAP_action(int nr, siginfo_t *info, void *void_context)
 {
@@ -735,6 +951,7 @@ TEST_F(TRAP, handler)
 
 FIXTURE_DATA(precedence) {
        struct sock_fprog allow;
+       struct sock_fprog log;
        struct sock_fprog trace;
        struct sock_fprog error;
        struct sock_fprog trap;
@@ -746,6 +963,13 @@ FIXTURE_SETUP(precedence)
        struct sock_filter allow_insns[] = {
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
        };
+       struct sock_filter log_insns[] = {
+               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+                       offsetof(struct seccomp_data, nr)),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
+       };
        struct sock_filter trace_insns[] = {
                BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
                        offsetof(struct seccomp_data, nr)),
@@ -782,6 +1006,7 @@ FIXTURE_SETUP(precedence)
        memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
        self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns)
        FILTER_ALLOC(allow);
+       FILTER_ALLOC(log);
        FILTER_ALLOC(trace);
        FILTER_ALLOC(error);
        FILTER_ALLOC(trap);
@@ -792,6 +1017,7 @@ FIXTURE_TEARDOWN(precedence)
 {
 #define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
        FILTER_FREE(allow);
+       FILTER_FREE(log);
        FILTER_FREE(trace);
        FILTER_FREE(error);
        FILTER_FREE(trap);
@@ -809,6 +1035,8 @@ TEST_F(precedence, allow_ok)
 
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
        ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -833,6 +1061,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS)
 
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
        ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -864,6 +1094,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS)
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
        ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
@@ -885,6 +1117,8 @@ TEST_F_SIGNAL(precedence, trap_is_second, SIGSYS)
 
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
        ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -910,6 +1144,8 @@ TEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS)
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
        ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -931,6 +1167,8 @@ TEST_F(precedence, errno_is_third)
 
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
        ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
@@ -949,6 +1187,8 @@ TEST_F(precedence, errno_is_third_in_any_order)
        ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
        ASSERT_EQ(0, ret);
 
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
@@ -971,6 +1211,8 @@ TEST_F(precedence, trace_is_fourth)
 
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
        ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
        ASSERT_EQ(0, ret);
        /* Should work just fine. */
@@ -992,12 +1234,54 @@ TEST_F(precedence, trace_is_fourth_in_any_order)
        ASSERT_EQ(0, ret);
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
        ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
        /* Should work just fine. */
        EXPECT_EQ(parent, syscall(__NR_getppid));
        /* No ptracer */
        EXPECT_EQ(-1, syscall(__NR_getpid));
 }
 
+TEST_F(precedence, log_is_fifth)
+{
+       pid_t mypid, parent;
+       long ret;
+
+       mypid = getpid();
+       parent = getppid();
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+       ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
+       /* Should work just fine. */
+       EXPECT_EQ(parent, syscall(__NR_getppid));
+       /* Should also work just fine */
+       EXPECT_EQ(mypid, syscall(__NR_getpid));
+}
+
+TEST_F(precedence, log_is_fifth_in_any_order)
+{
+       pid_t mypid, parent;
+       long ret;
+
+       mypid = getpid();
+       parent = getppid();
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
+       ASSERT_EQ(0, ret);
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+       ASSERT_EQ(0, ret);
+       /* Should work just fine. */
+       EXPECT_EQ(parent, syscall(__NR_getppid));
+       /* Should also work just fine */
+       EXPECT_EQ(mypid, syscall(__NR_getpid));
+}
+
 #ifndef PTRACE_O_TRACESECCOMP
 #define PTRACE_O_TRACESECCOMP  0x00000080
 #endif
@@ -1262,6 +1546,13 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 # error "Do not know how to find your architecture's registers and syscalls"
 #endif
 
+/* When the syscall return can't be changed, stub out the tests for it. */
+#ifdef SYSCALL_NUM_RET_SHARE_REG
+# define EXPECT_SYSCALL_RETURN(val, action)    EXPECT_EQ(-1, action)
+#else
+# define EXPECT_SYSCALL_RETURN(val, action)    EXPECT_EQ(val, action)
+#endif
+
 /* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
  * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
  */
@@ -1357,7 +1648,7 @@ void change_syscall(struct __test_metadata *_metadata,
 #ifdef SYSCALL_NUM_RET_SHARE_REG
                TH_LOG("Can't modify syscall return on this architecture");
 #else
-               regs.SYSCALL_RET = 1;
+               regs.SYSCALL_RET = EPERM;
 #endif
 
 #ifdef HAVE_GETREGS
@@ -1426,6 +1717,8 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
 
        if (nr == __NR_getpid)
                change_syscall(_metadata, tracee, __NR_getppid);
+       if (nr == __NR_open)
+               change_syscall(_metadata, tracee, -1);
 }
 
 FIXTURE_DATA(TRACE_syscall) {
@@ -1480,6 +1773,28 @@ FIXTURE_TEARDOWN(TRACE_syscall)
                free(self->prog.filter);
 }
 
+TEST_F(TRACE_syscall, ptrace_syscall_redirected)
+{
+       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
+       teardown_trace_fixture(_metadata, self->tracer);
+       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
+                                          true);
+
+       /* Tracer will redirect getpid to getppid. */
+       EXPECT_NE(self->mypid, syscall(__NR_getpid));
+}
+
+TEST_F(TRACE_syscall, ptrace_syscall_dropped)
+{
+       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
+       teardown_trace_fixture(_metadata, self->tracer);
+       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
+                                          true);
+
+       /* Tracer should skip the open syscall, resulting in EPERM. */
+       EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_open));
+}
+
 TEST_F(TRACE_syscall, syscall_allowed)
 {
        long ret;
@@ -1520,13 +1835,8 @@ TEST_F(TRACE_syscall, syscall_dropped)
        ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
        ASSERT_EQ(0, ret);
 
-#ifdef SYSCALL_NUM_RET_SHARE_REG
-       /* gettid has been skipped */
-       EXPECT_EQ(-1, syscall(__NR_gettid));
-#else
        /* gettid has been skipped and an altered return value stored. */
-       EXPECT_EQ(1, syscall(__NR_gettid));
-#endif
+       EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
        EXPECT_NE(self->mytid, syscall(__NR_gettid));
 }
 
@@ -1557,6 +1867,7 @@ TEST_F(TRACE_syscall, skip_after_RET_TRACE)
        ASSERT_EQ(0, ret);
 
        /* Tracer will redirect getpid to getppid, and we should see EPERM. */
+       errno = 0;
        EXPECT_EQ(-1, syscall(__NR_getpid));
        EXPECT_EQ(EPERM, errno);
 }
@@ -1654,47 +1965,6 @@ TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
        EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-#ifndef __NR_seccomp
-# if defined(__i386__)
-#  define __NR_seccomp 354
-# elif defined(__x86_64__)
-#  define __NR_seccomp 317
-# elif defined(__arm__)
-#  define __NR_seccomp 383
-# elif defined(__aarch64__)
-#  define __NR_seccomp 277
-# elif defined(__hppa__)
-#  define __NR_seccomp 338
-# elif defined(__powerpc__)
-#  define __NR_seccomp 358
-# elif defined(__s390__)
-#  define __NR_seccomp 348
-# else
-#  warning "seccomp syscall number unknown for this architecture"
-#  define __NR_seccomp 0xffff
-# endif
-#endif
-
-#ifndef SECCOMP_SET_MODE_STRICT
-#define SECCOMP_SET_MODE_STRICT 0
-#endif
-
-#ifndef SECCOMP_SET_MODE_FILTER
-#define SECCOMP_SET_MODE_FILTER 1
-#endif
-
-#ifndef SECCOMP_FILTER_FLAG_TSYNC
-#define SECCOMP_FILTER_FLAG_TSYNC 1
-#endif
-
-#ifndef seccomp
-int seccomp(unsigned int op, unsigned int flags, void *args)
-{
-       errno = 0;
-       return syscall(__NR_seccomp, op, flags, args);
-}
-#endif
-
 TEST(seccomp_syscall)
 {
        struct sock_filter filter[] = {
@@ -1783,6 +2053,67 @@ TEST(seccomp_syscall_mode_lock)
        }
 }
 
+/*
+ * Test detection of known and unknown filter flags. Userspace needs to be able
+ * to check if a filter flag is supported by the current kernel and a good way
+ * of doing that is by attempting to enter filter mode, with the flag bit in
+ * question set, and a NULL pointer for the _args_ parameter. EFAULT indicates
+ * that the flag is valid and EINVAL indicates that the flag is invalid.
+ */
+TEST(detect_seccomp_filter_flags)
+{
+       unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
+                                SECCOMP_FILTER_FLAG_LOG };
+       unsigned int flag, all_flags;
+       int i;
+       long ret;
+
+       /* Test detection of known-good filter flags */
+       for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
+               flag = flags[i];
+               ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
+               ASSERT_NE(ENOSYS, errno) {
+                       TH_LOG("Kernel does not support seccomp syscall!");
+               }
+               EXPECT_EQ(-1, ret);
+               EXPECT_EQ(EFAULT, errno) {
+                       TH_LOG("Failed to detect that a known-good filter flag (0x%X) is supported!",
+                              flag);
+               }
+
+               all_flags |= flag;
+       }
+
+       /* Test detection of all known-good filter flags */
+       ret = seccomp(SECCOMP_SET_MODE_FILTER, all_flags, NULL);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EFAULT, errno) {
+               TH_LOG("Failed to detect that all known-good filter flags (0x%X) are supported!",
+                      all_flags);
+       }
+
+       /* Test detection of an unknown filter flag */
+       flag = -1;
+       ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EINVAL, errno) {
+               TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported!",
+                      flag);
+       }
+
+       /*
+        * Test detection of an unknown filter flag that may simply need to be
+        * added to this test
+        */
+       flag = flags[ARRAY_SIZE(flags) - 1] << 1;
+       ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EINVAL, errno) {
+               TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported! Does a new flag need to be added to this test?",
+                      flag);
+       }
+}
+
 TEST(TSYNC_first)
 {
        struct sock_filter filter[] = {
@@ -2421,6 +2752,99 @@ TEST(syscall_restart)
                _metadata->passed = 0;
 }
 
+TEST_SIGNAL(filter_flag_log, SIGSYS)
+{
+       struct sock_filter allow_filter[] = {
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+       };
+       struct sock_filter kill_filter[] = {
+               BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+                       offsetof(struct seccomp_data, nr)),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+       };
+       struct sock_fprog allow_prog = {
+               .len = (unsigned short)ARRAY_SIZE(allow_filter),
+               .filter = allow_filter,
+       };
+       struct sock_fprog kill_prog = {
+               .len = (unsigned short)ARRAY_SIZE(kill_filter),
+               .filter = kill_filter,
+       };
+       long ret;
+       pid_t parent = getppid();
+
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       /* Verify that the FILTER_FLAG_LOG flag isn't accepted in strict mode */
+       ret = seccomp(SECCOMP_SET_MODE_STRICT, SECCOMP_FILTER_FLAG_LOG,
+                     &allow_prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
+       EXPECT_NE(0, ret) {
+               TH_LOG("Kernel accepted FILTER_FLAG_LOG flag in strict mode!");
+       }
+       EXPECT_EQ(EINVAL, errno) {
+               TH_LOG("Kernel returned unexpected errno for FILTER_FLAG_LOG flag in strict mode!");
+       }
+
+       /* Verify that a simple, permissive filter can be added with no flags */
+       ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &allow_prog);
+       EXPECT_EQ(0, ret);
+
+       /* See if the same filter can be added with the FILTER_FLAG_LOG flag */
+       ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
+                     &allow_prog);
+       ASSERT_NE(EINVAL, errno) {
+               TH_LOG("Kernel does not support the FILTER_FLAG_LOG flag!");
+       }
+       EXPECT_EQ(0, ret);
+
+       /* Ensure that the kill filter works with the FILTER_FLAG_LOG flag */
+       ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
+                     &kill_prog);
+       EXPECT_EQ(0, ret);
+
+       EXPECT_EQ(parent, syscall(__NR_getppid));
+       /* getpid() should never return. */
+       EXPECT_EQ(0, syscall(__NR_getpid));
+}
+
+TEST(get_action_avail)
+{
+       __u32 actions[] = { SECCOMP_RET_KILL_THREAD, SECCOMP_RET_TRAP,
+                           SECCOMP_RET_ERRNO, SECCOMP_RET_TRACE,
+                           SECCOMP_RET_LOG,   SECCOMP_RET_ALLOW };
+       __u32 unknown_action = 0x10000000U;
+       int i;
+       long ret;
+
+       ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[0]);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
+       ASSERT_NE(EINVAL, errno) {
+               TH_LOG("Kernel does not support SECCOMP_GET_ACTION_AVAIL operation!");
+       }
+       EXPECT_EQ(ret, 0);
+
+       for (i = 0; i < ARRAY_SIZE(actions); i++) {
+               ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[i]);
+               EXPECT_EQ(ret, 0) {
+                       TH_LOG("Expected action (0x%X) not available!",
+                              actions[i]);
+               }
+       }
+
+       /* Check that an unknown action is handled properly (EOPNOTSUPP) */
+       ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &unknown_action);
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, EOPNOTSUPP);
+}
+
 /*
  * TODO:
  * - add microbenchmarks
@@ -2429,6 +2853,8 @@ TEST(syscall_restart)
  * - endianness checking when appropriate
  * - 64-bit arg prodding
  * - arch value testing (x86 modes especially)
+ * - verify that FILTER_FLAG_LOG filters generate log messages
+ * - verify that RET_LOG generates log messages
  * - ...
  */
 
index 7d406c3973ba4944a4baee8363f59c736a98b52e..97bb150837df02422fc8a005d683cebb6191878f 100644 (file)
@@ -39,7 +39,11 @@ void my_usr1(int sig, siginfo_t *si, void *u)
        stack_t stk;
        struct stk_data *p;
 
+#if __s390x__
+       register unsigned long sp asm("%15");
+#else
        register unsigned long sp asm("sp");
+#endif
 
        if (sp < (unsigned long)sstack ||
                        sp >= (unsigned long)sstack + SIGSTKSZ) {
index 4981c6b6d050e95b77fa1540640a4b71770179f2..8e04d0afcbd7f9f820af5c550a0fa4741fc62141 100644 (file)
@@ -2,12 +2,16 @@ CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
 CFLAGS += -I../../../../usr/include/
 LDFLAGS += -pthread
 
-TEST_PROGS = sync_test
-
-all: $(TEST_PROGS)
+.PHONY: all clean
 
 include ../lib.mk
 
+# lib.mk TEST_CUSTOM_PROGS var is for custom tests that need special
+# build rules. lib.mk will run and install them.
+
+TEST_CUSTOM_PROGS := $(OUTPUT)/sync_test
+all: $(TEST_CUSTOM_PROGS)
+
 OBJS = sync_test.o sync.o
 
 TESTS += sync_alloc.o
@@ -18,6 +22,16 @@ TESTS += sync_stress_parallelism.o
 TESTS += sync_stress_consumer.o
 TESTS += sync_stress_merge.o
 
-sync_test: $(OBJS) $(TESTS)
+OBJS := $(patsubst %,$(OUTPUT)/%,$(OBJS))
+TESTS := $(patsubst %,$(OUTPUT)/%,$(TESTS))
+
+$(TEST_CUSTOM_PROGS): $(TESTS) $(OBJS)
+       $(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS)
+
+$(OBJS): $(OUTPUT)/%.o: %.c
+       $(CC) -c $^ -o $@
+
+$(TESTS): $(OUTPUT)/%.o: %.c
+       $(CC) -c $^ -o $@
 
-EXTRA_CLEAN := sync_test $(OBJS) $(TESTS)
+EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS)
index 9c92b7bd56410a38a0da0370bbee202f22d0778c..50da45437daab0b5785a4925ac793644cb9d02fd 100644 (file)
@@ -143,7 +143,8 @@ int setup_timer(int clock_id, int flags, int interval, timer_t *tm1)
                        printf("%-22s %s missing CAP_WAKE_ALARM?    : [UNSUPPORTED]\n",
                                        clockstring(clock_id),
                                        flags ? "ABSTIME":"RELTIME");
-                       return 0;
+                       /* Indicate timer isn't set, so caller doesn't wait */
+                       return 1;
                }
                printf("%s - timer_create() failed\n", clockstring(clock_id));
                return -1;
@@ -213,8 +214,9 @@ int do_timer(int clock_id, int flags)
        int err;
 
        err = setup_timer(clock_id, flags, interval, &tm1);
+       /* Unsupported case - return 0 to not fail the test */
        if (err)
-               return err;
+               return err == 1 ? 0 : err;
 
        while (alarmcount < 5)
                sleep(1);
@@ -228,18 +230,17 @@ int do_timer_oneshot(int clock_id, int flags)
        timer_t tm1;
        const int interval = 0;
        struct timeval timeout;
-       fd_set fds;
        int err;
 
        err = setup_timer(clock_id, flags, interval, &tm1);
+       /* Unsupported case - return 0 to not fail the test */
        if (err)
-               return err;
+               return err == 1 ? 0 : err;
 
        memset(&timeout, 0, sizeof(timeout));
        timeout.tv_sec = 5;
-       FD_ZERO(&fds);
        do {
-               err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
+               err = select(0, NULL, NULL, NULL, &timeout);
        } while (err == -1 && errno == EINTR);
 
        timer_delete(tm1);
index f863c664e3d143be1dd439a6098d5e389a49e762..ee068511fd0bc68ba8cb8b54bbe8a5c9371c322e 100644 (file)
@@ -1,8 +1,3 @@
-TEST_PROGS := watchdog-test
-
-all: $(TEST_PROGS)
+TEST_GEN_PROGS := watchdog-test
 
 include ../lib.mk
-
-clean:
-       rm -fr $(TEST_PROGS)
index c608ab495282ddb63ace657ce0a6deeea18a2240..f2ac53ab82438f0b473ecd8ed91b1e2548af7ca2 100644 (file)
@@ -565,8 +565,6 @@ kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
 {
        if (args->flags & ~(KVM_IRQFD_FLAG_DEASSIGN | KVM_IRQFD_FLAG_RESAMPLE))
                return -EINVAL;
-       if (args->gsi >= KVM_MAX_IRQ_ROUTES)
-               return -EINVAL;
 
        if (args->flags & KVM_IRQFD_FLAG_DEASSIGN)
                return kvm_irqfd_deassign(kvm, args);