Merge tag 'scmi-fixes-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep...
authorOlof Johansson <olof@lixom.net>
Sun, 29 Sep 2019 18:19:18 +0000 (11:19 -0700)
committerOlof Johansson <olof@lixom.net>
Sun, 29 Sep 2019 18:20:41 +0000 (11:20 -0700)
ARM SCMI fixes for v5.4

Couple of fixes: one in scmi reset driver initialising missed scmi handle
and an other in scmi reset API implementation fixing the assignment of
reset state

* tag 'scmi-fixes-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  reset: reset-scmi: add missing handle initialisation
  firmware: arm_scmi: reset: fix reset_state assignment in scmi_domain_reset

Link: https://lore.kernel.org/r/20190918142139.GA4370@bogus
Signed-off-by: Olof Johansson <olof@lixom.net>
2078 files changed:
.clang-format
.gitignore
.mailmap
Documentation/PCI/index.rst
Documentation/PCI/pci-error-recovery.rst
Documentation/PCI/pciebus-howto.rst [new file with mode: 0644]
Documentation/PCI/picebus-howto.rst [deleted file]
Documentation/RCU/rculist_nulls.txt
Documentation/admin-guide/conf.py [deleted file]
Documentation/admin-guide/hw-vuln/spectre.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/mm/transhuge.rst
Documentation/admin-guide/sysctl/net.rst
Documentation/conf.py
Documentation/core-api/conf.py [deleted file]
Documentation/crypto/conf.py [deleted file]
Documentation/dev-tools/conf.py [deleted file]
Documentation/devicetree/bindings/Makefile
Documentation/devicetree/bindings/arm/idle-states.txt
Documentation/devicetree/bindings/arm/renesas.yaml
Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml
Documentation/devicetree/bindings/arm/ti/ti,davinci.yaml
Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt
Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml [deleted file]
Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
Documentation/devicetree/bindings/net/dsa/ksz.txt
Documentation/devicetree/bindings/net/fsl-fec.txt
Documentation/devicetree/bindings/net/macb.txt
Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/nvmem/nvmem.txt
Documentation/devicetree/bindings/nvmem/nvmem.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml
Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
Documentation/devicetree/bindings/riscv/cpus.txt [deleted file]
Documentation/devicetree/bindings/riscv/cpus.yaml
Documentation/devicetree/bindings/riscv/sifive.yaml
Documentation/devicetree/bindings/spi/spi-controller.yaml
Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
Documentation/devicetree/bindings/usb/usb251xb.txt
Documentation/doc-guide/conf.py [deleted file]
Documentation/driver-api/80211/conf.py [deleted file]
Documentation/driver-api/conf.py [deleted file]
Documentation/driver-api/generic-counter.rst
Documentation/driver-api/phy/phy.rst
Documentation/driver-api/pm/conf.py [deleted file]
Documentation/filesystems/cifs/TODO
Documentation/filesystems/conf.py [deleted file]
Documentation/gpu/conf.py [deleted file]
Documentation/hwmon/k8temp.rst
Documentation/index.rst
Documentation/input/conf.py [deleted file]
Documentation/kernel-hacking/conf.py [deleted file]
Documentation/locking/spinlocks.rst
Documentation/maintainer/conf.py [deleted file]
Documentation/media/conf.py [deleted file]
Documentation/memory-barriers.txt
Documentation/networking/conf.py [deleted file]
Documentation/networking/tls-offload.rst
Documentation/networking/tuntap.txt
Documentation/power/index.rst
Documentation/powerpc/DAWR-POWER9.txt [deleted file]
Documentation/powerpc/bootwrapper.rst [new file with mode: 0644]
Documentation/powerpc/bootwrapper.txt [deleted file]
Documentation/powerpc/cpu_families.rst [new file with mode: 0644]
Documentation/powerpc/cpu_families.txt [deleted file]
Documentation/powerpc/cpu_features.rst [new file with mode: 0644]
Documentation/powerpc/cpu_features.txt [deleted file]
Documentation/powerpc/cxl.rst [new file with mode: 0644]
Documentation/powerpc/cxl.txt [deleted file]
Documentation/powerpc/cxlflash.rst [new file with mode: 0644]
Documentation/powerpc/cxlflash.txt [deleted file]
Documentation/powerpc/dawr-power9.rst [new file with mode: 0644]
Documentation/powerpc/dscr.rst [new file with mode: 0644]
Documentation/powerpc/dscr.txt [deleted file]
Documentation/powerpc/eeh-pci-error-recovery.rst [new file with mode: 0644]
Documentation/powerpc/eeh-pci-error-recovery.txt [deleted file]
Documentation/powerpc/firmware-assisted-dump.rst [new file with mode: 0644]
Documentation/powerpc/firmware-assisted-dump.txt [deleted file]
Documentation/powerpc/hvcs.rst [new file with mode: 0644]
Documentation/powerpc/hvcs.txt [deleted file]
Documentation/powerpc/index.rst [new file with mode: 0644]
Documentation/powerpc/isa-versions.rst
Documentation/powerpc/mpc52xx.rst [new file with mode: 0644]
Documentation/powerpc/mpc52xx.txt [deleted file]
Documentation/powerpc/pci_iov_resource_on_powernv.rst [new file with mode: 0644]
Documentation/powerpc/pci_iov_resource_on_powernv.txt [deleted file]
Documentation/powerpc/pmu-ebb.rst [new file with mode: 0644]
Documentation/powerpc/pmu-ebb.txt [deleted file]
Documentation/powerpc/ptrace.rst [new file with mode: 0644]
Documentation/powerpc/ptrace.txt [deleted file]
Documentation/powerpc/qe_firmware.rst [new file with mode: 0644]
Documentation/powerpc/qe_firmware.txt [deleted file]
Documentation/powerpc/syscall64-abi.rst [new file with mode: 0644]
Documentation/powerpc/syscall64-abi.txt [deleted file]
Documentation/powerpc/transactional_memory.rst [new file with mode: 0644]
Documentation/powerpc/transactional_memory.txt [deleted file]
Documentation/process/conf.py [deleted file]
Documentation/process/deprecated.rst
Documentation/process/embargoed-hardware-issues.rst [new file with mode: 0644]
Documentation/process/index.rst
Documentation/riscv/boot-image-header.txt
Documentation/s390/vfio-ccw.rst
Documentation/sh/conf.py [deleted file]
Documentation/sound/conf.py [deleted file]
Documentation/sphinx/load_config.py
Documentation/translations/it_IT/doc-guide/sphinx.rst
Documentation/translations/it_IT/process/index.rst
Documentation/translations/it_IT/process/kernel-docs.rst
Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
Documentation/translations/it_IT/process/programming-language.rst [new file with mode: 0644]
Documentation/translations/ko_KR/memory-barriers.txt
Documentation/userspace-api/conf.py [deleted file]
Documentation/virt/index.rst [new file with mode: 0644]
Documentation/virt/kvm/amd-memory-encryption.rst [new file with mode: 0644]
Documentation/virt/kvm/api.txt [new file with mode: 0644]
Documentation/virt/kvm/arm/hyp-abi.txt [new file with mode: 0644]
Documentation/virt/kvm/arm/psci.txt [new file with mode: 0644]
Documentation/virt/kvm/cpuid.rst [new file with mode: 0644]
Documentation/virt/kvm/devices/README [new file with mode: 0644]
Documentation/virt/kvm/devices/arm-vgic-its.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/arm-vgic-v3.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/arm-vgic.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/mpic.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/s390_flic.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/vcpu.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/vfio.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/vm.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/xics.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/xive.txt [new file with mode: 0644]
Documentation/virt/kvm/halt-polling.txt [new file with mode: 0644]
Documentation/virt/kvm/hypercalls.txt [new file with mode: 0644]
Documentation/virt/kvm/index.rst [new file with mode: 0644]
Documentation/virt/kvm/locking.txt [new file with mode: 0644]
Documentation/virt/kvm/mmu.txt [new file with mode: 0644]
Documentation/virt/kvm/msr.txt [new file with mode: 0644]
Documentation/virt/kvm/nested-vmx.txt [new file with mode: 0644]
Documentation/virt/kvm/ppc-pv.txt [new file with mode: 0644]
Documentation/virt/kvm/review-checklist.txt [new file with mode: 0644]
Documentation/virt/kvm/s390-diag.txt [new file with mode: 0644]
Documentation/virt/kvm/timekeeping.txt [new file with mode: 0644]
Documentation/virt/kvm/vcpu-requests.rst [new file with mode: 0644]
Documentation/virt/paravirt_ops.rst [new file with mode: 0644]
Documentation/virt/uml/UserModeLinux-HOWTO.txt [new file with mode: 0644]
Documentation/virtual/index.rst [deleted file]
Documentation/virtual/kvm/amd-memory-encryption.rst [deleted file]
Documentation/virtual/kvm/api.txt [deleted file]
Documentation/virtual/kvm/arm/hyp-abi.txt [deleted file]
Documentation/virtual/kvm/arm/psci.txt [deleted file]
Documentation/virtual/kvm/cpuid.rst [deleted file]
Documentation/virtual/kvm/devices/README [deleted file]
Documentation/virtual/kvm/devices/arm-vgic-its.txt [deleted file]
Documentation/virtual/kvm/devices/arm-vgic-v3.txt [deleted file]
Documentation/virtual/kvm/devices/arm-vgic.txt [deleted file]
Documentation/virtual/kvm/devices/mpic.txt [deleted file]
Documentation/virtual/kvm/devices/s390_flic.txt [deleted file]
Documentation/virtual/kvm/devices/vcpu.txt [deleted file]
Documentation/virtual/kvm/devices/vfio.txt [deleted file]
Documentation/virtual/kvm/devices/vm.txt [deleted file]
Documentation/virtual/kvm/devices/xics.txt [deleted file]
Documentation/virtual/kvm/devices/xive.txt [deleted file]
Documentation/virtual/kvm/halt-polling.txt [deleted file]
Documentation/virtual/kvm/hypercalls.txt [deleted file]
Documentation/virtual/kvm/index.rst [deleted file]
Documentation/virtual/kvm/locking.txt [deleted file]
Documentation/virtual/kvm/mmu.txt [deleted file]
Documentation/virtual/kvm/msr.txt [deleted file]
Documentation/virtual/kvm/nested-vmx.txt [deleted file]
Documentation/virtual/kvm/ppc-pv.txt [deleted file]
Documentation/virtual/kvm/review-checklist.txt [deleted file]
Documentation/virtual/kvm/s390-diag.txt [deleted file]
Documentation/virtual/kvm/timekeeping.txt [deleted file]
Documentation/virtual/kvm/vcpu-requests.rst [deleted file]
Documentation/virtual/paravirt_ops.rst [deleted file]
Documentation/virtual/uml/UserModeLinux-HOWTO.txt [deleted file]
Documentation/vm/conf.py [deleted file]
Documentation/vm/hmm.rst
Documentation/watchdog/hpwdt.rst
Documentation/x86/conf.py [deleted file]
MAINTAINERS
Makefile
arch/arc/boot/dts/Makefile
arch/arc/include/asm/entry-arcv2.h
arch/arc/include/asm/linkage.h
arch/arc/include/asm/mach_desc.h
arch/arc/kernel/mcip.c
arch/arc/kernel/unwind.c
arch/arc/mm/dma.c
arch/arc/plat-hsdk/platform.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/boot/dts/am33xx-l4.dtsi
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am437x-l4.dtsi
arch/arm/boot/dts/am571x-idk.dts
arch/arm/boot/dts/am572x-idk.dts
arch/arm/boot/dts/am574x-idk.dts
arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts
arch/arm/boot/dts/am57xx-beagle-x15-revc.dts
arch/arm/boot/dts/bcm47094-linksys-panamera.dts
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7-l4.dtsi
arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi
arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
arch/arm/boot/dts/imx6ul-geam.dts
arch/arm/boot/dts/imx6ul-isiot.dtsi
arch/arm/boot/dts/imx6ul-pico-hobbit.dts
arch/arm/boot/dts/imx6ul-pico-pi.dts
arch/arm/boot/dts/imx7ulp.dtsi
arch/arm/boot/dts/vf610-bk4.dts
arch/arm/configs/u8500_defconfig
arch/arm/include/asm/dma-mapping.h
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/signal.c
arch/arm/kvm/coproc.c
arch/arm/lib/backtrace.S
arch/arm/mach-aspeed/Kconfig
arch/arm/mach-davinci/sleep.S
arch/arm/mach-ep93xx/crunch.c
arch/arm/mach-netx/Kconfig [deleted file]
arch/arm/mach-netx/Makefile [deleted file]
arch/arm/mach-netx/Makefile.boot [deleted file]
arch/arm/mach-netx/fb.c [deleted file]
arch/arm/mach-netx/fb.h [deleted file]
arch/arm/mach-netx/generic.c [deleted file]
arch/arm/mach-netx/generic.h [deleted file]
arch/arm/mach-netx/include/mach/hardware.h [deleted file]
arch/arm/mach-netx/include/mach/irqs.h [deleted file]
arch/arm/mach-netx/include/mach/netx-regs.h [deleted file]
arch/arm/mach-netx/include/mach/pfifo.h [deleted file]
arch/arm/mach-netx/include/mach/uncompress.h [deleted file]
arch/arm/mach-netx/include/mach/xc.h [deleted file]
arch/arm/mach-netx/nxdb500.c [deleted file]
arch/arm/mach-netx/nxdkn.c [deleted file]
arch/arm/mach-netx/nxeb500hmi.c [deleted file]
arch/arm/mach-netx/pfifo.c [deleted file]
arch/arm/mach-netx/time.c [deleted file]
arch/arm/mach-netx/xc.c [deleted file]
arch/arm/mach-omap1/ams-delta-fiq-handler.S
arch/arm/mach-omap1/ams-delta-fiq.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-rpc/riscpc.c
arch/arm/mach-tegra/reset.c
arch/arm/mm/Kconfig
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/plat-omap/dma.c
arch/arm64/Makefile
arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts
arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/renesas/hihope-common.dtsi
arch/arm64/boot/dts/renesas/r8a77995-draak.dts
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/daifflags.h
arch/arm64/include/asm/efi.h
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/processor.h
arch/arm64/include/asm/ptrace.h
arch/arm64/include/asm/stacktrace.h
arch/arm64/include/asm/vdso/compat_gettimeofday.h
arch/arm64/include/uapi/asm/bpf_perf_event.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/ftrace.c
arch/arm64/kernel/hw_breakpoint.c
arch/arm64/kernel/module.c
arch/arm64/kernel/perf_callchain.c
arch/arm64/kernel/probes/kprobes.c
arch/arm64/kernel/process.c
arch/arm64/kernel/return_address.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/stacktrace.c
arch/arm64/kernel/time.c
arch/arm64/kernel/traps.c
arch/arm64/kernel/vdso/Makefile
arch/arm64/kernel/vdso32/Makefile
arch/arm64/kvm/hyp/debug-sr.c
arch/arm64/kvm/regmap.c
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/fault.c
arch/csky/include/uapi/asm/byteorder.h
arch/csky/include/uapi/asm/cachectl.h
arch/csky/include/uapi/asm/perf_regs.h
arch/csky/include/uapi/asm/ptrace.h
arch/csky/include/uapi/asm/sigcontext.h
arch/csky/include/uapi/asm/unistd.h
arch/mips/cavium-octeon/octeon-usb.c
arch/mips/include/asm/octeon/cvmx-sli-defs.h
arch/mips/kernel/cacheinfo.c
arch/mips/kernel/i8253.c
arch/mips/kvm/emulate.c
arch/mips/kvm/mips.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pci/ops-bcm63xx.c
arch/mips/vdso/vdso.h
arch/nds32/include/uapi/asm/auxvec.h
arch/nds32/include/uapi/asm/byteorder.h
arch/nds32/include/uapi/asm/cachectl.h
arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
arch/nds32/include/uapi/asm/param.h
arch/nds32/include/uapi/asm/ptrace.h
arch/nds32/include/uapi/asm/sigcontext.h
arch/nds32/include/uapi/asm/unistd.h
arch/nds32/kernel/signal.c
arch/parisc/Makefile
arch/parisc/boot/compressed/Makefile
arch/parisc/boot/compressed/vmlinux.lds.S
arch/parisc/configs/default_defconfig [deleted file]
arch/parisc/configs/defconfig [new file with mode: 0644]
arch/parisc/include/asm/kprobes.h
arch/parisc/include/asm/pgtable.h
arch/parisc/kernel/ftrace.c
arch/parisc/kernel/pacache.S
arch/parisc/math-emu/Makefile
arch/parisc/mm/fault.c
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/hvcall.h
arch/powerpc/include/asm/pmc.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/bpf_perf_event.h
arch/powerpc/include/uapi/asm/kvm_para.h
arch/powerpc/kernel/align.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/syscalls/syscall.tbl
arch/powerpc/kvm/book3s_32_mmu.c
arch/powerpc/kvm/book3s_64_vio.c
arch/powerpc/kvm/book3s_64_vio_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_xive.c
arch/powerpc/kvm/book3s_xive_native.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/book3s64/hash_utils.c
arch/powerpc/mm/kasan/kasan_init_32.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/nohash/tlb.c
arch/powerpc/platforms/pseries/papr_scm.c
arch/powerpc/sysdev/xive/common.c
arch/riscv/boot/dts/sifive/fu540-c000.dtsi
arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
arch/riscv/configs/defconfig
arch/riscv/configs/rv32_defconfig
arch/riscv/include/asm/Kbuild
arch/riscv/include/asm/fixmap.h
arch/riscv/include/asm/image.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/switch_to.h
arch/riscv/include/asm/tlbflush.h
arch/riscv/include/uapi/asm/auxvec.h
arch/riscv/include/uapi/asm/bitsperlong.h
arch/riscv/include/uapi/asm/byteorder.h
arch/riscv/include/uapi/asm/hwcap.h
arch/riscv/include/uapi/asm/ptrace.h
arch/riscv/include/uapi/asm/sigcontext.h
arch/riscv/include/uapi/asm/ucontext.h
arch/riscv/include/uapi/asm/unistd.h
arch/riscv/kernel/head.S
arch/riscv/kernel/process.c
arch/riscv/kernel/vdso/Makefile
arch/riscv/lib/Makefile
arch/riscv/lib/delay.c
arch/riscv/lib/udivdi3.S [deleted file]
arch/s390/boot/Makefile
arch/s390/boot/boot.h
arch/s390/boot/head.S
arch/s390/boot/ipl_parm.c
arch/s390/boot/kaslr.c
arch/s390/boot/version.c [new file with mode: 0644]
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/hypfs/hypfs_vm.c
arch/s390/include/asm/bitops.h
arch/s390/include/asm/page.h
arch/s390/include/asm/qdio.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/unistd.h
arch/s390/include/uapi/asm/bpf_perf_event.h
arch/s390/include/uapi/asm/ipl.h
arch/s390/include/uapi/asm/zcrypt.h
arch/s390/kernel/dumpstack.c
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/machine_kexec_reloc.c
arch/s390/kernel/perf_cpum_cf_diag.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls/syscall.tbl
arch/s390/kernel/vdso.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/lib/xor.c
arch/s390/mm/dump_pagetables.c
arch/s390/mm/fault.c
arch/s390/mm/gmap.c
arch/s390/mm/pgalloc.c
arch/s390/net/bpf_jit_comp.c
arch/s390/scripts/Makefile.chkbss
arch/sh/include/uapi/asm/setup.h
arch/sh/include/uapi/asm/types.h
arch/sh/kernel/disassemble.c
arch/sh/kernel/hw_breakpoint.c
arch/sparc/include/uapi/asm/oradax.h
arch/sparc/kernel/sys_sparc_64.c
arch/um/include/shared/timer-internal.h
arch/um/kernel/process.c
arch/um/kernel/time.c
arch/x86/Makefile
arch/x86/boot/compressed/pgtable_64.c
arch/x86/boot/string.c
arch/x86/entry/calling.h
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/events/amd/ibs.c
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/intel/ds.c
arch/x86/hyperv/mmu.c
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/ftrace.h
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/vdso/gettimeofday.h
arch/x86/include/uapi/asm/byteorder.h
arch/x86/include/uapi/asm/hwcap2.h
arch/x86/include/uapi/asm/sigcontext32.h
arch/x86/include/uapi/asm/types.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/bigsmp_32.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/probe_32.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/mtrr/cyrix.c
arch/x86/kernel/cpu/umwait.c
arch/x86/kernel/head_64.S
arch/x86/kernel/hpet.c
arch/x86/kernel/kvm.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/stacktrace.c
arch/x86/kernel/sysfb_efi.c
arch/x86/kernel/uprobes.c
arch/x86/kvm/debugfs.c
arch/x86/kvm/hyperv.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/cpu.c
arch/x86/math-emu/errors.c
arch/x86/math-emu/fpu_trig.c
arch/x86/mm/fault.c
arch/x86/mm/pageattr.c
arch/x86/net/bpf_jit_comp.c
arch/x86/power/cpu.c
arch/x86/purgatory/Makefile
arch/x86/purgatory/purgatory.c
arch/x86/purgatory/string.c [deleted file]
arch/xtensa/kernel/coprocessor.S
arch/xtensa/kernel/setup.c
block/bfq-iosched.c
block/blk-cgroup.c
block/blk-iolatency.c
block/blk-mq-sched.h
block/blk-mq.c
block/blk-rq-qos.c
block/blk-settings.c
block/blk-sysfs.c
block/genhd.c
drivers/acpi/arm64/iort.c
drivers/acpi/device_pm.c
drivers/acpi/nfit/core.c
drivers/acpi/nfit/nfit.h
drivers/acpi/scan.c
drivers/android/binder.c
drivers/ata/libahci_platform.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/libata-zpodd.c
drivers/ata/pata_rb532_cf.c
drivers/atm/Kconfig
drivers/atm/iphase.c
drivers/auxdisplay/Kconfig
drivers/auxdisplay/charlcd.c
drivers/auxdisplay/charlcd.h [new file with mode: 0644]
drivers/auxdisplay/hd44780.c
drivers/auxdisplay/ht16k33.c
drivers/auxdisplay/panel.c
drivers/base/core.c
drivers/base/firmware_loader/firmware.h
drivers/base/platform.c
drivers/base/regmap/Kconfig
drivers/block/aoe/aoedev.c
drivers/block/ataflop.c
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_receiver.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/rbd.c
drivers/block/xen-blkback/xenbus.c
drivers/bluetooth/bpa10x.c
drivers/bluetooth/btqca.c
drivers/bluetooth/btqca.h
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_ath.c
drivers/bluetooth/hci_bcm.c
drivers/bluetooth/hci_intel.c
drivers/bluetooth/hci_ldisc.c
drivers/bluetooth/hci_mrvl.c
drivers/bluetooth/hci_qca.c
drivers/bluetooth/hci_uart.h
drivers/bus/hisi_lpc.c
drivers/bus/ti-sysc.c
drivers/char/hpet.c
drivers/char/ipmi/ipmb_dev_int.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm1-cmd.c
drivers/char/tpm/tpm2-cmd.c
drivers/clk/at91/clk-generated.c
drivers/clk/clk.c
drivers/clk/mediatek/clk-mt8183.c
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/samsung/clk-exynos5-subcmu.c
drivers/clk/samsung/clk-exynos5-subcmu.h
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/socfpga/clk-periph-s10.c
drivers/clk/sprd/Kconfig
drivers/clocksource/timer-riscv.c
drivers/connector/connector.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/pasemi-cpufreq.c
drivers/crypto/ccp/ccp-crypto-aes-galois.c
drivers/crypto/ccp/ccp-dev.c
drivers/crypto/ccp/ccp-ops.c
drivers/crypto/ux500/cryp/cryp.c
drivers/dma/dw-edma/dw-edma-core.h
drivers/dma/dw-edma/dw-edma-pcie.c
drivers/dma/dw-edma/dw-edma-v0-core.c
drivers/dma/dw-edma/dw-edma-v0-debugfs.c
drivers/dma/fsldma.c
drivers/dma/sh/rcar-dmac.c
drivers/dma/sprd-dma.c
drivers/dma/ste_dma40.c
drivers/dma/stm32-mdma.c
drivers/dma/tegra210-adma.c
drivers/dma/ti/dma-crossbar.c
drivers/dma/ti/omap-dma.c
drivers/firewire/core-device.c
drivers/firewire/core-iso.c
drivers/firewire/core-topology.c
drivers/firmware/Kconfig
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/iscsi_ibft.c
drivers/fpga/Kconfig
drivers/fpga/altera-ps-spi.c
drivers/fsi/fsi-scom.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dce120/dce120_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c
drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
drivers/gpu/drm/amd/display/include/dpcd_defs.h
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/navi10_ppt.h
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/amd/powerplay/vega20_ppt.c
drivers/gpu/drm/arm/display/komeda/komeda_dev.c
drivers/gpu/drm/arm/display/komeda/komeda_format_caps.c
drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h
drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/ast/ast_post.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/drm_client.c
drivers/gpu/drm/drm_client_modeset.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_scaler.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/intel_bios.c
drivers/gpu/drm/i915/display/intel_bw.c
drivers/gpu/drm/i915/display/intel_cdclk.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/intel_vbt_defs.h
drivers/gpu/drm/i915/display/intel_vdsc.c
drivers/gpu/drm/i915/display/vlv_dsi_pll.c
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gem/i915_gem_mman.c
drivers/gpu/drm/i915/gem/i915_gem_pages.c
drivers/gpu/drm/i915/gem/i915_gem_pm.c
drivers/gpu/drm/i915/gt/intel_context.c
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_engine_pm.c
drivers/gpu/drm/i915/gt/intel_engine_pm.h
drivers/gpu/drm/i915/gt/intel_engine_types.h
drivers/gpu/drm/i915/gt/intel_gt_pm.c
drivers/gpu/drm/i915/gt/intel_gt_pm.h
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_reset.c
drivers/gpu/drm/i915/gt/intel_ringbuffer.c
drivers/gpu/drm/i915/gt/intel_workarounds.c
drivers/gpu/drm/i915/gt/mock_engine.c
drivers/gpu/drm/i915/gt/selftest_reset.c
drivers/gpu/drm/i915/gt/selftest_workarounds.c
drivers/gpu/drm/i915/gvt/cmd_parser.c
drivers/gpu/drm/i915/gvt/fb_decoder.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/trace_points.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/i915_vgpu.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/i915/intel_wakeref.h
drivers/gpu/drm/ingenic/ingenic-drm.c
drivers/gpu/drm/lima/lima_gem.c
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/mediatek/mtk_drm_drv.h
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c
drivers/gpu/drm/omapdrm/dss/output.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/qxl/qxl_drv.c
drivers/gpu/drm/rcar-du/rcar_lvds.c
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
drivers/gpu/drm/scheduler/sched_entity.c
drivers/gpu/drm/selftests/drm_cmdline_selftests.h
drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
drivers/gpu/drm/virtio/virtgpu_object.c
drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
drivers/hid/hid-a4tech.c
drivers/hid/hid-cp2112.c
drivers/hid/hid-holtek-kbd.c
drivers/hid/hid-ids.h
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-quirks.c
drivers/hid/hid-sony.c
drivers/hid/hid-tmff.c
drivers/hid/intel-ish-hid/ipc/hw-ish.h
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/usbhid/hiddev.c
drivers/hid/wacom_wac.c
drivers/hv/channel.c
drivers/hv/hv_trace.h
drivers/hv/hyperv_vmbus.h
drivers/hwmon/lm75.c
drivers/hwmon/nct6775.c
drivers/hwmon/nct7802.c
drivers/hwmon/occ/common.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/hwtracing/intel_th/msu.h
drivers/hwtracing/intel_th/pci.c
drivers/hwtracing/intel_th/pti.h
drivers/hwtracing/stm/core.c
drivers/i2c/busses/i2c-at91-core.c
drivers/i2c/busses/i2c-at91-master.c
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/busses/i2c-designware-slave.c
drivers/i2c/busses/i2c-emev2.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-nvidia-gpu.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-stm32.h
drivers/i2c/i2c-core-base.c
drivers/iio/accel/cros_ec_accel_legacy.c
drivers/iio/adc/ingenic-adc.c
drivers/iio/adc/max9611.c
drivers/iio/adc/rcar-gyroadc.c
drivers/iio/frequency/adf4371.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/counters.c
drivers/infiniband/core/device.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/restrack.c
drivers/infiniband/core/umem.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
drivers/infiniband/hw/bnxt_re/qplib_res.c
drivers/infiniband/hw/bnxt_re/qplib_res.h
drivers/infiniband/hw/bnxt_re/qplib_sp.c
drivers/infiniband/hw/bnxt_re/qplib_sp.h
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/fault.c
drivers/infiniband/hw/hfi1/rc.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/hfi1/verbs.c
drivers/infiniband/hw/hns/Kconfig
drivers/infiniband/hw/hns/Makefile
drivers/infiniband/hw/hns/hns_roce_db.c
drivers/infiniband/hw/hns/hns_roce_hw_v1.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx5/devx.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mem.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/qedr/main.c
drivers/infiniband/sw/siw/Kconfig
drivers/infiniband/sw/siw/siw.h
drivers/infiniband/sw/siw/siw_cm.c
drivers/infiniband/sw/siw/siw_cq.c
drivers/infiniband/sw/siw/siw_main.c
drivers/infiniband/sw/siw/siw_mem.c
drivers/infiniband/sw/siw/siw_mem.h
drivers/infiniband/sw/siw/siw_qp.c
drivers/infiniband/sw/siw/siw_qp_rx.c
drivers/infiniband/sw/siw/siw_qp_tx.c
drivers/infiniband/sw/siw/siw_verbs.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/applespi.c
drivers/input/mouse/elantech.c
drivers/input/mouse/synaptics.c
drivers/input/serio/hyperv-keyboard.c
drivers/input/tablet/kbtab.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/arm-smmu-v3.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu-debugfs.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
drivers/iommu/iova.c
drivers/iommu/virtio-iommu.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-imx-gpcv2.c
drivers/irqchip/irq-mbigen.c
drivers/isdn/capi/capi.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/macintosh/smu.c
drivers/md/bcache/super.c
drivers/md/bcache/sysfs.c
drivers/md/dm-bufio.c
drivers/md/dm-dust.c
drivers/md/dm-integrity.c
drivers/md/dm-kcopyd.c
drivers/md/dm-raid.c
drivers/md/dm-table.c
drivers/md/dm-zoned-metadata.c
drivers/md/dm-zoned-reclaim.c
drivers/md/dm-zoned-target.c
drivers/md/dm-zoned.h
drivers/md/persistent-data/dm-btree.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/media/platform/omap/omap_vout_vrfb.c
drivers/media/platform/vivid/vivid-core.c
drivers/media/v4l2-core/v4l2-subdev.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/omap-usb-host.c
drivers/mfd/rk808.c
drivers/misc/Kconfig
drivers/misc/eeprom/Kconfig
drivers/misc/eeprom/at24.c
drivers/misc/habanalabs/command_submission.c
drivers/misc/habanalabs/device.c
drivers/misc/habanalabs/firmware_if.c
drivers/misc/habanalabs/goya/goya.c
drivers/misc/habanalabs/goya/goyaP.h
drivers/misc/habanalabs/habanalabs.h
drivers/misc/habanalabs/hw_queue.c
drivers/misc/habanalabs/include/goya/goya_packets.h
drivers/misc/habanalabs/irq.c
drivers/misc/habanalabs/memory.c
drivers/misc/lkdtm/bugs.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/vmw_balloon.c
drivers/misc/vmw_vmci/vmci_doorbell.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/queue.c
drivers/mmc/core/sd.c
drivers/mmc/host/bcm2835.c
drivers/mmc/host/cavium.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/meson-mx-sdio.c
drivers/mmc/host/renesas_sdhi_core.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sdhci-cadence.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-of-at91.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci-pci-o2micro.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci-sprd.c
drivers/mmc/host/sdhci-tegra.c
drivers/mmc/host/sdhci-xenon.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/tmio_mmc.c
drivers/mmc/host/tmio_mmc.h
drivers/mmc/host/tmio_mmc_core.c
drivers/mmc/host/uniphier-sd.c
drivers/mtd/hyperbus/Kconfig
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/nand/onenand/onenand_base.c
drivers/mtd/nand/raw/nand_micron.c
drivers/mtd/spi-nor/spi-nor.c
drivers/net/arcnet/arc-rimi.c
drivers/net/arcnet/com20020-isa.c
drivers/net/arcnet/com90io.c
drivers/net/arcnet/com90xx.c
drivers/net/bonding/bond_main.c
drivers/net/can/at91_can.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/peak_canfd/peak_pciefd_main.c
drivers/net/can/rcar/rcar_canfd.c
drivers/net/can/sja1000/peak_pcmcia.c
drivers/net/can/spi/mcp251x.c
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_fd.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/microchip/ksz9477_spi.c
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/qca8k.c
drivers/net/dsa/sja1105/sja1105_dynamic_config.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/dsa/sja1105/sja1105_ptp.c
drivers/net/ethernet/8390/Kconfig
drivers/net/ethernet/agere/et131x.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/amd/Kconfig
drivers/net/ethernet/amd/xgbe/xgbe-main.c
drivers/net/ethernet/apple/Kconfig
drivers/net/ethernet/aquantia/atlantic/aq_filters.c
drivers/net/ethernet/aquantia/atlantic/aq_main.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_vec.c
drivers/net/ethernet/atheros/ag71xx.c
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/common/cavium_ptp.c
drivers/net/ethernet/cavium/liquidio/request_manager.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/chelsio/cxgb/my3126.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/ezchip/nps_enet.h
drivers/net/ethernet/freescale/enetc/Kconfig
drivers/net/ethernet/freescale/enetc/enetc_ptp.c
drivers/net/ethernet/freescale/fman/fman.c
drivers/net/ethernet/google/gve/gve.h
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/google/gve/gve_main.c
drivers/net/ethernet/google/gve/gve_rx.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mediatek/Kconfig
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx5/core/dev.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/params.h
drivers/net/ethernet/mellanox/mlx5/core/en/port.c
drivers/net/ethernet/mellanox/mlx5/core/en/port.h
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_ace.c
drivers/net/ethernet/mscc/ocelot_flower.c
drivers/net/ethernet/mscc/ocelot_tc.c
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/natsemi/sonic.c
drivers/net/ethernet/netronome/nfp/bpf/jit.c
drivers/net/ethernet/netronome/nfp/flower/cmsg.c
drivers/net/ethernet/netronome/nfp/flower/offload.c
drivers/net/ethernet/netronome/nfp/flower/qos_conf.c
drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/ni/Kconfig
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/packetengines/Kconfig
drivers/net/ethernet/packetengines/Makefile
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_rdma.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/samsung/Kconfig
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/toshiba/spider_net.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/tundra/tsi108_eth.c
drivers/net/ethernet/xscale/Kconfig
drivers/net/hamradio/6pack.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ieee802154/mac802154_hwsim.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/fib.c
drivers/net/netdevsim/netdev.c
drivers/net/netdevsim/netdevsim.h
drivers/net/phy/at803x.c
drivers/net/phy/fixed_phy.c
drivers/net/phy/mscc.c
drivers/net/phy/phy-c45.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/phy_led_triggers.c
drivers/net/phy/phylink.c
drivers/net/phy/sfp.c
drivers/net/ppp/pppoe.c
drivers/net/ppp/pppox.c
drivers/net/ppp/pptp.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cx82310_eth.c
drivers/net/usb/kalmia.c
drivers/net/usb/lan78xx.c
drivers/net/usb/pegasus.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/virtio_net.c
drivers/net/vrf.c
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/sdla.c
drivers/net/wimax/i2400m/fw.c
drivers/net/wimax/i2400m/op-rfkill.c
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
drivers/net/wireless/intel/iwlwifi/cfg/22000.c
drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/iwl-config.h
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.h
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/marvell/mwifiex/ie.c
drivers/net/wireless/marvell/mwifiex/main.h
drivers/net/wireless/marvell/mwifiex/scan.c
drivers/net/wireless/marvell/mwifiex/uap_cmd.c
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
drivers/net/wireless/ralink/rt2x00/rt2800lib.c
drivers/net/wireless/ralink/rt2x00/rt2x00.h
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
drivers/net/wireless/rsi/rsi_91x_usb.c
drivers/net/wireless/ti/wlcore/vendor_cmd.c
drivers/net/xen-netback/netback.c
drivers/nfc/nfcmrvl/main.c
drivers/nfc/nfcmrvl/uart.c
drivers/nfc/nfcmrvl/usb.c
drivers/nfc/st-nci/se.c
drivers/nfc/st21nfca/se.c
drivers/nfc/st95hf/core.c
drivers/ntb/msi.c
drivers/nvdimm/btt_devs.c
drivers/nvdimm/bus.c
drivers/nvdimm/core.c
drivers/nvdimm/dimm_devs.c
drivers/nvdimm/namespace_devs.c
drivers/nvdimm/nd-core.h
drivers/nvdimm/pfn_devs.c
drivers/nvdimm/pmem.c
drivers/nvdimm/region.c
drivers/nvdimm/region_devs.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/target/configfs.c
drivers/nvme/target/core.c
drivers/nvme/target/loop.c
drivers/nvme/target/nvmet.h
drivers/nvmem/nvmem-sysfs.c
drivers/of/irq.c
drivers/of/resolver.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/quirks.c
drivers/pcmcia/db1xxx_ss.c
drivers/perf/arm_pmu.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
drivers/pinctrl/aspeed/pinctrl-aspeed.c
drivers/pinctrl/aspeed/pinmux-aspeed.c
drivers/pinctrl/aspeed/pinmux-aspeed.h
drivers/platform/chrome/cros_ec_ishtp.c
drivers/platform/olpc/olpc-xo175-ec.c
drivers/platform/x86/intel_pmc_core.c
drivers/platform/x86/pcengines-apuv2.c
drivers/power/supply/ab8500_charger.c
drivers/powercap/intel_rapl_common.c
drivers/powercap/powercap_sys.c
drivers/pwm/core.c
drivers/regulator/act8945a-regulator.c
drivers/regulator/axp20x-regulator.c
drivers/regulator/lp87565-regulator.c
drivers/regulator/of_regulator.c
drivers/regulator/slg51000-regulator.c
drivers/regulator/twl-regulator.c
drivers/s390/block/dasd_alias.c
drivers/s390/char/con3215.c
drivers/s390/char/tape_core.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/vfio_ccw_async.c
drivers/s390/cio/vfio_ccw_cp.c
drivers/s390/cio/vfio_ccw_drv.c
drivers/s390/crypto/ap_queue.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/net/ctcm_fsms.c
drivers/s390/net/ctcm_mpc.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/Kconfig
drivers/scsi/arm/fas216.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/fcoe/fcoe_ctlr.c
drivers/scsi/hpsa.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_lib.c
drivers/scsi/ufs/ufshcd.c
drivers/soc/fsl/qe/qe.c
drivers/soc/ixp4xx/Kconfig
drivers/soc/qcom/qcom-geni-se.c
drivers/soc/ti/pm33xx.c
drivers/soundwire/Kconfig
drivers/soundwire/Makefile
drivers/soundwire/cadence_master.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-fsl-qspi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-pxa2xx.c
drivers/staging/android/ion/ion_page_pool.c
drivers/staging/comedi/drivers/dt3000.c
drivers/staging/fbtft/fb_bd663474.c
drivers/staging/fbtft/fb_ili9163.c
drivers/staging/fbtft/fb_ili9325.c
drivers/staging/fbtft/fb_s6d1121.c
drivers/staging/fbtft/fb_ssd1289.c
drivers/staging/fbtft/fb_ssd1331.c
drivers/staging/fbtft/fb_upd161704.c
drivers/staging/fbtft/fbtft-bus.c
drivers/staging/fbtft/fbtft-core.c
drivers/staging/gasket/apex_driver.c
drivers/staging/unisys/visornic/visornic_main.c
drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
drivers/target/iscsi/cxgbit/cxgbit_cm.c
drivers/target/iscsi/cxgbit/cxgbit_main.c
drivers/target/target_core_user.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
drivers/tty/hvc/hvcs.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/kgdboc.c
drivers/tty/serial/netx-serial.c [deleted file]
drivers/tty/tty_ldsem.c
drivers/tty/vt/vt.c
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/class/usbtmc.c
drivers/usb/core/buffer.c
drivers/usb/core/devio.c
drivers/usb/core/file.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/message.c
drivers/usb/core/sysfs.c
drivers/usb/core/usb.h
drivers/usb/dwc2/hcd.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/udc/lpc32xx_udc.c
drivers/usb/gadget/udc/renesas_usb3.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/fotg210-hcd.c
drivers/usb/host/hwa-hc.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/pci-quirks.h
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-rcar.c
drivers/usb/host/xhci-tegra.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/iowarrior.c
drivers/usb/misc/rio500.c
drivers/usb/misc/usb251xb.c
drivers/usb/misc/yurex.c
drivers/usb/serial/option.c
drivers/usb/storage/realtek_cr.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi_ccg.c
drivers/vhost/test.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/fbdev/acornfb.c
drivers/video/fbdev/omap/omapfb_main.c
drivers/virtio/virtio_ring.c
drivers/watchdog/ar7_wdt.c
drivers/watchdog/pcwd.c
drivers/watchdog/riowd.c
drivers/watchdog/sb_wdog.c
drivers/watchdog/scx200_wdt.c
drivers/watchdog/wdt.c
drivers/watchdog/wdt285.c
drivers/watchdog/wdt977.c
drivers/xen/gntdev.c
drivers/xen/privcmd.c
drivers/xen/swiotlb-xen.c
drivers/xen/xen-pciback/conf_space_capability.c
drivers/xen/xlate_mmu.c
fs/afs/cell.c
fs/afs/cmservice.c
fs/afs/dir.c
fs/afs/file.c
fs/afs/fsclient.c
fs/afs/vlclient.c
fs/afs/yfsclient.c
fs/block_dev.c
fs/btrfs/Kconfig
fs/btrfs/backref.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/locking.c
fs/btrfs/ordered-data.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/locks.c
fs/ceph/snap.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/cifsfs.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/misc.c
fs/cifs/sess.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/compat_ioctl.c
fs/configfs/configfs_internal.h
fs/configfs/dir.c
fs/configfs/file.c
fs/coredump.c
fs/dax.c
fs/exec.c
fs/ext4/inode.c
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/super.c
fs/gfs2/bmap.c
fs/io_uring.c
fs/iomap/Makefile
fs/namespace.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/fscache.c
fs/nfs/fscache.h
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4file.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs_nfs.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfscache.c
fs/nfsd/nfsctl.c
fs/ocfs2/xattr.c
fs/open.c
fs/read_write.c
fs/seq_file.c
fs/super.c
fs/ubifs/budget.c
fs/ubifs/orphan.c
fs/ubifs/super.c
fs/userfaultfd.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_da_btree.c
fs/xfs/libxfs/xfs_dir2_node.c
fs/xfs/scrub/dabtree.c
fs/xfs/xfs_ioctl32.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_log.c
fs/xfs/xfs_pnfs.c
fs/xfs/xfs_reflink.c
include/asm-generic/5level-fixup.h
include/asm-generic/futex.h
include/asm-generic/getorder.h
include/drm/drm_client.h
include/drm/drm_mode_config.h
include/kvm/arm_pmu.h
include/kvm/arm_vgic.h
include/linux/blk-cgroup.h
include/linux/ccp.h
include/linux/ceph/buffer.h
include/linux/clk.h
include/linux/compiler.h
include/linux/connector.h
include/linux/cred.h
include/linux/device.h
include/linux/dim.h
include/linux/dma-contiguous.h
include/linux/dma-mapping.h
include/linux/dma-noncoherent.h
include/linux/elevator.h
include/linux/filter.h
include/linux/fs.h
include/linux/gfp.h
include/linux/gpio.h
include/linux/gpio/consumer.h
include/linux/hmm.h
include/linux/if_pppox.h
include/linux/if_rmnet.h
include/linux/input/elan-i2c-ids.h
include/linux/intel-iommu.h
include/linux/iova.h
include/linux/key.h
include/linux/kvm_host.h
include/linux/logic_pio.h
include/linux/memcontrol.h
include/linux/mempolicy.h
include/linux/mlx5/device.h
include/linux/mlx5/fs.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm_types.h
include/linux/mmzone.h
include/linux/mod_devicetable.h
include/linux/netfilter/nf_conntrack_h323_asn1.h
include/linux/netfilter/nf_conntrack_h323_types.h
include/linux/of.h
include/linux/page-flags-layout.h
include/linux/page-flags.h
include/linux/pci.h
include/linux/phy.h
include/linux/phy_fixed.h
include/linux/sched.h
include/linux/sched/numa_balancing.h
include/linux/signal.h
include/linux/skbuff.h
include/linux/skmsg.h
include/linux/socket.h
include/linux/sunrpc/sched.h
include/linux/syscalls.h
include/linux/timekeeper_internal.h
include/linux/trace_events.h
include/linux/usb.h
include/linux/usb/hcd.h
include/linux/wait.h
include/math-emu/op-common.h
include/misc/charlcd.h [deleted file]
include/net/act_api.h
include/net/addrconf.h
include/net/bluetooth/hci_core.h
include/net/cfg80211.h
include/net/flow_offload.h
include/net/inet_frag.h
include/net/ip_fib.h
include/net/net_namespace.h
include/net/netfilter/nf_conntrack_expect.h
include/net/netfilter/nf_conntrack_synproxy.h
include/net/netfilter/nf_tables.h
include/net/netfilter/nf_tables_offload.h
include/net/netlink.h
include/net/nexthop.h
include/net/pkt_cls.h
include/net/psample.h
include/net/route.h
include/net/sch_generic.h
include/net/sock.h
include/net/tc_act/tc_police.h
include/net/tc_act/tc_sample.h
include/net/tcp.h
include/net/tls.h
include/net/xfrm.h
include/rdma/ib_verbs.h
include/rdma/rdmavt_qp.h
include/rdma/restrack.h
include/scsi/libfc.h
include/scsi/libfcoe.h
include/soc/arc/mcip.h
include/soc/fsl/qe/qe.h
include/sound/compress_driver.h
include/sound/simple_card_utils.h
include/sound/sof/control.h
include/sound/sof/dai-intel.h
include/sound/sof/dai.h
include/sound/sof/header.h
include/sound/sof/info.h
include/sound/sof/pm.h
include/sound/sof/stream.h
include/sound/sof/topology.h
include/sound/sof/trace.h
include/sound/sof/xtensa.h
include/trace/events/dma_fence.h
include/trace/events/napi.h
include/trace/events/qdisc.h
include/trace/events/rxrpc.h
include/trace/events/tegra_apb_dma.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/bpf.h
include/uapi/linux/bpfilter.h
include/uapi/linux/ipmi_bmc.h
include/uapi/linux/isdn/capicmd.h
include/uapi/linux/isst_if.h
include/uapi/linux/jffs2.h
include/uapi/linux/kfd_ioctl.h
include/uapi/linux/kvm.h
include/uapi/linux/netfilter/nf_synproxy.h
include/uapi/linux/netfilter/xt_connlabel.h
include/uapi/linux/netfilter/xt_nfacct.h
include/uapi/linux/nl80211.h
include/uapi/linux/psp-sev.h
include/uapi/linux/rds.h
include/uapi/linux/rxrpc.h
include/uapi/linux/serial_core.h
include/uapi/linux/socket.h
include/uapi/linux/usb/g_uvc.h
include/uapi/linux/vbox_vmmdev_types.h
include/uapi/linux/vboxguest.h
include/uapi/linux/videodev2.h
include/uapi/linux/virtio_iommu.h
include/uapi/linux/virtio_pmem.h
include/uapi/linux/vmcore.h
include/uapi/linux/wmi.h
include/uapi/misc/fastrpc.h
include/uapi/rdma/rvt-abi.h
include/uapi/rdma/siw-abi.h
include/uapi/scsi/scsi_bsg_ufs.h
include/uapi/sound/skl-tplg-interface.h
include/uapi/sound/sof/fw.h
include/uapi/sound/sof/header.h
include/xen/xen-ops.h
ipc/util.h
kernel/Kconfig.preempt
kernel/Makefile
kernel/bpf/core.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/configs.c
kernel/cred.c
kernel/dma/contiguous.c
kernel/dma/direct.c
kernel/dma/mapping.c
kernel/dma/remap.c
kernel/events/core.c
kernel/events/hw_breakpoint.c
kernel/exit.c
kernel/fork.c
kernel/irq/affinity.c
kernel/irq/irqdesc.c
kernel/irq/resend.c
kernel/kallsyms.c
kernel/kprobes.c
kernel/locking/lockdep.c
kernel/locking/lockdep_proc.c
kernel/locking/mutex.c
kernel/locking/rwsem.c
kernel/memremap.c [deleted file]
kernel/module.c
kernel/sched/core.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/deadline.c
kernel/sched/fair.c
kernel/sched/psi.c
kernel/signal.c
kernel/time/timekeeping.c
kernel/time/vsyscall.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/trace/trace_functions_graph.c
kernel/trace/trace_probe.c
lib/Kconfig
lib/Kconfig.kasan
lib/Makefile
lib/dim/dim.c
lib/dim/net_dim.c
lib/kfifo.c
lib/logic_pio.c
lib/raid6/Makefile
lib/test_firmware.c
lib/test_meminit.c
lib/vdso/gettimeofday.c
mm/Makefile
mm/balloon_compaction.c
mm/compaction.c
mm/hmm.c
mm/huge_memory.c
mm/hugetlb.c
mm/kasan/common.c
mm/kmemleak.c
mm/memcontrol.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/memremap.c [new file with mode: 0644]
mm/migrate.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/slub.c
mm/usercopy.c
mm/vmalloc.c
mm/vmscan.c
mm/workingset.c
mm/z3fold.c
mm/zsmalloc.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bat_v_ogm.c
net/batman-adv/multicast.c
net/batman-adv/netlink.c
net/bluetooth/hci_core.c
net/bluetooth/hci_debugfs.c
net/bluetooth/hci_event.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/bridge/br.c
net/bridge/br_mdb.c
net/bridge/br_multicast.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_private.h
net/bridge/br_vlan.c
net/bridge/netfilter/Kconfig
net/bridge/netfilter/ebtables.c
net/bridge/netfilter/nft_meta_bridge.c
net/can/gw.c
net/ceph/crypto.c
net/ceph/osd_client.c
net/core/dev.c
net/core/filter.c
net/core/flow_dissector.c
net/core/flow_offload.c
net/core/netpoll.c
net/core/skbuff.c
net/core/skmsg.c
net/core/sock.c
net/core/sock_diag.c
net/core/sock_map.c
net/core/stream.c
net/dsa/slave.c
net/dsa/switch.c
net/dsa/tag_8021q.c
net/dsa/tag_sja1105.c
net/ieee802154/6lowpan/reassembly.c
net/ieee802154/socket.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/inet_fragment.c
net/ipv4/ip_fragment.c
net/ipv4/ipip.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv4/netfilter/ipt_rpfilter.c
net/ipv4/netfilter/nf_nat_h323.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/tcp_ulp.c
net/ipv6/addrconf.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/mcast.c
net/ipv6/netfilter/ip6t_SYNPROXY.c
net/ipv6/netfilter/ip6t_rpfilter.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/ping.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/iucv/af_iucv.c
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/driver-ops.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/util.c
net/mpls/mpls_iptunnel.c
net/ncsi/ncsi-cmd.c
net/ncsi/ncsi-rsp.c
net/netfilter/Kconfig
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_ipmac.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/nf_conntrack_amanda.c
net/netfilter/nf_conntrack_broadcast.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_expect.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_h323_asn1.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/nf_conntrack_irc.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_pptp.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_conntrack_proto_icmp.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_sane.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_conntrack_tftp.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_ip.c
net/netfilter/nf_nat_amanda.c
net/netfilter/nf_nat_core.c
net/netfilter/nf_nat_ftp.c
net/netfilter/nf_nat_irc.c
net/netfilter/nf_nat_sip.c
net/netfilter/nf_nat_tftp.c
net/netfilter/nf_synproxy_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_offload.c
net/netfilter/nfnetlink.c
net/netfilter/nft_chain_filter.c
net/netfilter/nft_chain_nat.c
net/netfilter/nft_ct.c
net/netfilter/nft_fib_netdev.c
net/netfilter/nft_flow_offload.c
net/netfilter/nft_hash.c
net/netfilter/nft_meta.c
net/netfilter/nft_redir.c
net/netfilter/nft_socket.c
net/netfilter/nft_synproxy.c
net/netfilter/xt_nfacct.c
net/netfilter/xt_physdev.c
net/netrom/af_netrom.c
net/openvswitch/conntrack.c
net/openvswitch/datapath.c
net/openvswitch/flow.c
net/openvswitch/flow.h
net/openvswitch/flow_table.c
net/packet/af_packet.c
net/psample/psample.c
net/qrtr/tun.c
net/rds/bind.c
net/rds/ib.c
net/rds/ib.h
net/rds/ib_cm.c
net/rds/rdma_transport.c
net/rds/recv.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_event.c
net/rxrpc/call_object.c
net/rxrpc/conn_client.c
net/rxrpc/conn_event.c
net/rxrpc/conn_object.c
net/rxrpc/input.c
net/rxrpc/local_event.c
net/rxrpc/local_object.c
net/rxrpc/output.c
net/rxrpc/peer_event.c
net/rxrpc/peer_object.c
net/rxrpc/protocol.h
net/rxrpc/recvmsg.c
net/rxrpc/rxkad.c
net/rxrpc/sendmsg.c
net/rxrpc/skbuff.c
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_ct.c
net/sched/act_ctinfo.c
net/sched/act_gact.c
net/sched/act_ife.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_mpls.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_sample.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/act_tunnel_key.c
net/sched/act_vlan.c
net/sched/cls_api.c
net/sched/cls_bpf.c
net/sched/cls_flower.c
net/sched/cls_matchall.c
net/sched/cls_u32.c
net/sched/sch_api.c
net/sched/sch_cbs.c
net/sched/sch_codel.c
net/sched/sch_generic.c
net/sched/sch_hhf.c
net/sched/sch_taprio.c
net/sctp/protocol.c
net/sctp/sm_sideeffect.c
net/sctp/socket.c
net/sctp/stream.c
net/smc/af_smc.c
net/smc/smc_tx.c
net/sunrpc/clnt.c
net/sunrpc/xprt.c
net/tipc/addr.c
net/tipc/link.c
net/tipc/msg.h
net/tipc/name_distr.c
net/tipc/netlink_compat.c
net/tipc/socket.c
net/tipc/topsrv.c
net/tls/tls_device.c
net/tls/tls_main.c
net/tls/tls_sw.c
net/vmw_vsock/hyperv_transport.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/util.c
net/xdp/xdp_umem.c
net/xfrm/xfrm_interface.c
net/xfrm/xfrm_policy.c
samples/auxdisplay/cfag12864b-example.c
samples/vfio-mdev/mdpy-defs.h
scripts/Kbuild.include
scripts/Kconfig.include
scripts/Makefile.build
scripts/Makefile.lib
scripts/Makefile.modpost
scripts/coccinelle/api/atomic_as_refcounter.cocci
scripts/gen_compile_commands.py
scripts/headers_install.sh
scripts/kconfig/confdata.c
scripts/link-vmlinux.sh
scripts/sphinx-pre-install
security/Kconfig.hardening
security/keys/request_key.c
security/keys/request_key_auth.c
security/keys/trusted.c
security/selinux/ss/policydb.c
security/selinux/ss/sidtab.c
sound/ac97/bus.c
sound/core/compress_offload.c
sound/core/pcm_native.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_fifo.c
sound/core/seq/seq_fifo.h
sound/firewire/oxfw/oxfw-pcm.c
sound/firewire/packets-buffer.c
sound/hda/hdac_i915.c
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/codecs/cs42xx8.c
sound/soc/codecs/max98357a.c
sound/soc/codecs/max98373.c
sound/soc/codecs/max98373.h
sound/soc/codecs/pcm3060-i2c.c
sound/soc/codecs/pcm3060-spi.c
sound/soc/codecs/pcm3060.c
sound/soc/codecs/pcm3060.h
sound/soc/codecs/rt1011.c
sound/soc/codecs/rt1308.c [changed mode: 0755->0644]
sound/soc/codecs/rt1308.h [changed mode: 0755->0644]
sound/soc/generic/audio-graph-card.c
sound/soc/generic/simple-card-utils.c
sound/soc/generic/simple-card.c
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/common/soc-acpi-intel-bxt-match.c
sound/soc/intel/common/soc-acpi-intel-byt-match.c
sound/soc/intel/common/soc-acpi-intel-cht-match.c
sound/soc/intel/common/soc-acpi-intel-cnl-match.c
sound/soc/intel/common/soc-acpi-intel-glk-match.c
sound/soc/intel/common/soc-acpi-intel-hda-match.c
sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
sound/soc/intel/common/soc-acpi-intel-icl-match.c
sound/soc/intel/common/soc-acpi-intel-kbl-match.c
sound/soc/intel/common/soc-acpi-intel-skl-match.c
sound/soc/qcom/apq8016_sbc.c
sound/soc/rockchip/rockchip_i2s.c
sound/soc/rockchip/rockchip_max98090.c
sound/soc/samsung/odroid.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/sof/intel/cnl.c
sound/soc/sof/intel/hda-ipc.c
sound/soc/sunxi/sun4i-i2s.c
sound/soc/ti/davinci-mcasp.c
sound/sound_core.c
sound/usb/helper.c
sound/usb/hiface/pcm.c
sound/usb/line6/pcm.c
sound/usb/line6/podhd.c
sound/usb/line6/variax.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/stream.c
tools/arch/arm/include/uapi/asm/kvm.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/mman.h
tools/arch/sparc/include/uapi/asm/mman.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/vmx.h
tools/bpf/bpftool/common.c
tools/bpf/bpftool/prog.c
tools/hv/hv_get_dhcp_info.sh
tools/hv/hv_kvp_daemon.c
tools/hv/hv_set_ifconfig.sh
tools/hv/hv_vss_daemon.c
tools/hv/lsvmbus
tools/include/uapi/asm-generic/mman-common.h
tools/include/uapi/asm-generic/mman.h
tools/include/uapi/asm-generic/unistd.h
tools/include/uapi/drm/drm.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/bpf.h
tools/include/uapi/linux/if_link.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/sched.h
tools/include/uapi/linux/usbdevice_fs.h
tools/lib/bpf/btf.c
tools/lib/bpf/hashmap.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/xsk.c
tools/objtool/check.c
tools/objtool/check.h
tools/perf/Documentation/Makefile
tools/perf/Documentation/perf-script.txt
tools/perf/Documentation/perf.data-file-format.txt
tools/perf/arch/s390/util/machine.c
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/bench/numa.c
tools/perf/builtin-ftrace.c
tools/perf/builtin-probe.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/pmu-events/jevents.c
tools/perf/trace/beauty/usbdevfs_ioctl.sh
tools/perf/ui/browser.c
tools/perf/ui/tui/progress.c
tools/perf/util/annotate.c
tools/perf/util/cpumap.c
tools/perf/util/evsel.c
tools/perf/util/header.c
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/probe-event.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/stat-shadow.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/thread.c
tools/perf/util/zstd.c
tools/power/x86/turbostat/Makefile
tools/power/x86/turbostat/turbostat.c
tools/power/x86/x86_energy_perf_policy/Makefile
tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
tools/scripts/Makefile.include
tools/testing/ktest/config-bisect.pl
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/config
tools/testing/selftests/bpf/progs/sendmsg6_prog.c
tools/testing/selftests/bpf/test_btf_dump.c
tools/testing/selftests/bpf/test_cgroup_storage.c
tools/testing/selftests/bpf/test_sock.c
tools/testing/selftests/bpf/test_xdp_vlan.sh
tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh [new file with mode: 0755]
tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh [new file with mode: 0755]
tools/testing/selftests/bpf/verifier/ctx_skb.c
tools/testing/selftests/bpf/verifier/loops1.c
tools/testing/selftests/cgroup/cgroup_util.c
tools/testing/selftests/cgroup/test_freezer.c
tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh
tools/testing/selftests/kmod/kmod.sh
tools/testing/selftests/kselftest.h
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/config [new file with mode: 0644]
tools/testing/selftests/kvm/include/evmcs.h
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/lib/x86_64/vmx.c
tools/testing/selftests/kvm/x86_64/evmcs_test.c
tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
tools/testing/selftests/kvm/x86_64/platform_info_test.c
tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c
tools/testing/selftests/livepatch/functions.sh
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/fib_nexthops.sh
tools/testing/selftests/net/forwarding/gre_multipath.sh
tools/testing/selftests/net/tcp_fastopen_backup_key.sh
tools/testing/selftests/net/tls.c
tools/testing/selftests/net/xfrm_policy.sh
tools/testing/selftests/netfilter/nft_flowtable.sh
tools/testing/selftests/pidfd/pidfd_test.c
tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py
tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json
tools/testing/selftests/x86/test_vsyscall.c
usr/include/Makefile
virt/kvm/arm/arm.c
virt/kvm/arm/hyp/vgic-v3-sr.c
virt/kvm/arm/mmio.c
virt/kvm/arm/pmu.c
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-mmio-v3.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic.c
virt/kvm/arm/vgic/vgic.h
virt/kvm/kvm_main.c

index 2ffd69afc1a8280654a8763e044e27e08be7a69f..196ca317bd1f24ad57ad9ded549bc0b7994d8111 100644 (file)
@@ -107,10 +107,13 @@ ForEachMacros:
   - 'css_for_each_descendant_post'
   - 'css_for_each_descendant_pre'
   - 'device_for_each_child_node'
+  - 'dma_fence_chain_for_each'
   - 'drm_atomic_crtc_for_each_plane'
   - 'drm_atomic_crtc_state_for_each_plane'
   - 'drm_atomic_crtc_state_for_each_plane_state'
   - 'drm_atomic_for_each_plane_damage'
+  - 'drm_client_for_each_connector_iter'
+  - 'drm_client_for_each_modeset'
   - 'drm_connector_for_each_possible_encoder'
   - 'drm_for_each_connector_iter'
   - 'drm_for_each_crtc'
@@ -126,6 +129,7 @@ ForEachMacros:
   - 'drm_mm_for_each_node_in_range'
   - 'drm_mm_for_each_node_safe'
   - 'flow_action_for_each'
+  - 'for_each_active_dev_scope'
   - 'for_each_active_drhd_unit'
   - 'for_each_active_iommu'
   - 'for_each_available_child_of_node'
@@ -153,6 +157,8 @@ ForEachMacros:
   - 'for_each_cpu_not'
   - 'for_each_cpu_wrap'
   - 'for_each_dev_addr'
+  - 'for_each_dev_scope'
+  - 'for_each_displayid_db'
   - 'for_each_dma_cap_mask'
   - 'for_each_dpcm_be'
   - 'for_each_dpcm_be_rollback'
@@ -169,6 +175,8 @@ ForEachMacros:
   - 'for_each_evictable_lru'
   - 'for_each_fib6_node_rt_rcu'
   - 'for_each_fib6_walker_rt'
+  - 'for_each_free_mem_pfn_range_in_zone'
+  - 'for_each_free_mem_pfn_range_in_zone_from'
   - 'for_each_free_mem_range'
   - 'for_each_free_mem_range_reverse'
   - 'for_each_func_rsrc'
@@ -178,6 +186,7 @@ ForEachMacros:
   - 'for_each_ip_tunnel_rcu'
   - 'for_each_irq_nr'
   - 'for_each_link_codecs'
+  - 'for_each_link_platforms'
   - 'for_each_lru'
   - 'for_each_matching_node'
   - 'for_each_matching_node_and_match'
@@ -302,7 +311,10 @@ ForEachMacros:
   - 'ide_port_for_each_present_dev'
   - 'idr_for_each_entry'
   - 'idr_for_each_entry_continue'
+  - 'idr_for_each_entry_continue_ul'
   - 'idr_for_each_entry_ul'
+  - 'in_dev_for_each_ifa_rcu'
+  - 'in_dev_for_each_ifa_rtnl'
   - 'inet_bind_bucket_for_each'
   - 'inet_lhash2_for_each_icsk_rcu'
   - 'key_for_each'
@@ -343,8 +355,6 @@ ForEachMacros:
   - 'media_device_for_each_intf'
   - 'media_device_for_each_link'
   - 'media_device_for_each_pad'
-  - 'mp_bvec_for_each_page'
-  - 'mp_bvec_for_each_segment'
   - 'nanddev_io_for_each_page'
   - 'netdev_for_each_lower_dev'
   - 'netdev_for_each_lower_private'
@@ -381,18 +391,19 @@ ForEachMacros:
   - 'radix_tree_for_each_slot'
   - 'radix_tree_for_each_tagged'
   - 'rbtree_postorder_for_each_entry_safe'
+  - 'rdma_for_each_block'
   - 'rdma_for_each_port'
   - 'resource_list_for_each_entry'
   - 'resource_list_for_each_entry_safe'
   - 'rhl_for_each_entry_rcu'
   - 'rhl_for_each_rcu'
   - 'rht_for_each'
-  - 'rht_for_each_from'
   - 'rht_for_each_entry'
   - 'rht_for_each_entry_from'
   - 'rht_for_each_entry_rcu'
   - 'rht_for_each_entry_rcu_from'
   - 'rht_for_each_entry_safe'
+  - 'rht_for_each_from'
   - 'rht_for_each_rcu'
   - 'rht_for_each_rcu_from'
   - '__rq_for_each_bio'
index 8f5422cba6e2b0b687e7f16b2cc1adf1e5bf2cab..2030c7a4d2f8c4d5d3764990c7b4a7b6855bb10b 100644 (file)
@@ -142,3 +142,6 @@ x509.genkey
 
 # Kdevelop4
 *.kdev4
+
+# Clang's compilation database file
+/compile_commands.json
index 0fef932de3dba5e696e51dce43ffdd5283077639..afaad605284a8be6b9aa96f0157716fdf869453b 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -64,6 +64,9 @@ Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com>
 Dengcheng Zhu <dzhu@wavecomp.com> <dczhu@mips.com>
 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com>
 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
+Dmitry Safonov <0x7f454c46@gmail.com> <d.safonov@partner.samsung.com>
+Dmitry Safonov <0x7f454c46@gmail.com> <dima@arista.com>
 Domen Puncer <domen@coderock.org>
 Douglas Gilbert <dougg@torque.net>
 Ed L. Cashin <ecashin@coraid.com>
@@ -98,6 +101,7 @@ Jason Gunthorpe <jgg@ziepe.ca> <jgunthorpe@obsidianresearch.com>
 Javi Merino <javi.merino@kernel.org> <javi.merino@arm.com>
 <javier@osg.samsung.com> <javier.martinez@collabora.co.uk>
 Jean Tourrilhes <jt@hpl.hp.com>
+<jean-philippe@linaro.org> <jean-philippe.brucker@arm.com>
 Jeff Garzik <jgarzik@pretzel.yyz.us>
 Jeff Layton <jlayton@kernel.org> <jlayton@redhat.com>
 Jeff Layton <jlayton@kernel.org> <jlayton@poochiereds.net>
@@ -116,6 +120,7 @@ John Stultz <johnstul@us.ibm.com>
 Juha Yrjola <at solidboot.com>
 Juha Yrjola <juha.yrjola@nokia.com>
 Juha Yrjola <juha.yrjola@solidboot.com>
+Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
 Kay Sievers <kay.sievers@vrfy.org>
 Kenneth W Chen <kenneth.w.chen@intel.com>
 Konstantin Khlebnikov <koct9i@gmail.com> <k.khlebnikov@samsung.com>
@@ -132,6 +137,7 @@ Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
 Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
 Li Yang <leoyang.li@nxp.com> <leoli@freescale.com>
 Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
+Marc Zyngier <maz@kernel.org> <marc.zyngier@arm.com>
 Marcin Nowakowski <marcin.nowakowski@mips.com> <marcin.nowakowski@imgtec.com>
 Mark Brown <broonie@sirena.org.uk>
 Mark Yao <markyao0591@gmail.com> <mark.yao@rock-chips.com>
@@ -157,6 +163,8 @@ Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.co
 Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
 Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
 Matt Redfearn <matt.redfearn@mips.com> <matt.redfearn@imgtec.com>
+Maxime Ripard <mripard@kernel.org> <maxime.ripard@bootlin.com>
+Maxime Ripard <mripard@kernel.org> <maxime.ripard@free-electrons.com>
 Mayuresh Janorkar <mayur@ti.com>
 Michael Buesch <m@bues.ch>
 Michel Dänzer <michel@tungstengraphics.com>
index f4c6121868c37d29b9efab6985f255c2593a1aad..6768305e4c266035682f58bc25ce20ee2ddc6a74 100644 (file)
@@ -9,7 +9,7 @@ Linux PCI Bus Subsystem
    :numbered:
 
    pci
-   picebus-howto
+   pciebus-howto
    pci-iov-howto
    msi-howto
    acpi-info
index 83db420929352cce72c301d30a4435e01223fe8e..e5d450df06b4dedd91aa0507ea39181ebb845f6a 100644 (file)
@@ -403,7 +403,7 @@ That is, the recovery API only requires that:
 .. note::
 
    Implementation details for the powerpc platform are discussed in
-   the file Documentation/powerpc/eeh-pci-error-recovery.txt
+   the file Documentation/powerpc/eeh-pci-error-recovery.rst
 
    As of this writing, there is a growing list of device drivers with
    patches implementing error recovery. Not all of these patches are in
@@ -422,3 +422,6 @@ That is, the recovery API only requires that:
    - drivers/net/cxgb3
    - drivers/net/s2io.c
    - drivers/net/qlge
+
+The End
+-------
diff --git a/Documentation/PCI/pciebus-howto.rst b/Documentation/PCI/pciebus-howto.rst
new file mode 100644 (file)
index 0000000..f882ff6
--- /dev/null
@@ -0,0 +1,220 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: <isonum.txt>
+
+===========================================
+The PCI Express Port Bus Driver Guide HOWTO
+===========================================
+
+:Author: Tom L Nguyen tom.l.nguyen@intel.com 11/03/2004
+:Copyright: |copy| 2004 Intel Corporation
+
+About this guide
+================
+
+This guide describes the basics of the PCI Express Port Bus driver
+and provides information on how to enable the service drivers to
+register/unregister with the PCI Express Port Bus Driver.
+
+
+What is the PCI Express Port Bus Driver
+=======================================
+
+A PCI Express Port is a logical PCI-PCI Bridge structure. There
+are two types of PCI Express Port: the Root Port and the Switch
+Port. The Root Port originates a PCI Express link from a PCI Express
+Root Complex and the Switch Port connects PCI Express links to
+internal logical PCI buses. The Switch Port, which has its secondary
+bus representing the switch's internal routing logic, is called the
+switch's Upstream Port. The switch's Downstream Port is bridging from
+switch's internal routing bus to a bus representing the downstream
+PCI Express link from the PCI Express Switch.
+
+A PCI Express Port can provide up to four distinct functions,
+referred to in this document as services, depending on its port type.
+PCI Express Port's services include native hotplug support (HP),
+power management event support (PME), advanced error reporting
+support (AER), and virtual channel support (VC). These services may
+be handled by a single complex driver or be individually distributed
+and handled by corresponding service drivers.
+
+Why use the PCI Express Port Bus Driver?
+========================================
+
+In existing Linux kernels, the Linux Device Driver Model allows a
+physical device to be handled by only a single driver. The PCI
+Express Port is a PCI-PCI Bridge device with multiple distinct
+services. To maintain a clean and simple solution each service
+may have its own software service driver. In this case several
+service drivers will compete for a single PCI-PCI Bridge device.
+For example, if the PCI Express Root Port native hotplug service
+driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
+kernel therefore does not load other service drivers for that Root
+Port. In other words, it is impossible to have multiple service
+drivers load and run on a PCI-PCI Bridge device simultaneously
+using the current driver model.
+
+To enable multiple service drivers running simultaneously requires
+having a PCI Express Port Bus driver, which manages all populated
+PCI Express Ports and distributes all provided service requests
+to the corresponding service drivers as required. Some key
+advantages of using the PCI Express Port Bus driver are listed below:
+
+  - Allow multiple service drivers to run simultaneously on
+    a PCI-PCI Bridge Port device.
+
+  - Allow service drivers implemented in an independent
+    staged approach.
+
+  - Allow one service driver to run on multiple PCI-PCI Bridge
+    Port devices.
+
+  - Manage and distribute resources of a PCI-PCI Bridge Port
+    device to requested service drivers.
+
+Configuring the PCI Express Port Bus Driver vs. Service Drivers
+===============================================================
+
+Including the PCI Express Port Bus Driver Support into the Kernel
+-----------------------------------------------------------------
+
+Including the PCI Express Port Bus driver depends on whether the PCI
+Express support is included in the kernel config. The kernel will
+automatically include the PCI Express Port Bus driver as a kernel
+driver when the PCI Express support is enabled in the kernel.
+
+Enabling Service Driver Support
+-------------------------------
+
+PCI device drivers are implemented based on Linux Device Driver Model.
+All service drivers are PCI device drivers. As discussed above, it is
+impossible to load any service driver once the kernel has loaded the
+PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
+Model requires some minimal changes on existing service drivers that
+imposes no impact on the functionality of existing service drivers.
+
+A service driver is required to use the two APIs shown below to
+register its service with the PCI Express Port Bus driver (see
+section 5.2.1 & 5.2.2). It is important that a service driver
+initializes the pcie_port_service_driver data structure, included in
+header file /include/linux/pcieport_if.h, before calling these APIs.
+Failure to do so will result an identity mismatch, which prevents
+the PCI Express Port Bus driver from loading a service driver.
+
+pcie_port_service_register
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+::
+
+  int pcie_port_service_register(struct pcie_port_service_driver *new)
+
+This API replaces the Linux Driver Model's pci_register_driver API. A
+service driver should always calls pcie_port_service_register at
+module init. Note that after service driver being loaded, calls
+such as pci_enable_device(dev) and pci_set_master(dev) are no longer
+necessary since these calls are executed by the PCI Port Bus driver.
+
+pcie_port_service_unregister
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+::
+
+  void pcie_port_service_unregister(struct pcie_port_service_driver *new)
+
+pcie_port_service_unregister replaces the Linux Driver Model's
+pci_unregister_driver. It's always called by service driver when a
+module exits.
+
+Sample Code
+~~~~~~~~~~~
+
+Below is sample service driver code to initialize the port service
+driver data structure.
+::
+
+  static struct pcie_port_service_id service_id[] = { {
+    .vendor = PCI_ANY_ID,
+    .device = PCI_ANY_ID,
+    .port_type = PCIE_RC_PORT,
+    .service_type = PCIE_PORT_SERVICE_AER,
+    }, { /* end: all zeroes */ }
+  };
+
+  static struct pcie_port_service_driver root_aerdrv = {
+    .name              = (char *)device_name,
+    .id_table  = &service_id[0],
+
+    .probe             = aerdrv_load,
+    .remove            = aerdrv_unload,
+
+    .suspend   = aerdrv_suspend,
+    .resume            = aerdrv_resume,
+  };
+
+Below is a sample code for registering/unregistering a service
+driver.
+::
+
+  static int __init aerdrv_service_init(void)
+  {
+    int retval = 0;
+
+    retval = pcie_port_service_register(&root_aerdrv);
+    if (!retval) {
+      /*
+      * FIX ME
+      */
+    }
+    return retval;
+  }
+
+  static void __exit aerdrv_service_exit(void)
+  {
+    pcie_port_service_unregister(&root_aerdrv);
+  }
+
+  module_init(aerdrv_service_init);
+  module_exit(aerdrv_service_exit);
+
+Possible Resource Conflicts
+===========================
+
+Since all service drivers of a PCI-PCI Bridge Port device are
+allowed to run simultaneously, below lists a few of possible resource
+conflicts with proposed solutions.
+
+MSI and MSI-X Vector Resource
+-----------------------------
+
+Once MSI or MSI-X interrupts are enabled on a device, it stays in this
+mode until they are disabled again.  Since service drivers of the same
+PCI-PCI Bridge port share the same physical device, if an individual
+service driver enables or disables MSI/MSI-X mode it may result
+unpredictable behavior.
+
+To avoid this situation all service drivers are not permitted to
+switch interrupt mode on its device. The PCI Express Port Bus driver
+is responsible for determining the interrupt mode and this should be
+transparent to service drivers. Service drivers need to know only
+the vector IRQ assigned to the field irq of struct pcie_device, which
+is passed in when the PCI Express Port Bus driver probes each service
+driver. Service drivers should use (struct pcie_device*)dev->irq to
+call request_irq/free_irq. In addition, the interrupt mode is stored
+in the field interrupt_mode of struct pcie_device.
+
+PCI Memory/IO Mapped Regions
+----------------------------
+
+Service drivers for PCI Express Power Management (PME), Advanced
+Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
+PCI configuration space on the PCI Express port. In all cases the
+registers accessed are independent of each other. This patch assumes
+that all service drivers will be well behaved and not overwrite
+other service driver's configuration settings.
+
+PCI Config Registers
+--------------------
+
+Each service driver runs its PCI config operations on its own
+capability structure except the PCI Express capability structure, in
+which Root Control register and Device Control register are shared
+between PME and AER. This patch assumes that all service drivers
+will be well behaved and not overwrite other service driver's
+configuration settings.
diff --git a/Documentation/PCI/picebus-howto.rst b/Documentation/PCI/picebus-howto.rst
deleted file mode 100644 (file)
index f882ff6..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-.. include:: <isonum.txt>
-
-===========================================
-The PCI Express Port Bus Driver Guide HOWTO
-===========================================
-
-:Author: Tom L Nguyen tom.l.nguyen@intel.com 11/03/2004
-:Copyright: |copy| 2004 Intel Corporation
-
-About this guide
-================
-
-This guide describes the basics of the PCI Express Port Bus driver
-and provides information on how to enable the service drivers to
-register/unregister with the PCI Express Port Bus Driver.
-
-
-What is the PCI Express Port Bus Driver
-=======================================
-
-A PCI Express Port is a logical PCI-PCI Bridge structure. There
-are two types of PCI Express Port: the Root Port and the Switch
-Port. The Root Port originates a PCI Express link from a PCI Express
-Root Complex and the Switch Port connects PCI Express links to
-internal logical PCI buses. The Switch Port, which has its secondary
-bus representing the switch's internal routing logic, is called the
-switch's Upstream Port. The switch's Downstream Port is bridging from
-switch's internal routing bus to a bus representing the downstream
-PCI Express link from the PCI Express Switch.
-
-A PCI Express Port can provide up to four distinct functions,
-referred to in this document as services, depending on its port type.
-PCI Express Port's services include native hotplug support (HP),
-power management event support (PME), advanced error reporting
-support (AER), and virtual channel support (VC). These services may
-be handled by a single complex driver or be individually distributed
-and handled by corresponding service drivers.
-
-Why use the PCI Express Port Bus Driver?
-========================================
-
-In existing Linux kernels, the Linux Device Driver Model allows a
-physical device to be handled by only a single driver. The PCI
-Express Port is a PCI-PCI Bridge device with multiple distinct
-services. To maintain a clean and simple solution each service
-may have its own software service driver. In this case several
-service drivers will compete for a single PCI-PCI Bridge device.
-For example, if the PCI Express Root Port native hotplug service
-driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
-kernel therefore does not load other service drivers for that Root
-Port. In other words, it is impossible to have multiple service
-drivers load and run on a PCI-PCI Bridge device simultaneously
-using the current driver model.
-
-To enable multiple service drivers running simultaneously requires
-having a PCI Express Port Bus driver, which manages all populated
-PCI Express Ports and distributes all provided service requests
-to the corresponding service drivers as required. Some key
-advantages of using the PCI Express Port Bus driver are listed below:
-
-  - Allow multiple service drivers to run simultaneously on
-    a PCI-PCI Bridge Port device.
-
-  - Allow service drivers implemented in an independent
-    staged approach.
-
-  - Allow one service driver to run on multiple PCI-PCI Bridge
-    Port devices.
-
-  - Manage and distribute resources of a PCI-PCI Bridge Port
-    device to requested service drivers.
-
-Configuring the PCI Express Port Bus Driver vs. Service Drivers
-===============================================================
-
-Including the PCI Express Port Bus Driver Support into the Kernel
------------------------------------------------------------------
-
-Including the PCI Express Port Bus driver depends on whether the PCI
-Express support is included in the kernel config. The kernel will
-automatically include the PCI Express Port Bus driver as a kernel
-driver when the PCI Express support is enabled in the kernel.
-
-Enabling Service Driver Support
--------------------------------
-
-PCI device drivers are implemented based on Linux Device Driver Model.
-All service drivers are PCI device drivers. As discussed above, it is
-impossible to load any service driver once the kernel has loaded the
-PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
-Model requires some minimal changes on existing service drivers that
-imposes no impact on the functionality of existing service drivers.
-
-A service driver is required to use the two APIs shown below to
-register its service with the PCI Express Port Bus driver (see
-section 5.2.1 & 5.2.2). It is important that a service driver
-initializes the pcie_port_service_driver data structure, included in
-header file /include/linux/pcieport_if.h, before calling these APIs.
-Failure to do so will result an identity mismatch, which prevents
-the PCI Express Port Bus driver from loading a service driver.
-
-pcie_port_service_register
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-::
-
-  int pcie_port_service_register(struct pcie_port_service_driver *new)
-
-This API replaces the Linux Driver Model's pci_register_driver API. A
-service driver should always calls pcie_port_service_register at
-module init. Note that after service driver being loaded, calls
-such as pci_enable_device(dev) and pci_set_master(dev) are no longer
-necessary since these calls are executed by the PCI Port Bus driver.
-
-pcie_port_service_unregister
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-::
-
-  void pcie_port_service_unregister(struct pcie_port_service_driver *new)
-
-pcie_port_service_unregister replaces the Linux Driver Model's
-pci_unregister_driver. It's always called by service driver when a
-module exits.
-
-Sample Code
-~~~~~~~~~~~
-
-Below is sample service driver code to initialize the port service
-driver data structure.
-::
-
-  static struct pcie_port_service_id service_id[] = { {
-    .vendor = PCI_ANY_ID,
-    .device = PCI_ANY_ID,
-    .port_type = PCIE_RC_PORT,
-    .service_type = PCIE_PORT_SERVICE_AER,
-    }, { /* end: all zeroes */ }
-  };
-
-  static struct pcie_port_service_driver root_aerdrv = {
-    .name              = (char *)device_name,
-    .id_table  = &service_id[0],
-
-    .probe             = aerdrv_load,
-    .remove            = aerdrv_unload,
-
-    .suspend   = aerdrv_suspend,
-    .resume            = aerdrv_resume,
-  };
-
-Below is a sample code for registering/unregistering a service
-driver.
-::
-
-  static int __init aerdrv_service_init(void)
-  {
-    int retval = 0;
-
-    retval = pcie_port_service_register(&root_aerdrv);
-    if (!retval) {
-      /*
-      * FIX ME
-      */
-    }
-    return retval;
-  }
-
-  static void __exit aerdrv_service_exit(void)
-  {
-    pcie_port_service_unregister(&root_aerdrv);
-  }
-
-  module_init(aerdrv_service_init);
-  module_exit(aerdrv_service_exit);
-
-Possible Resource Conflicts
-===========================
-
-Since all service drivers of a PCI-PCI Bridge Port device are
-allowed to run simultaneously, below lists a few of possible resource
-conflicts with proposed solutions.
-
-MSI and MSI-X Vector Resource
------------------------------
-
-Once MSI or MSI-X interrupts are enabled on a device, it stays in this
-mode until they are disabled again.  Since service drivers of the same
-PCI-PCI Bridge port share the same physical device, if an individual
-service driver enables or disables MSI/MSI-X mode it may result
-unpredictable behavior.
-
-To avoid this situation all service drivers are not permitted to
-switch interrupt mode on its device. The PCI Express Port Bus driver
-is responsible for determining the interrupt mode and this should be
-transparent to service drivers. Service drivers need to know only
-the vector IRQ assigned to the field irq of struct pcie_device, which
-is passed in when the PCI Express Port Bus driver probes each service
-driver. Service drivers should use (struct pcie_device*)dev->irq to
-call request_irq/free_irq. In addition, the interrupt mode is stored
-in the field interrupt_mode of struct pcie_device.
-
-PCI Memory/IO Mapped Regions
-----------------------------
-
-Service drivers for PCI Express Power Management (PME), Advanced
-Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
-PCI configuration space on the PCI Express port. In all cases the
-registers accessed are independent of each other. This patch assumes
-that all service drivers will be well behaved and not overwrite
-other service driver's configuration settings.
-
-PCI Config Registers
---------------------
-
-Each service driver runs its PCI config operations on its own
-capability structure except the PCI Express capability structure, in
-which Root Control register and Device Control register are shared
-between PME and AER. This patch assumes that all service drivers
-will be well behaved and not overwrite other service driver's
-configuration settings.
index 8151f0195f7688386e8057ad34fdc9cc153b7fb8..23f115dc87cf9bb832e94f5373df0b41c07013fd 100644 (file)
@@ -1,7 +1,7 @@
 Using hlist_nulls to protect read-mostly linked lists and
 objects using SLAB_TYPESAFE_BY_RCU allocations.
 
-Please read the basics in Documentation/RCU/listRCU.txt
+Please read the basics in Documentation/RCU/listRCU.rst
 
 Using special makers (called 'nulls') is a convenient way
 to solve following problem :
diff --git a/Documentation/admin-guide/conf.py b/Documentation/admin-guide/conf.py
deleted file mode 100644 (file)
index 86f7389..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel User Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'linux-user.tex', 'Linux Kernel User Documentation',
-     'The kernel development community', 'manual'),
-]
index 25f3b253219859a6fa120850b9fcd99bd775b1bd..e05e581af5cfe617f38112907aadea8d03f2a9d6 100644 (file)
@@ -41,10 +41,11 @@ Related CVEs
 
 The following CVE entries describe Spectre variants:
 
-   =============   =======================  =================
+   =============   =======================  ==========================
    CVE-2017-5753   Bounds check bypass      Spectre variant 1
    CVE-2017-5715   Branch target injection  Spectre variant 2
-   =============   =======================  =================
+   CVE-2019-1125   Spectre v1 swapgs        Spectre variant 1 (swapgs)
+   =============   =======================  ==========================
 
 Problem
 -------
@@ -78,6 +79,13 @@ There are some extensions of Spectre variant 1 attacks for reading data
 over the network, see :ref:`[12] <spec_ref12>`. However such attacks
 are difficult, low bandwidth, fragile, and are considered low risk.
 
+Note that, despite "Bounds Check Bypass" name, Spectre variant 1 is not
+only about user-controlled array bounds checks.  It can affect any
+conditional checks.  The kernel entry code interrupt, exception, and NMI
+handlers all have conditional swapgs checks.  Those may be problematic
+in the context of Spectre v1, as kernel code can speculatively run with
+a user GS.
+
 Spectre variant 2 (Branch Target Injection)
 -------------------------------------------
 
@@ -132,6 +140,9 @@ not cover all possible attack vectors.
 1. A user process attacking the kernel
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+Spectre variant 1
+~~~~~~~~~~~~~~~~~
+
    The attacker passes a parameter to the kernel via a register or
    via a known address in memory during a syscall. Such parameter may
    be used later by the kernel as an index to an array or to derive
@@ -144,7 +155,40 @@ not cover all possible attack vectors.
    potentially be influenced for Spectre attacks, new "nospec" accessor
    macros are used to prevent speculative loading of data.
 
-   Spectre variant 2 attacker can :ref:`poison <poison_btb>` the branch
+Spectre variant 1 (swapgs)
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+   An attacker can train the branch predictor to speculatively skip the
+   swapgs path for an interrupt or exception.  If they initialize
+   the GS register to a user-space value, if the swapgs is speculatively
+   skipped, subsequent GS-related percpu accesses in the speculation
+   window will be done with the attacker-controlled GS value.  This
+   could cause privileged memory to be accessed and leaked.
+
+   For example:
+
+   ::
+
+     if (coming from user space)
+         swapgs
+     mov %gs:<percpu_offset>, %reg
+     mov (%reg), %reg1
+
+   When coming from user space, the CPU can speculatively skip the
+   swapgs, and then do a speculative percpu load using the user GS
+   value.  So the user can speculatively force a read of any kernel
+   value.  If a gadget exists which uses the percpu value as an address
+   in another load/store, then the contents of the kernel value may
+   become visible via an L1 side channel attack.
+
+   A similar attack exists when coming from kernel space.  The CPU can
+   speculatively do the swapgs, causing the user GS to get used for the
+   rest of the speculative window.
+
+Spectre variant 2
+~~~~~~~~~~~~~~~~~
+
+   A spectre variant 2 attacker can :ref:`poison <poison_btb>` the branch
    target buffer (BTB) before issuing syscall to launch an attack.
    After entering the kernel, the kernel could use the poisoned branch
    target buffer on indirect jump and jump to gadget code in speculative
@@ -280,11 +324,18 @@ The sysfs file showing Spectre variant 1 mitigation status is:
 
 The possible values in this file are:
 
-  =======================================  =================================
-  'Mitigation: __user pointer sanitation'  Protection in kernel on a case by
-                                           case base with explicit pointer
-                                           sanitation.
-  =======================================  =================================
+  .. list-table::
+
+     * - 'Not affected'
+       - The processor is not vulnerable.
+     * - 'Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers'
+       - The swapgs protections are disabled; otherwise it has
+         protection in the kernel on a case by case base with explicit
+         pointer sanitation and usercopy LFENCE barriers.
+     * - 'Mitigation: usercopy/swapgs barriers and __user pointer sanitization'
+       - Protection in the kernel on a case by case base with explicit
+         pointer sanitation, usercopy LFENCE barriers, and swapgs LFENCE
+         barriers.
 
 However, the protections are put in place on a case by case basis,
 and there is no guarantee that all possible attack vectors for Spectre
@@ -366,12 +417,27 @@ Turning on mitigation for Spectre variant 1 and Spectre variant 2
 1. Kernel mitigation
 ^^^^^^^^^^^^^^^^^^^^
 
+Spectre variant 1
+~~~~~~~~~~~~~~~~~
+
    For the Spectre variant 1, vulnerable kernel code (as determined
    by code audit or scanning tools) is annotated on a case by case
    basis to use nospec accessor macros for bounds clipping :ref:`[2]
    <spec_ref2>` to avoid any usable disclosure gadgets. However, it may
    not cover all attack vectors for Spectre variant 1.
 
+   Copy-from-user code has an LFENCE barrier to prevent the access_ok()
+   check from being mis-speculated.  The barrier is done by the
+   barrier_nospec() macro.
+
+   For the swapgs variant of Spectre variant 1, LFENCE barriers are
+   added to interrupt, exception and NMI entry where needed.  These
+   barriers are done by the FENCE_SWAPGS_KERNEL_ENTRY and
+   FENCE_SWAPGS_USER_ENTRY macros.
+
+Spectre variant 2
+~~~~~~~~~~~~~~~~~
+
    For Spectre variant 2 mitigation, the compiler turns indirect calls or
    jumps in the kernel into equivalent return trampolines (retpolines)
    :ref:`[3] <spec_ref3>` :ref:`[9] <spec_ref9>` to go to the target
@@ -473,6 +539,12 @@ Mitigation control on the kernel command line
 Spectre variant 2 mitigation can be disabled or force enabled at the
 kernel command line.
 
+       nospectre_v1
+
+               [X86,PPC] Disable mitigations for Spectre Variant 1
+               (bounds check bypass). With this option data leaks are
+               possible in the system.
+
        nospectre_v2
 
                [X86] Disable all mitigations for the Spectre variant 2
index 46b826fcb5ad55fed0d8ca92ab10751baabf64a9..4c1971960afa30484cfe0d2533e9cf28d003662c 100644 (file)
                        mem_encrypt=on:         Activate SME
                        mem_encrypt=off:        Do not activate SME
 
-                       Refer to Documentation/virtual/kvm/amd-memory-encryption.rst
+                       Refer to Documentation/virt/kvm/amd-memory-encryption.rst
                        for details on when memory encryption can be activated.
 
        mem_sleep_default=      [SUSPEND] Default system suspend mode:
                                expose users to several CPU vulnerabilities.
                                Equivalent to: nopti [X86,PPC]
                                               kpti=0 [ARM64]
-                                              nospectre_v1 [PPC]
+                                              nospectre_v1 [X86,PPC]
                                               nobp=0 [S390]
                                               nospectre_v2 [X86,PPC,S390,ARM64]
                                               spectre_v2_user=off [X86]
                        nosmt=force: Force disable SMT, cannot be undone
                                     via the sysfs control file.
 
-       nospectre_v1    [PPC] Disable mitigations for Spectre Variant 1 (bounds
-                       check bypass). With this option data leaks are possible
-                       in the system.
+       nospectre_v1    [X86,PPC] Disable mitigations for Spectre Variant 1
+                       (bounds check bypass). With this option data leaks are
+                       possible in the system.
 
        nospectre_v2    [X86,PPC_FSL_BOOK3E,ARM64] Disable all mitigations for
                        the Spectre variant 2 (indirect branch prediction)
                        Run specified binary instead of /init from the ramdisk,
                        used for early userspace startup. See initrd.
 
+       rdrand=         [X86]
+                       force - Override the decision by the kernel to hide the
+                               advertisement of RDRAND support (this affects
+                               certain AMD processors because of buggy BIOS
+                               support, specifically around the suspend/resume
+                               path).
+
        rdt=            [HW,X86,RDT]
                        Turn on/off individual RDT features. List is:
                        cmt, mbmtotal, mbmlocal, l3cat, l3cdp, l2cat, l2cdp,
index 7ab93a8404b9de0c223e74c28713da66b7f49f5a..bd5714547cee0cbb06edd31d59c0d4f12476ad33 100644 (file)
@@ -53,7 +53,7 @@ disabled, there is ``khugepaged`` daemon that scans memory and
 collapses sequences of basic pages into huge pages.
 
 The THP behaviour is controlled via :ref:`sysfs <thp_sysfs>`
-interface and using madivse(2) and prctl(2) system calls.
+interface and using madvise(2) and prctl(2) system calls.
 
 Transparent Hugepage Support maximizes the usefulness of free memory
 if compared to the reservation approach of hugetlbfs by allowing all
index a7d44e71019d680f283b2e7bcbe25e59e079c1bb..287b98708a40915a80ba76455621b507cce161bd 100644 (file)
@@ -39,7 +39,6 @@ Table : Subdirectories in /proc/sys/net
  802       E802 protocol         ax25       AX25
  ethernet  Ethernet protocol     rose       X.25 PLP layer
  ipv4      IP version 4          x25        X.25 protocol
- ipx       IPX                   token-ring IBM token ring
  bridge    Bridging              decnet     DEC net
  ipv6      IP version 6          tipc       TIPC
  ========= =================== = ========== ==================
@@ -401,33 +400,7 @@ interface.
 (network) that the route leads to, the router (may be directly connected), the
 route flags, and the device the route is using.
 
-
-5. IPX
-------
-
-The IPX protocol has no tunable values in proc/sys/net.
-
-The IPX  protocol  does,  however,  provide  proc/net/ipx. This lists each IPX
-socket giving  the  local  and  remote  addresses  in  Novell  format (that is
-network:node:port). In  accordance  with  the  strange  Novell  tradition,
-everything but the port is in hex. Not_Connected is displayed for sockets that
-are not  tied to a specific remote address. The Tx and Rx queue sizes indicate
-the number  of  bytes  pending  for  transmission  and  reception.  The  state
-indicates the  state  the  socket  is  in and the uid is the owning uid of the
-socket.
-
-The /proc/net/ipx_interface  file lists all IPX interfaces. For each interface
-it gives  the network number, the node number, and indicates if the network is
-the primary  network.  It  also  indicates  which  device  it  is bound to (or
-Internal for  internal  networks)  and  the  Frame  Type if appropriate. Linux
-supports 802.3,  802.2,  802.2  SNAP  and DIX (Blue Book) ethernet framing for
-IPX.
-
-The /proc/net/ipx_route  table  holds  a list of IPX routes. For each route it
-gives the  destination  network, the router node (or Directly) and the network
-address of the router (or Connected) for internal networks.
-
-6. TIPC
+5. TIPC
 -------
 
 tipc_rmem
index 3b2397bcb5650a64350a5184d3be8bdcb899b78d..a8fe845832bce4e24173812c8fc342cbcc91ed3c 100644 (file)
@@ -16,6 +16,8 @@ import sys
 import os
 import sphinx
 
+from subprocess import check_output
+
 # Get Sphinx version
 major, minor, patch = sphinx.version_info[:3]
 
@@ -276,10 +278,21 @@ latex_elements = {
         \\setsansfont{DejaVu Sans}
         \\setromanfont{DejaVu Serif}
         \\setmonofont{DejaVu Sans Mono}
-
      '''
 }
 
+# At least one book (translations) may have Asian characters
+# with are only displayed if xeCJK is used
+
+cjk_cmd = check_output(['fc-list', '--format="%{family[0]}\n"']).decode('utf-8', 'ignore')
+if cjk_cmd.find("Noto Sans CJK SC") >= 0:
+    print ("enabling CJK for LaTeX builder")
+    latex_elements['preamble']  += '''
+       % This is needed for translations
+        \\usepackage{xeCJK}
+        \\setCJKmainfont{Noto Sans CJK SC}
+     '''
+
 # Fix reference escape troubles with Sphinx 1.4.x
 if major == 1 and minor > 3:
     latex_elements['preamble']  += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
@@ -410,6 +423,21 @@ latex_documents = [
      'The kernel development community', 'manual'),
 ]
 
+# Add all other index files from Documentation/ subdirectories
+for fn in os.listdir('.'):
+    doc = os.path.join(fn, "index")
+    if os.path.exists(doc + ".rst"):
+        has = False
+        for l in latex_documents:
+            if l[0] == doc:
+                has = True
+                break
+        if not has:
+            latex_documents.append((doc, fn + '.tex',
+                                    'Linux %s Documentation' % fn.capitalize(),
+                                    'The kernel development community',
+                                    'manual'))
+
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
 #latex_logo = None
diff --git a/Documentation/core-api/conf.py b/Documentation/core-api/conf.py
deleted file mode 100644 (file)
index db1f765..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Core-API Documentation"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'core-api.tex', project,
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/crypto/conf.py b/Documentation/crypto/conf.py
deleted file mode 100644 (file)
index 4335d25..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Crypto API'
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'crypto-api.tex', 'Linux Kernel Crypto API manual',
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/dev-tools/conf.py b/Documentation/dev-tools/conf.py
deleted file mode 100644 (file)
index 7faafa3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Development tools for the kernel"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'dev-tools.tex', project,
-     'The kernel development community', 'manual'),
-]
index 6b0dfd5c17baccb3232f032738a7a5c53efd28c9..5138a2f6232aa23cdc98211d2e3fcaaa2890030e 100644 (file)
@@ -19,7 +19,9 @@ quiet_cmd_mk_schema = SCHEMA  $@
 
 DT_DOCS = $(shell \
        cd $(srctree)/$(src) && \
-       find * \( -name '*.yaml' ! -name $(DT_TMP_SCHEMA) \) \
+       find * \( -name '*.yaml' ! \
+               -name $(DT_TMP_SCHEMA) ! \
+               -name '*.example.dt.yaml' \) \
        )
 
 DT_SCHEMA_FILES ?= $(addprefix $(src)/,$(DT_DOCS))
index 326f29b270ad140dfa421203f719d6d4c9b3da1e..2d325bed37e53c1cd39607a7ba8e2cdf9f2bc5a4 100644 (file)
@@ -703,4 +703,4 @@ cpus {
     https://www.devicetree.org/specifications/
 
 [6] ARM Linux Kernel documentation - Booting AArch64 Linux
-    Documentation/arm64/booting.txt
+    Documentation/arm64/booting.rst
index 08c923f8c25788b6c563a8f48dfb4fd5dd7b6242..28eb458f761ac1d2a365eb3a7538280216b218db 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/arm/shmobile.yaml#
+$id: http://devicetree.org/schemas/arm/renesas.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Renesas SH-Mobile, R-Mobile, and R-Car Platform Device Tree Bindings
index aae53fc3cb1ec734d0414889a374306ddaff32e9..2bd519d2e8557fae8f648ab32fe416bb6e39fc71 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/arm/milbeaut.yaml#
+$id: http://devicetree.org/schemas/arm/socionext/milbeaut.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Milbeaut platforms device tree bindings
index 4326d2cfa15d05d40e7d5bb188075dba9fb37b26..a8765ba29476cac331edd641cab3f6de2dab9092 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/arm/ti/davinci.yaml#
+$id: http://devicetree.org/schemas/arm/ti/ti,davinci.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Texas Instruments DaVinci Platforms Device Tree Bindings
index c935405458fed1304a17fce059371ec8660bcc04..fa4d143a73de2e16d5c7d841c4dacd69cdd9817c 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/phy/allwinner,sun4i-a10-ccu.yaml#
+$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-ccu.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Allwinner Clock Control Unit Device Tree Bindings
index 8cb136c376fbe8dcfb4379179e2fb3a396b18ffe..4f0db8ee226a96881f71519b8ee66cdca5626874 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright 2019 Linaro Ltd.
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/firmware/intel-ixp4xx-network-processing-engine.yaml#"
+$id: "http://devicetree.org/schemas/firmware/intel,ixp4xx-network-processing-engine.yaml#"
 $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 
 title: Intel IXP4xx Network Processing Engine
index 7ba167e2e1eabe6b73fca04b173de38f8b8d1bc7..c602b6fe1c0c51fec01bf58afb5a146d35d6b497 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/iio/accelerometers/adi,adxl345.yaml#
+$id: http://devicetree.org/schemas/iio/accel/adi,adxl345.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Analog Devices ADXL345/ADXL375 3-Axis Digital Accelerometers
index a7fafb9bf5c61c0f2ee9686e978eef77df9c5ce5..e7daffec88d3667ca9a86b4f5cdd53c1addde737 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/iio/accelerometers/adi,adxl372.yaml#
+$id: http://devicetree.org/schemas/iio/accel/adi,adxl372.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
index 4e82fd575cecab3e3e7b55b5fecf8acb086bdee2..c676b03c752edbe16dacc82e82a88d9bac1e0e0f 100644 (file)
@@ -5,21 +5,19 @@ Required properties:
 - compatible: should be "amazon,al-fic"
 - reg: physical base address and size of the registers
 - interrupt-controller: identifies the node as an interrupt controller
-- #interrupt-cells: must be 2.
-  First cell defines the index of the interrupt within the controller.
-  Second cell is used to specify the trigger type and must be one of the
-  following:
-    - bits[3:0] trigger type and level flags
-       1 = low-to-high edge triggered
-       4 = active high level-sensitive
-- interrupt-parent: specifies the parent interrupt controller.
+- #interrupt-cells : must be 2. Specifies the number of cells needed to encode
+  an interrupt source. Supported trigger types are low-to-high edge
+  triggered and active high level-sensitive.
 - interrupts: describes which input line in the interrupt parent, this
   fic's output is connected to. This field property depends on the parent's
   binding
 
+Please refer to interrupts.txt in this directory for details of the common
+Interrupt Controllers bindings used by client devices.
+
 Example:
 
-amazon_fic: interrupt-controller@0xfd8a8500 {
+amazon_fic: interrupt-controller@fd8a8500 {
        compatible = "amazon,al-fic";
        interrupt-controller;
        #interrupt-cells = <2>;
index bae10e261fa9cbc3a025ad058d94d97d64e50f31..507c141ea76038a0e9e61c4b3d9e44d90db4f603 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright 2018 Linaro Ltd.
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/interrupt/intel-ixp4xx-interrupt.yaml#"
+$id: "http://devicetree.org/schemas/interrupt-controller/intel,ixp4xx-interrupt.yaml#"
 $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 
 title: Intel IXP4xx XScale Networking Processors Interrupt Controller
index 09fc02b9984577860563661d881d88f3308a489a..a5c1db95b3ecb105c31eb7890bc731340ba92a3a 100644 (file)
@@ -1,20 +1,30 @@
 * ARC-HS Interrupt Distribution Unit
 
-  This optional 2nd level interrupt controller can be used in SMP configurations for
-  dynamic IRQ routing, load balancing of common/external IRQs towards core intc.
+  This optional 2nd level interrupt controller can be used in SMP configurations
+  for dynamic IRQ routing, load balancing of common/external IRQs towards core
+  intc.
 
 Properties:
 
 - compatible: "snps,archs-idu-intc"
 - interrupt-controller: This is an interrupt controller.
-- #interrupt-cells: Must be <1>.
-
-  Value of the cell specifies the "common" IRQ from peripheral to IDU. Number N
-  of the particular interrupt line of IDU corresponds to the line N+24 of the
-  core interrupt controller.
-
-  intc accessed via the special ARC AUX register interface, hence "reg" property
-  is not specified.
+- #interrupt-cells: Must be <1> or <2>.
+
+  Value of the first cell specifies the "common" IRQ from peripheral to IDU.
+  Number N of the particular interrupt line of IDU corresponds to the line N+24
+  of the core interrupt controller.
+
+  The (optional) second cell specifies any of the following flags:
+    - bits[3:0] trigger type and level flags
+        1 = low-to-high edge triggered
+        2 = NOT SUPPORTED (high-to-low edge triggered)
+        4 = active high level-sensitive <<< DEFAULT
+        8 = NOT SUPPORTED (active low level-sensitive)
+  When no second cell is specified, the interrupt is assumed to be level
+  sensitive.
+
+  The interrupt controller is accessed via the special ARC AUX register
+  interface, hence "reg" property is not specified.
 
 Example:
        core_intc: core-interrupt-controller {
diff --git a/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml b/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml
new file mode 100644 (file)
index 0000000..0ea21a6
--- /dev/null
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019 Linaro Ltd.
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/misc/intel,ixp4xx-ahb-queue-manager.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Intel IXP4xx AHB Queue Manager
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+  The IXP4xx AHB Queue Manager maintains queues as circular buffers in
+  an 8KB embedded SRAM along with hardware pointers. It is used by both
+  the XScale processor and the NPEs (Network Processing Units) in the
+  IXP4xx for accelerating queues, especially for networking. Clients pick
+  queues from the queue manager with foo-queue = <&qmgr N> where the
+  &qmgr is a phandle to the queue manager and N is the queue resource
+  number. The queue resources available and their specific purpose
+  on a certain IXP4xx system will vary.
+
+properties:
+  compatible:
+    items:
+      - const: intel,ixp4xx-ahb-queue-manager
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    items:
+      - description: Interrupt for queues 0-31
+      - description: Interrupt for queues 32-63
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    qmgr: queue-manager@60000000 {
+         compatible = "intel,ixp4xx-ahb-queue-manager";
+         reg = <0x60000000 0x4000>;
+         interrupts = <3 IRQ_TYPE_LEVEL_HIGH>, <4 IRQ_TYPE_LEVEL_HIGH>;
+    };
diff --git a/Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml b/Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml
deleted file mode 100644 (file)
index d2313b1..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-# Copyright 2019 Linaro Ltd.
-%YAML 1.2
----
-$id: "http://devicetree.org/schemas/misc/intel-ixp4xx-ahb-queue-manager.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
-
-title: Intel IXP4xx AHB Queue Manager
-
-maintainers:
-  - Linus Walleij <linus.walleij@linaro.org>
-
-description: |
-  The IXP4xx AHB Queue Manager maintains queues as circular buffers in
-  an 8KB embedded SRAM along with hardware pointers. It is used by both
-  the XScale processor and the NPEs (Network Processing Units) in the
-  IXP4xx for accelerating queues, especially for networking. Clients pick
-  queues from the queue manager with foo-queue = <&qmgr N> where the
-  &qmgr is a phandle to the queue manager and N is the queue resource
-  number. The queue resources available and their specific purpose
-  on a certain IXP4xx system will vary.
-
-properties:
-  compatible:
-    items:
-      - const: intel,ixp4xx-ahb-queue-manager
-
-  reg:
-    maxItems: 1
-
-  interrupts:
-    items:
-      - description: Interrupt for queues 0-31
-      - description: Interrupt for queues 32-63
-
-required:
-  - compatible
-  - reg
-  - interrupts
-
-examples:
-  - |
-    #include <dt-bindings/interrupt-controller/irq.h>
-
-    qmgr: queue-manager@60000000 {
-         compatible = "intel,ixp4xx-ahb-queue-manager";
-         reg = <0x60000000 0x4000>;
-         interrupts = <3 IRQ_TYPE_LEVEL_HIGH>, <4 IRQ_TYPE_LEVEL_HIGH>;
-    };
index d4084c149768eaaf24bc84616de19a712c9a46e8..3fb0714e761edea9f441906a04825ed5643369ed 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/net/allwinner,sun8i-a83t-gmac.yaml#
+$id: http://devicetree.org/schemas/net/allwinner,sun8i-a83t-emac.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Allwinner A83t EMAC Device Tree Bindings
index 4ac21cef370ece9fb5b769b3c217d47d5a08d2d9..113e7ac79aad59259e035ea2179a51e4c62fbba4 100644 (file)
@@ -12,6 +12,7 @@ Required properties:
   - "microchip,ksz8565"
   - "microchip,ksz9893"
   - "microchip,ksz9563"
+  - "microchip,ksz8563"
 
 Optional properties:
 
index 2d41fb96ce0a2b66acf309071f1534c6437f52cf..5b88fae0307d153e50a6faac33d6152bdf2711d4 100644 (file)
@@ -7,18 +7,6 @@ Required properties:
 - phy-mode : See ethernet.txt file in the same directory
 
 Optional properties:
-- phy-reset-gpios : Should specify the gpio for phy reset
-- phy-reset-duration : Reset duration in milliseconds.  Should present
-  only if property "phy-reset-gpios" is available.  Missing the property
-  will have the duration be 1 millisecond.  Numbers greater than 1000 are
-  invalid and 1 millisecond will be used instead.
-- phy-reset-active-high : If present then the reset sequence using the GPIO
-  specified in the "phy-reset-gpios" property is reversed (H=reset state,
-  L=operation state).
-- phy-reset-post-delay : Post reset delay in milliseconds. If present then
-  a delay of phy-reset-post-delay milliseconds will be observed after the
-  phy-reset-gpios has been toggled. Can be omitted thus no delay is
-  observed. Delay is in range of 1ms to 1000ms. Other delays are invalid.
 - phy-supply : regulator that powers the Ethernet PHY.
 - phy-handle : phandle to the PHY device connected to this device.
 - fixed-link : Assume a fixed link. See fixed-link.txt in the same directory.
@@ -47,11 +35,27 @@ Optional properties:
   For imx6sx, "int0" handles all 3 queues and ENET_MII. "pps" is for the pulse
   per second interrupt associated with 1588 precision time protocol(PTP).
 
-
 Optional subnodes:
 - mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
   according to phy.txt in the same directory
 
+Deprecated optional properties:
+       To avoid these, create a phy node according to phy.txt in the same
+       directory, and point the fec's "phy-handle" property to it. Then use
+       the phy's reset binding, again described by phy.txt.
+- phy-reset-gpios : Should specify the gpio for phy reset
+- phy-reset-duration : Reset duration in milliseconds.  Should present
+  only if property "phy-reset-gpios" is available.  Missing the property
+  will have the duration be 1 millisecond.  Numbers greater than 1000 are
+  invalid and 1 millisecond will be used instead.
+- phy-reset-active-high : If present then the reset sequence using the GPIO
+  specified in the "phy-reset-gpios" property is reversed (H=reset state,
+  L=operation state).
+- phy-reset-post-delay : Post reset delay in milliseconds. If present then
+  a delay of phy-reset-post-delay milliseconds will be observed after the
+  phy-reset-gpios has been toggled. Can be omitted thus no delay is
+  observed. Delay is in range of 1ms to 1000ms. Other delays are invalid.
+
 Example:
 
 ethernet@83fec000 {
index 63c73fafe26dcc73be043d84d036cb776f1c97b8..0b61a90f1592bfd6a31534fc41bfb955b477e5f7 100644 (file)
@@ -15,10 +15,10 @@ Required properties:
   Use "atmel,sama5d4-gem" for the GEM IP (10/100) available on Atmel sama5d4 SoCs.
   Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
   Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
-  Use "sifive,fu540-macb" for SiFive FU540-C000 SoC.
+  Use "sifive,fu540-c000-gem" for SiFive FU540-C000 SoC.
   Or the generic form: "cdns,emac".
 - reg: Address and length of the register set for the device
-       For "sifive,fu540-macb", second range is required to specify the
+       For "sifive,fu540-c000-gem", second range is required to specify the
        address and length of the registers for GEMGXL Management block.
 - interrupts: Should contain macb interrupt
 - phy-mode: See ethernet.txt file in the same directory.
index c9efd6e2c13469c765153d53484efbe0a0bd479d..1084e9d2917d041f1fa0a09ff132bf2d54b28db4 100644 (file)
@@ -37,13 +37,13 @@ required:
 
 examples:
   - |
-    sid@1c23800 {
+    efuse@1c23800 {
         compatible = "allwinner,sun4i-a10-sid";
         reg = <0x01c23800 0x10>;
     };
 
   - |
-    sid@1c23800 {
+    efuse@1c23800 {
         compatible = "allwinner,sun7i-a20-sid";
         reg = <0x01c23800 0x200>;
     };
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml b/Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml
new file mode 100644 (file)
index 0000000..b7c00ed
--- /dev/null
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/nvmem-consumer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVMEM (Non Volatile Memory) Consumer Device Tree Bindings
+
+maintainers:
+  - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+select: true
+
+properties:
+  nvmem:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description:
+      List of phandle to the nvmem providers.
+
+  nvmem-cells:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description:
+      List of phandle to the nvmem data cells.
+
+  nvmem-names:
+    $ref: /schemas/types.yaml#/definitions/string-array
+    description:
+      Names for the each nvmem provider.
+
+  nvmem-cell-names:
+    $ref: /schemas/types.yaml#/definitions/string-array
+    description:
+      Names for each nvmem-cells specified.
+
+dependencies:
+  nvmem-names: [ nvmem ]
+  nvmem-cell-names: [ nvmem-cells ]
+
+examples:
+  - |
+    tsens {
+        /* ... */
+        nvmem-cells = <&tsens_calibration>;
+        nvmem-cell-names = "calibration";
+    };
index fd06c09b822b91b6aa0184d699df9b682884dc1f..46a7ef485e24154570b9836841ca67c17699b6a6 100644 (file)
@@ -1,80 +1 @@
-= NVMEM(Non Volatile Memory) Data Device Tree Bindings =
-
-This binding is intended to represent the location of hardware
-configuration data stored in NVMEMs like eeprom, efuses and so on.
-
-On a significant proportion of boards, the manufacturer has stored
-some data on NVMEM, for the OS to be able to retrieve these information
-and act upon it. Obviously, the OS has to know about where to retrieve
-these data from, and where they are stored on the storage device.
-
-This document is here to document this.
-
-= Data providers =
-Contains bindings specific to provider drivers and data cells as children
-of this node.
-
-Optional properties:
- read-only: Mark the provider as read only.
-
-= Data cells =
-These are the child nodes of the provider which contain data cell
-information like offset and size in nvmem provider.
-
-Required properties:
-reg:   specifies the offset in byte within the storage device.
-
-Optional properties:
-
-bits:  Is pair of bit location and number of bits, which specifies offset
-       in bit and number of bits within the address range specified by reg property.
-       Offset takes values from 0-7.
-
-For example:
-
-       /* Provider */
-       qfprom: qfprom@700000 {
-               ...
-
-               /* Data cells */
-               tsens_calibration: calib@404 {
-                       reg = <0x404 0x10>;
-               };
-
-               tsens_calibration_bckp: calib_bckp@504 {
-                       reg = <0x504 0x11>;
-                       bits = <6 128>
-               };
-
-               pvs_version: pvs-version@6 {
-                       reg = <0x6 0x2>
-                       bits = <7 2>
-               };
-
-               speed_bin: speed-bin@c{
-                       reg = <0xc 0x1>;
-                       bits = <2 3>;
-
-               };
-               ...
-       };
-
-= Data consumers =
-Are device nodes which consume nvmem data cells/providers.
-
-Required-properties:
-nvmem-cells: list of phandle to the nvmem data cells.
-nvmem-cell-names: names for the each nvmem-cells specified. Required if
-       nvmem-cells is used.
-
-Optional-properties:
-nvmem  : list of phandles to nvmem providers.
-nvmem-names: names for the each nvmem provider. required if nvmem is used.
-
-For example:
-
-       tsens {
-               ...
-               nvmem-cells = <&tsens_calibration>;
-               nvmem-cell-names = "calibration";
-       };
+This file has been moved to nvmem.yaml and nvmem-consumer.yaml.
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.yaml b/Documentation/devicetree/bindings/nvmem/nvmem.yaml
new file mode 100644 (file)
index 0000000..1c75a05
--- /dev/null
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/nvmem.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVMEM (Non Volatile Memory) Device Tree Bindings
+
+maintainers:
+  - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+description: |
+  This binding is intended to represent the location of hardware
+  configuration data stored in NVMEMs like eeprom, efuses and so on.
+
+  On a significant proportion of boards, the manufacturer has stored
+  some data on NVMEM, for the OS to be able to retrieve these
+  information and act upon it. Obviously, the OS has to know about
+  where to retrieve these data from, and where they are stored on the
+  storage device.
+
+properties:
+  $nodename:
+    pattern: "^(eeprom|efuse|nvram)(@.*|-[0-9a-f])*$"
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 1
+
+  read-only:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Mark the provider as read only.
+
+patternProperties:
+  "^.*@[0-9a-f]+$":
+    type: object
+
+    properties:
+      reg:
+        maxItems: 1
+        description:
+          Offset and size in bytes within the storage device.
+
+      bits:
+        maxItems: 1
+        items:
+          items:
+            - minimum: 0
+              maximum: 7
+              description:
+                Offset in bit within the address range specified by reg.
+            - minimum: 1
+              description:
+                Size in bit within the address range specified by reg.
+
+    required:
+      - reg
+
+    additionalProperties: false
+
+examples:
+  - |
+      qfprom: eeprom@700000 {
+          #address-cells = <1>;
+          #size-cells = <1>;
+
+          /* ... */
+
+          /* Data cells */
+          tsens_calibration: calib@404 {
+              reg = <0x404 0x10>;
+          };
+
+          tsens_calibration_bckp: calib_bckp@504 {
+              reg = <0x504 0x11>;
+              bits = <6 128>;
+          };
+
+          pvs_version: pvs-version@6 {
+              reg = <0x6 0x2>;
+              bits = <7 2>;
+          };
+
+          speed_bin: speed-bin@c{
+              reg = <0xc 0x1>;
+              bits = <2 3>;
+          };
+      };
+
+...
index 250f9d5aabdf5b7426924557c71a1c97a4b85138..fa46670de2992dd1bde4809e397a905e8f77e72f 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/display/allwinner,sun6i-a31-mipi-dphy.yaml#
+$id: http://devicetree.org/schemas/phy/allwinner,sun6i-a31-mipi-dphy.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Allwinner A31 MIPI D-PHY Controller Device Tree Bindings
index 91d3e78b3395cd3b23b07826f6fcee9cda71166e..400df2da018a32f0ee2b0e036ac3432912dac0a4 100644 (file)
@@ -37,7 +37,8 @@ properties:
   hwlocks: true
 
   st,syscfg:
-    $ref: "/schemas/types.yaml#/definitions/phandle-array"
+    allOf:
+      - $ref: "/schemas/types.yaml#/definitions/phandle-array"
     description: Should be phandle/offset/mask
     items:
       - description: Phandle to the syscon node which includes IRQ mux selection.
diff --git a/Documentation/devicetree/bindings/riscv/cpus.txt b/Documentation/devicetree/bindings/riscv/cpus.txt
deleted file mode 100644 (file)
index adf7b7a..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-===================
-RISC-V CPU Bindings
-===================
-
-The device tree allows to describe the layout of CPUs in a system through
-the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
-defining properties for every cpu.
-
-Bindings for CPU nodes follow the Devicetree Specification, available from:
-
-https://www.devicetree.org/specifications/
-
-with updates for 32-bit and 64-bit RISC-V systems provided in this document.
-
-===========
-Terminology
-===========
-
-This document uses some terminology common to the RISC-V community that is not
-widely used, the definitions of which are listed here:
-
-* hart: A hardware execution context, which contains all the state mandated by
-  the RISC-V ISA: a PC and some registers.  This terminology is designed to
-  disambiguate software's view of execution contexts from any particular
-  microarchitectural implementation strategy.  For example, my Intel laptop is
-  described as having one socket with two cores, each of which has two hyper
-  threads.  Therefore this system has four harts.
-
-=====================================
-cpus and cpu node bindings definition
-=====================================
-
-The RISC-V architecture, in accordance with the Devicetree Specification,
-requires the cpus and cpu nodes to be present and contain the properties
-described below.
-
-- cpus node
-
-        Description: Container of cpu nodes
-
-        The node name must be "cpus".
-
-        A cpus node must define the following properties:
-
-        - #address-cells
-                Usage: required
-                Value type: <u32>
-                Definition: must be set to 1
-        - #size-cells
-                Usage: required
-                Value type: <u32>
-                Definition: must be set to 0
-
-- cpu node
-
-        Description: Describes a hart context
-
-        PROPERTIES
-
-        - device_type
-                Usage: required
-                Value type: <string>
-                Definition: must be "cpu"
-        - reg
-                Usage: required
-                Value type: <u32>
-                Definition: The hart ID of this CPU node
-        - compatible:
-                Usage: required
-                Value type: <stringlist>
-                Definition: must contain "riscv", may contain one of
-                            "sifive,rocket0"
-        - mmu-type:
-                Usage: optional
-                Value type: <string>
-                Definition: Specifies the CPU's MMU type.  Possible values are
-                            "riscv,sv32"
-                            "riscv,sv39"
-                            "riscv,sv48"
-        - riscv,isa:
-                Usage: required
-                Value type: <string>
-                Definition: Contains the RISC-V ISA string of this hart.  These
-                            ISA strings are defined by the RISC-V ISA manual.
-
-Example: SiFive Freedom U540G Development Kit
----------------------------------------------
-
-This system contains two harts: a hart marked as disabled that's used for
-low-level system tasks and should be ignored by Linux, and a second hart that
-Linux is allowed to run on.
-
-        cpus {
-                #address-cells = <1>;
-                #size-cells = <0>;
-                timebase-frequency = <1000000>;
-                cpu@0 {
-                        clock-frequency = <1600000000>;
-                        compatible = "sifive,rocket0", "riscv";
-                        device_type = "cpu";
-                        i-cache-block-size = <64>;
-                        i-cache-sets = <128>;
-                        i-cache-size = <16384>;
-                        next-level-cache = <&L15 &L0>;
-                        reg = <0>;
-                        riscv,isa = "rv64imac";
-                        status = "disabled";
-                        L10: interrupt-controller {
-                                #interrupt-cells = <1>;
-                                compatible = "riscv,cpu-intc";
-                                interrupt-controller;
-                        };
-                };
-                cpu@1 {
-                        clock-frequency = <1600000000>;
-                        compatible = "sifive,rocket0", "riscv";
-                        d-cache-block-size = <64>;
-                        d-cache-sets = <64>;
-                        d-cache-size = <32768>;
-                        d-tlb-sets = <1>;
-                        d-tlb-size = <32>;
-                        device_type = "cpu";
-                        i-cache-block-size = <64>;
-                        i-cache-sets = <64>;
-                        i-cache-size = <32768>;
-                        i-tlb-sets = <1>;
-                        i-tlb-size = <32>;
-                        mmu-type = "riscv,sv39";
-                        next-level-cache = <&L15 &L0>;
-                        reg = <1>;
-                        riscv,isa = "rv64imafdc";
-                        status = "okay";
-                        tlb-split;
-                        L13: interrupt-controller {
-                                #interrupt-cells = <1>;
-                                compatible = "riscv,cpu-intc";
-                                interrupt-controller;
-                        };
-                };
-        };
-
-Example: Spike ISA Simulator with 1 Hart
-----------------------------------------
-
-This device tree matches the Spike ISA golden model as run with `spike -p1`.
-
-        cpus {
-                cpu@0 {
-                        device_type = "cpu";
-                        reg = <0x00000000>;
-                        status = "okay";
-                        compatible = "riscv";
-                        riscv,isa = "rv64imafdc";
-                        mmu-type = "riscv,sv48";
-                        clock-frequency = <0x3b9aca00>;
-                        interrupt-controller {
-                                #interrupt-cells = <0x00000001>;
-                                interrupt-controller;
-                                compatible = "riscv,cpu-intc";
-                        }
-                }
-        }
index c899111aa5e3799cf84524d932dbd55448164c0f..b261a3015f84f3c7982397123d908beabe45e9cd 100644 (file)
@@ -10,6 +10,18 @@ maintainers:
   - Paul Walmsley <paul.walmsley@sifive.com>
   - Palmer Dabbelt <palmer@sifive.com>
 
+description: |
+  This document uses some terminology common to the RISC-V community
+  that is not widely used, the definitions of which are listed here:
+
+  hart: A hardware execution context, which contains all the state
+  mandated by the RISC-V ISA: a PC and some registers.  This
+  terminology is designed to disambiguate software's view of execution
+  contexts from any particular microarchitectural implementation
+  strategy.  For example, an Intel laptop containing one socket with
+  two cores, each of which has two hyperthreads, could be described as
+  having four harts.
+
 properties:
   compatible:
     items:
@@ -50,6 +62,10 @@ properties:
       User-Level ISA document, available from
       https://riscv.org/specifications/
 
+      While the isa strings in ISA specification are case
+      insensitive, letters in the riscv,isa string must be all
+      lowercase to simplify parsing.
+
   timebase-frequency:
     type: integer
     minimum: 1
index 9d17dc2f3f843611ca2cbda105d8c537b98b4322..3ab532713dc12dfe0273f320b0ff9700e764890f 100644 (file)
@@ -19,7 +19,7 @@ properties:
   compatible:
     items:
       - enum:
-          - sifive,freedom-unleashed-a00
+          - sifive,hifive-unleashed-a00
       - const: sifive,fu540-c000
       - const: sifive,fu540
 ...
index 876c0623f322916a1d228da85371a381230d37a4..a02e2fe2bfb22350773759da4b27fc13800f1c49 100644 (file)
@@ -73,7 +73,6 @@ patternProperties:
           Compatible of the SPI device.
 
       reg:
-        maxItems: 1
         minimum: 0
         maximum: 256
         description:
index a36a0746c056392bee9be075eb5ea147e2108c4f..2807225db902a5542c02079e409574a9141cd06e 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright 2018 Linaro Ltd.
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/timer/intel-ixp4xx-timer.yaml#"
+$id: "http://devicetree.org/schemas/timer/intel,ixp4xx-timer.yaml#"
 $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 
 title: Intel IXP4xx XScale Networking Processors Timers
index bc7945e9dbfe73a4f1ca7eb89c81da2d1a4a8aa1..17915f64b8ee3c628e6c7e86385d31a942d11067 100644 (file)
@@ -64,10 +64,8 @@ Optional properties :
  - power-on-time-ms : Specifies the time it takes from the time the host
        initiates the power-on sequence to a port until the port has adequate
        power. The value is given in ms in a 0 - 510 range (default is 100ms).
- - swap-dx-lanes : Specifies the downstream ports which will swap the
-       differential-pair (D+/D-), default is not-swapped.
- - swap-us-lanes : Selects the upstream port differential-pair (D+/D-)
-       swapping (boolean, default is not-swapped)
+ - swap-dx-lanes : Specifies the ports which will swap the differential-pair
+       (D+/D-), default is not-swapped.
 
 Examples:
        usb2512b@2c {
diff --git a/Documentation/doc-guide/conf.py b/Documentation/doc-guide/conf.py
deleted file mode 100644 (file)
index fd37311..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Documentation Guide'
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'kernel-doc-guide.tex', 'Linux Kernel Documentation Guide',
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/driver-api/80211/conf.py b/Documentation/driver-api/80211/conf.py
deleted file mode 100644 (file)
index 4424b4b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux 802.11 Driver Developer's Guide"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', '80211.tex', project,
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/driver-api/conf.py b/Documentation/driver-api/conf.py
deleted file mode 100644 (file)
index 202726d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "The Linux driver implementer's API guide"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'driver-api.tex', project,
-     'The kernel development community', 'manual'),
-]
index 0c161b1a3be6d3d44e185a4b419abedb77663100..8382f01a53e3e753a965745a158d4df6398769dd 100644 (file)
@@ -233,7 +233,7 @@ Userspace Interface
 Several sysfs attributes are generated by the Generic Counter interface,
 and reside under the /sys/bus/counter/devices/counterX directory, where
 counterX refers to the respective counter device. Please see
-Documentation/ABI/testing/sys-bus-counter-generic-sysfs for detailed
+Documentation/ABI/testing/sysfs-bus-counter for detailed
 information on each Generic Counter interface sysfs attribute.
 
 Through these sysfs attributes, programs and scripts may interact with
@@ -325,7 +325,7 @@ sysfs attributes, where Y is the unique ID of the respective Count:
 
 For a more detailed breakdown of the available Generic Counter interface
 sysfs attributes, please refer to the
-Documentation/ABI/testing/sys-bus-counter file.
+Documentation/ABI/testing/sysfs-bus-counter file.
 
 The Signals and Counts associated with the Counter device are registered
 to the system as well by the counter_register function. The
index 457c3e0f86d6290f975e5494ecb1cf91dd3d44a7..8fc1ce0bb905de86dd4aa332e1dfc82cdd030339 100644 (file)
@@ -179,8 +179,8 @@ PHY Mappings
 
 In order to get reference to a PHY without help from DeviceTree, the framework
 offers lookups which can be compared to clkdev that allow clk structures to be
-bound to devices. A lookup can be made be made during runtime when a handle to
-the struct phy already exists.
+bound to devices. A lookup can be made during runtime when a handle to the
+struct phy already exists.
 
 The framework offers the following API for registering and unregistering the
 lookups::
diff --git a/Documentation/driver-api/pm/conf.py b/Documentation/driver-api/pm/conf.py
deleted file mode 100644 (file)
index a89fac1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Device Power Management"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'pm.tex', project,
-     'The kernel development community', 'manual'),
-]
index 9267f3fb131f9b5cf0e027ba9bdd9ff51a93d5b8..edbbccda1942e4c84bf5b3dd3e5d3c1bd7959b32 100644 (file)
@@ -13,7 +13,8 @@ a) SMB3 (and SMB3.1.1) missing optional features:
    - T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl
      currently the only two server side copy mechanisms supported)
 
-b) improved sparse file support
+b) improved sparse file support (fiemap and SEEK_HOLE are implemented
+but additional features would be supportable by the protocol).
 
 c) Directory entry caching relies on a 1 second timer, rather than
 using Directory Leases, currently only the root file handle is cached longer
@@ -21,9 +22,13 @@ using Directory Leases, currently only the root file handle is cached longer
 d) quota support (needs minor kernel change since quota calls
 to make it to network filesystems or deviceless filesystems)
 
-e) Additional use cases where we use "compoounding" (e.g. open/query/close
-and open/setinfo/close) to reduce the number of roundtrips, and also
-open to reduce redundant opens (using deferred close and reference counts more).
+e) Additional use cases can be optimized to use "compounding"
+(e.g. open/query/close and open/setinfo/close) to reduce the number
+of roundtrips to the server and improve performance. Various cases
+(stat, statfs, create, unlink, mkdir) already have been improved by
+using compounding but more can be done.  In addition we could significantly
+reduce redundant opens by using deferred close (with handle caching leases)
+and better using reference counters on file handles.
 
 f) Finish inotify support so kde and gnome file list windows
 will autorefresh (partially complete by Asser). Needs minor kernel
@@ -43,18 +48,17 @@ mount or a per server basis to client UIDs or nobody if no mapping
 exists. Also better integration with winbind for resolving SID owners
 
 k) Add tools to take advantage of more smb3 specific ioctls and features
-(passthrough ioctl/fsctl for sending various SMB3 fsctls to the server
-is in progress, and a passthrough query_info call is already implemented
-in cifs.ko to allow smb3 info levels queries to be sent from userspace)
+(passthrough ioctl/fsctl is now implemented in cifs.ko to allow sending
+various SMB3 fsctls and query info and set info calls directly from user space)
+Add tools to make setting various non-POSIX metadata attributes easier
+from tools (e.g. extending what was done in smb-info tool).
 
 l) encrypted file support
 
 m) improved stats gathering tools (perhaps integration with nfsometer?)
 to extend and make easier to use what is currently in /proc/fs/cifs/Stats
 
-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.
+n) Add support for claims based ACLs ("DAC")
 
 o) mount helper GUI (to simplify the various configuration options on mount)
 
@@ -82,6 +86,8 @@ so far).
 w) Add support for additional strong encryption types, and additional spnego
 authentication mechanisms (see MS-SMB2)
 
+x) Finish support for SMB3.1.1 compression
+
 KNOWN BUGS
 ====================================
 See http://bugzilla.samba.org - search on product "CifsVFS" for
diff --git a/Documentation/filesystems/conf.py b/Documentation/filesystems/conf.py
deleted file mode 100644 (file)
index ea44172..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux Filesystems API"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'filesystems.tex', project,
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/gpu/conf.py b/Documentation/gpu/conf.py
deleted file mode 100644 (file)
index 1757b04..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux GPU Driver Developer's Guide"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'gpu.tex', project,
-     'The kernel development community', 'manual'),
-]
index 72da12aa17e58b381a2a8bc78a9deb8d55d7faa8..fe91095210560368165d729d8fe30795ee36c8b0 100644 (file)
@@ -9,7 +9,7 @@ Supported chips:
 
     Addresses scanned: PCI space
 
-    Datasheet: http://support.amd.com/us/Processor_TechDocs/32559.pdf
+    Datasheet: http://www.amd.com/system/files/TechDocs/32559.pdf
 
 Author: Rudolf Marek
 
index 70ae148ec980eed0f462ab45655c3b2064fe4b2a..2df5a3da563c2d2bfefa017eca5c7e84b3c85076 100644 (file)
@@ -111,9 +111,11 @@ needed).
    netlabel/index
    networking/index
    pcmcia/index
+   power/index
    target/index
    timers/index
    watchdog/index
+   virtual/index
    input/index
    hwmon/index
    gpu/index
@@ -143,6 +145,7 @@ implementation.
    arm64/index
    ia64/index
    m68k/index
+   powerpc/index
    riscv/index
    s390/index
    sh/index
diff --git a/Documentation/input/conf.py b/Documentation/input/conf.py
deleted file mode 100644 (file)
index d2352fd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "The Linux input driver subsystem"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'linux-input.tex', project,
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/kernel-hacking/conf.py b/Documentation/kernel-hacking/conf.py
deleted file mode 100644 (file)
index 3d8acf0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Kernel Hacking Guides"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'kernel-hacking.tex', project,
-     'The kernel development community', 'manual'),
-]
index 098107fb7d86bb8f909383c7f2ad9a9664947e95..e93ec6645238286fe29bf359b619e193928181a5 100644 (file)
@@ -82,7 +82,7 @@ itself.  The read lock allows many concurrent readers.  Anything that
 **changes** the list will have to get the write lock.
 
    NOTE! RCU is better for list traversal, but requires careful
-   attention to design detail (see Documentation/RCU/listRCU.txt).
+   attention to design detail (see Documentation/RCU/listRCU.rst).
 
 Also, you cannot "upgrade" a read-lock to a write-lock, so if you at _any_
 time need to do any changes (even if you don't do it every time), you have
@@ -90,7 +90,7 @@ to get the write-lock at the very beginning.
 
    NOTE! We are working hard to remove reader-writer spinlocks in most
    cases, so please don't add a new one without consensus.  (Instead, see
-   Documentation/RCU/rcu.txt for complete information.)
+   Documentation/RCU/rcu.rst for complete information.)
 
 ----
 
diff --git a/Documentation/maintainer/conf.py b/Documentation/maintainer/conf.py
deleted file mode 100644 (file)
index 81e9eb7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Development Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'maintainer.tex', 'Linux Kernel Development Documentation',
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/media/conf.py b/Documentation/media/conf.py
deleted file mode 100644 (file)
index 1f194fc..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-# SPDX-License-Identifier: GPL-2.0
-
-project = 'Linux Media Subsystem Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'media.tex', 'Linux Media Subsystem Documentation',
-     'The kernel development community', 'manual'),
-]
index 045bb8148fe99fcc9d5acca73da0628702b40762..1adbb8a371c71b401a77f2f4857d79964a4a8480 100644 (file)
@@ -548,7 +548,7 @@ There are certain things that the Linux kernel memory barriers do not guarantee:
 
        [*] For information on bus mastering DMA and coherency please read:
 
-           Documentation/PCI/pci.rst
+           Documentation/driver-api/pci/pci.rst
            Documentation/DMA-API-HOWTO.txt
            Documentation/DMA-API.txt
 
diff --git a/Documentation/networking/conf.py b/Documentation/networking/conf.py
deleted file mode 100644 (file)
index 40f69e6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux Networking Documentation"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'networking.tex', project,
-     'The kernel development community', 'manual'),
-]
index 048e5ca44824b4bd7304ee26b5a4c0b7185f828c..0dd3f748239f2858f49ec24590433ea3c8843230 100644 (file)
@@ -424,13 +424,24 @@ Statistics
 Following minimum set of TLS-related statistics should be reported
 by the driver:
 
- * ``rx_tls_decrypted`` - number of successfully decrypted TLS segments
- * ``tx_tls_encrypted`` - number of in-order TLS segments passed to device
-   for encryption
+ * ``rx_tls_decrypted_packets`` - number of successfully decrypted RX packets
+   which were part of a TLS stream.
+ * ``rx_tls_decrypted_bytes`` - number of TLS payload bytes in RX packets
+   which were successfully decrypted.
+ * ``tx_tls_encrypted_packets`` - number of TX packets passed to the device
+   for encryption of their TLS payload.
+ * ``tx_tls_encrypted_bytes`` - number of TLS payload bytes in TX packets
+   passed to the device for encryption.
+ * ``tx_tls_ctx`` - number of TLS TX HW offload contexts added to device for
+   encryption.
  * ``tx_tls_ooo`` - number of TX packets which were part of a TLS stream
-   but did not arrive in the expected order
- * ``tx_tls_drop_no_sync_data`` - number of TX packets dropped because
-   they arrived out of order and associated record could not be found
+   but did not arrive in the expected order.
+ * ``tx_tls_drop_no_sync_data`` - number of TX packets which were part of
+   a TLS stream dropped, because they arrived out of order and associated
+   record could not be found.
+ * ``tx_tls_drop_bypass_req`` - number of TX packets which were part of a TLS
+   stream dropped, because they contain both data that has been encrypted by
+   software and data that expects hardware crypto offload.
 
 Notable corner cases, exceptions and additional requirements
 ============================================================
@@ -495,21 +506,3 @@ Drivers should ignore the changes to TLS the device feature flags.
 These flags will be acted upon accordingly by the core ``ktls`` code.
 TLS device feature flags only control adding of new TLS connection
 offloads, old connections will remain active after flags are cleared.
-
-Known bugs
-==========
-
-skb_orphan() leaks clear text
------------------------------
-
-Currently drivers depend on the :c:member:`sk` member of
-:c:type:`struct sk_buff <sk_buff>` to identify segments requiring
-encryption. Any operation which removes or does not preserve the socket
-association such as :c:func:`skb_orphan` or :c:func:`skb_clone`
-will cause the driver to miss the packets and lead to clear text leaks.
-
-Redirects leak clear text
--------------------------
-
-In the RX direction, if segment has already been decrypted by the device
-and it gets redirected or mirrored - clear text will be transmitted out.
index 949d5dcdd9a348fd646f89c62f604d9d29433d2c..0104830d5075ff255b539c34adabfb6b70f7ea45 100644 (file)
@@ -204,8 +204,8 @@ Ethernet device, which instead of receiving packets from a physical
 media, receives them from user space program and instead of sending 
 packets via physical media sends them to the user space program. 
 
-Let's say that you configured IPX on the tap0, then whenever 
-the kernel sends an IPX packet to tap0, it is passed to the application
+Let's say that you configured IPv6 on the tap0, then whenever
+the kernel sends an IPv6 packet to tap0, it is passed to the application
 (VTun for example). The application encrypts, compresses and sends it to 
 the other side over TCP or UDP. The application on the other side decompresses
 and decrypts the data received and writes the packet to the TAP device, 
index 20415f21e48ae9af964e2f124b6ec2c0525e1258..002e42745263a6416de98bb93532786ab444b5cf 100644 (file)
@@ -1,4 +1,4 @@
-:orphan:
+.. SPDX-License-Identifier: GPL-2.0
 
 ================
 Power Management
diff --git a/Documentation/powerpc/DAWR-POWER9.txt b/Documentation/powerpc/DAWR-POWER9.txt
deleted file mode 100644 (file)
index ecdbb07..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-DAWR issues on POWER9
-============================
-
-On POWER9 the Data Address Watchpoint Register (DAWR) can cause a checkstop
-if it points to cache inhibited (CI) memory. Currently Linux has no way to
-disinguish CI memory when configuring the DAWR, so (for now) the DAWR is
-disabled by this commit:
-
-    commit 9654153158d3e0684a1bdb76dbababdb7111d5a0
-    Author: Michael Neuling <mikey@neuling.org>
-    Date:   Tue Mar 27 15:37:24 2018 +1100
-    powerpc: Disable DAWR in the base POWER9 CPU features
-
-Technical Details:
-============================
-
-DAWR has 6 different ways of being set.
-1) ptrace
-2) h_set_mode(DAWR)
-3) h_set_dabr()
-4) kvmppc_set_one_reg()
-5) xmon
-
-For ptrace, we now advertise zero breakpoints on POWER9 via the
-PPC_PTRACE_GETHWDBGINFO call. This results in GDB falling back to
-software emulation of the watchpoint (which is slow).
-
-h_set_mode(DAWR) and h_set_dabr() will now return an error to the
-guest on a POWER9 host. Current Linux guests ignore this error, so
-they will silently not get the DAWR.
-
-kvmppc_set_one_reg() will store the value in the vcpu but won't
-actually set it on POWER9 hardware. This is done so we don't break
-migration from POWER8 to POWER9, at the cost of silently losing the
-DAWR on the migration.
-
-For xmon, the 'bd' command will return an error on P9.
-
-Consequences for users
-============================
-
-For GDB watchpoints (ie 'watch' command) on POWER9 bare metal , GDB
-will accept the command. Unfortunately since there is no hardware
-support for the watchpoint, GDB will software emulate the watchpoint
-making it run very slowly.
-
-The same will also be true for any guests started on a POWER9
-host. The watchpoint will fail and GDB will fall back to software
-emulation.
-
-If a guest is started on a POWER8 host, GDB will accept the watchpoint
-and configure the hardware to use the DAWR. This will run at full
-speed since it can use the hardware emulation. Unfortunately if this
-guest is migrated to a POWER9 host, the watchpoint will be lost on the
-POWER9. Loads and stores to the watchpoint locations will not be
-trapped in GDB. The watchpoint is remembered, so if the guest is
-migrated back to the POWER8 host, it will start working again.
-
-Force enabling the DAWR
-=============================
-Kernels (since ~v5.2) have an option to force enable the DAWR via:
-
-  echo Y > /sys/kernel/debug/powerpc/dawr_enable_dangerous
-
-This enables the DAWR even on POWER9.
-
-This is a dangerous setting, USE AT YOUR OWN RISK.
-
-Some users may not care about a bad user crashing their box
-(ie. single user/desktop systems) and really want the DAWR.  This
-allows them to force enable DAWR.
-
-This flag can also be used to disable DAWR access. Once this is
-cleared, all DAWR access should be cleared immediately and your
-machine once again safe from crashing.
-
-Userspace may get confused by toggling this. If DAWR is force
-enabled/disabled between getting the number of breakpoints (via
-PTRACE_GETHWDBGINFO) and setting the breakpoint, userspace will get an
-inconsistent view of what's available. Similarly for guests.
-
-For the DAWR to be enabled in a KVM guest, the DAWR needs to be force
-enabled in the host AND the guest. For this reason, this won't work on
-POWERVM as it doesn't allow the HCALL to work. Writes of 'Y' to the
-dawr_enable_dangerous file will fail if the hypervisor doesn't support
-writing the DAWR.
-
-To double check the DAWR is working, run this kernel selftest:
-  tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
-Any errors/failures/skips mean something is wrong.
diff --git a/Documentation/powerpc/bootwrapper.rst b/Documentation/powerpc/bootwrapper.rst
new file mode 100644 (file)
index 0000000..a6292af
--- /dev/null
@@ -0,0 +1,155 @@
+========================
+The PowerPC boot wrapper
+========================
+
+Copyright (C) Secret Lab Technologies Ltd.
+
+PowerPC image targets compresses and wraps the kernel image (vmlinux) with
+a boot wrapper to make it usable by the system firmware.  There is no
+standard PowerPC firmware interface, so the boot wrapper is designed to
+be adaptable for each kind of image that needs to be built.
+
+The boot wrapper can be found in the arch/powerpc/boot/ directory.  The
+Makefile in that directory has targets for all the available image types.
+The different image types are used to support all of the various firmware
+interfaces found on PowerPC platforms.  OpenFirmware is the most commonly
+used firmware type on general purpose PowerPC systems from Apple, IBM and
+others.  U-Boot is typically found on embedded PowerPC hardware, but there
+are a handful of other firmware implementations which are also popular.  Each
+firmware interface requires a different image format.
+
+The boot wrapper is built from the makefile in arch/powerpc/boot/Makefile and
+it uses the wrapper script (arch/powerpc/boot/wrapper) to generate target
+image.  The details of the build system is discussed in the next section.
+Currently, the following image format targets exist:
+
+   ==================== ========================================================
+   cuImage.%:          Backwards compatible uImage for older version of
+                       U-Boot (for versions that don't understand the device
+                       tree).  This image embeds a device tree blob inside
+                       the image.  The boot wrapper, kernel and device tree
+                       are all embedded inside the U-Boot uImage file format
+                       with boot wrapper code that extracts data from the old
+                       bd_info structure and loads the data into the device
+                       tree before jumping into the kernel.
+
+                       Because of the series of #ifdefs found in the
+                       bd_info structure used in the old U-Boot interfaces,
+                       cuImages are platform specific.  Each specific
+                       U-Boot platform has a different platform init file
+                       which populates the embedded device tree with data
+                       from the platform specific bd_info file.  The platform
+                       specific cuImage platform init code can be found in
+                       `arch/powerpc/boot/cuboot.*.c`. Selection of the correct
+                       cuImage init code for a specific board can be found in
+                       the wrapper structure.
+
+   dtbImage.%:         Similar to zImage, except device tree blob is embedded
+                       inside the image instead of provided by firmware.  The
+                       output image file can be either an elf file or a flat
+                       binary depending on the platform.
+
+                       dtbImages are used on systems which do not have an
+                       interface for passing a device tree directly.
+                       dtbImages are similar to simpleImages except that
+                       dtbImages have platform specific code for extracting
+                       data from the board firmware, but simpleImages do not
+                       talk to the firmware at all.
+
+                       PlayStation 3 support uses dtbImage.  So do Embedded
+                       Planet boards using the PlanetCore firmware.  Board
+                       specific initialization code is typically found in a
+                       file named arch/powerpc/boot/<platform>.c; but this
+                       can be overridden by the wrapper script.
+
+   simpleImage.%:      Firmware independent compressed image that does not
+                       depend on any particular firmware interface and embeds
+                       a device tree blob.  This image is a flat binary that
+                       can be loaded to any location in RAM and jumped to.
+                       Firmware cannot pass any configuration data to the
+                       kernel with this image type and it depends entirely on
+                       the embedded device tree for all information.
+
+                       The simpleImage is useful for booting systems with
+                       an unknown firmware interface or for booting from
+                       a debugger when no firmware is present (such as on
+                       the Xilinx Virtex platform).  The only assumption that
+                       simpleImage makes is that RAM is correctly initialized
+                       and that the MMU is either off or has RAM mapped to
+                       base address 0.
+
+                       simpleImage also supports inserting special platform
+                       specific initialization code to the start of the bootup
+                       sequence.  The virtex405 platform uses this feature to
+                       ensure that the cache is invalidated before caching
+                       is enabled.  Platform specific initialization code is
+                       added as part of the wrapper script and is keyed on
+                       the image target name.  For example, all
+                       simpleImage.virtex405-* targets will add the
+                       virtex405-head.S initialization code (This also means
+                       that the dts file for virtex405 targets should be
+                       named (virtex405-<board>.dts).  Search the wrapper
+                       script for 'virtex405' and see the file
+                       arch/powerpc/boot/virtex405-head.S for details.
+
+   treeImage.%;                Image format for used with OpenBIOS firmware found
+                       on some ppc4xx hardware.  This image embeds a device
+                       tree blob inside the image.
+
+   uImage:             Native image format used by U-Boot.  The uImage target
+                       does not add any boot code.  It just wraps a compressed
+                       vmlinux in the uImage data structure.  This image
+                       requires a version of U-Boot that is able to pass
+                       a device tree to the kernel at boot.  If using an older
+                       version of U-Boot, then you need to use a cuImage
+                       instead.
+
+   zImage.%:           Image format which does not embed a device tree.
+                       Used by OpenFirmware and other firmware interfaces
+                       which are able to supply a device tree.  This image
+                       expects firmware to provide the device tree at boot.
+                       Typically, if you have general purpose PowerPC
+                       hardware then you want this image format.
+   ==================== ========================================================
+
+Image types which embed a device tree blob (simpleImage, dtbImage, treeImage,
+and cuImage) all generate the device tree blob from a file in the
+arch/powerpc/boot/dts/ directory.  The Makefile selects the correct device
+tree source based on the name of the target.  Therefore, if the kernel is
+built with 'make treeImage.walnut simpleImage.virtex405-ml403', then the
+build system will use arch/powerpc/boot/dts/walnut.dts to build
+treeImage.walnut and arch/powerpc/boot/dts/virtex405-ml403.dts to build
+the simpleImage.virtex405-ml403.
+
+Two special targets called 'zImage' and 'zImage.initrd' also exist.  These
+targets build all the default images as selected by the kernel configuration.
+Default images are selected by the boot wrapper Makefile
+(arch/powerpc/boot/Makefile) by adding targets to the $image-y variable.  Look
+at the Makefile to see which default image targets are available.
+
+How it is built
+---------------
+arch/powerpc is designed to support multiplatform kernels, which means
+that a single vmlinux image can be booted on many different target boards.
+It also means that the boot wrapper must be able to wrap for many kinds of
+images on a single build.  The design decision was made to not use any
+conditional compilation code (#ifdef, etc) in the boot wrapper source code.
+All of the boot wrapper pieces are buildable at any time regardless of the
+kernel configuration.  Building all the wrapper bits on every kernel build
+also ensures that obscure parts of the wrapper are at the very least compile
+tested in a large variety of environments.
+
+The wrapper is adapted for different image types at link time by linking in
+just the wrapper bits that are appropriate for the image type.  The 'wrapper
+script' (found in arch/powerpc/boot/wrapper) is called by the Makefile and
+is responsible for selecting the correct wrapper bits for the image type.
+The arguments are well documented in the script's comment block, so they
+are not repeated here.  However, it is worth mentioning that the script
+uses the -p (platform) argument as the main method of deciding which wrapper
+bits to compile in.  Look for the large 'case "$platform" in' block in the
+middle of the script.  This is also the place where platform specific fixups
+can be selected by changing the link order.
+
+In particular, care should be taken when working with cuImages.  cuImage
+wrapper bits are very board specific and care should be taken to make sure
+the target you are trying to build is supported by the wrapper bits.
diff --git a/Documentation/powerpc/bootwrapper.txt b/Documentation/powerpc/bootwrapper.txt
deleted file mode 100644 (file)
index d60fced..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-The PowerPC boot wrapper
-------------------------
-Copyright (C) Secret Lab Technologies Ltd.
-
-PowerPC image targets compresses and wraps the kernel image (vmlinux) with
-a boot wrapper to make it usable by the system firmware.  There is no
-standard PowerPC firmware interface, so the boot wrapper is designed to
-be adaptable for each kind of image that needs to be built.
-
-The boot wrapper can be found in the arch/powerpc/boot/ directory.  The
-Makefile in that directory has targets for all the available image types.
-The different image types are used to support all of the various firmware
-interfaces found on PowerPC platforms.  OpenFirmware is the most commonly
-used firmware type on general purpose PowerPC systems from Apple, IBM and
-others.  U-Boot is typically found on embedded PowerPC hardware, but there
-are a handful of other firmware implementations which are also popular.  Each
-firmware interface requires a different image format.
-
-The boot wrapper is built from the makefile in arch/powerpc/boot/Makefile and
-it uses the wrapper script (arch/powerpc/boot/wrapper) to generate target
-image.  The details of the build system is discussed in the next section.
-Currently, the following image format targets exist:
-
-   cuImage.%:          Backwards compatible uImage for older version of
-                       U-Boot (for versions that don't understand the device
-                       tree).  This image embeds a device tree blob inside
-                       the image.  The boot wrapper, kernel and device tree
-                       are all embedded inside the U-Boot uImage file format
-                       with boot wrapper code that extracts data from the old
-                       bd_info structure and loads the data into the device
-                       tree before jumping into the kernel.
-                         Because of the series of #ifdefs found in the
-                       bd_info structure used in the old U-Boot interfaces,
-                       cuImages are platform specific.  Each specific
-                       U-Boot platform has a different platform init file
-                       which populates the embedded device tree with data
-                       from the platform specific bd_info file.  The platform
-                       specific cuImage platform init code can be found in
-                       arch/powerpc/boot/cuboot.*.c.  Selection of the correct
-                       cuImage init code for a specific board can be found in
-                       the wrapper structure.
-   dtbImage.%:         Similar to zImage, except device tree blob is embedded
-                       inside the image instead of provided by firmware.  The
-                       output image file can be either an elf file or a flat
-                       binary depending on the platform.
-                         dtbImages are used on systems which do not have an
-                       interface for passing a device tree directly.
-                       dtbImages are similar to simpleImages except that
-                       dtbImages have platform specific code for extracting
-                       data from the board firmware, but simpleImages do not
-                       talk to the firmware at all.
-                         PlayStation 3 support uses dtbImage.  So do Embedded
-                       Planet boards using the PlanetCore firmware.  Board
-                       specific initialization code is typically found in a
-                       file named arch/powerpc/boot/<platform>.c; but this
-                       can be overridden by the wrapper script.
-   simpleImage.%:      Firmware independent compressed image that does not
-                       depend on any particular firmware interface and embeds
-                       a device tree blob.  This image is a flat binary that
-                       can be loaded to any location in RAM and jumped to.
-                       Firmware cannot pass any configuration data to the
-                       kernel with this image type and it depends entirely on
-                       the embedded device tree for all information.
-                         The simpleImage is useful for booting systems with
-                       an unknown firmware interface or for booting from
-                       a debugger when no firmware is present (such as on
-                       the Xilinx Virtex platform).  The only assumption that
-                       simpleImage makes is that RAM is correctly initialized
-                       and that the MMU is either off or has RAM mapped to
-                       base address 0.
-                         simpleImage also supports inserting special platform
-                       specific initialization code to the start of the bootup
-                       sequence.  The virtex405 platform uses this feature to
-                       ensure that the cache is invalidated before caching
-                       is enabled.  Platform specific initialization code is
-                       added as part of the wrapper script and is keyed on
-                       the image target name.  For example, all
-                       simpleImage.virtex405-* targets will add the
-                       virtex405-head.S initialization code (This also means
-                       that the dts file for virtex405 targets should be
-                       named (virtex405-<board>.dts).  Search the wrapper
-                       script for 'virtex405' and see the file
-                       arch/powerpc/boot/virtex405-head.S for details.
-   treeImage.%;                Image format for used with OpenBIOS firmware found
-                       on some ppc4xx hardware.  This image embeds a device
-                       tree blob inside the image.
-   uImage:             Native image format used by U-Boot.  The uImage target
-                       does not add any boot code.  It just wraps a compressed
-                       vmlinux in the uImage data structure.  This image
-                       requires a version of U-Boot that is able to pass
-                       a device tree to the kernel at boot.  If using an older
-                       version of U-Boot, then you need to use a cuImage
-                       instead.
-   zImage.%:           Image format which does not embed a device tree.
-                       Used by OpenFirmware and other firmware interfaces
-                       which are able to supply a device tree.  This image
-                       expects firmware to provide the device tree at boot.
-                       Typically, if you have general purpose PowerPC
-                       hardware then you want this image format.
-
-Image types which embed a device tree blob (simpleImage, dtbImage, treeImage,
-and cuImage) all generate the device tree blob from a file in the
-arch/powerpc/boot/dts/ directory.  The Makefile selects the correct device
-tree source based on the name of the target.  Therefore, if the kernel is
-built with 'make treeImage.walnut simpleImage.virtex405-ml403', then the
-build system will use arch/powerpc/boot/dts/walnut.dts to build
-treeImage.walnut and arch/powerpc/boot/dts/virtex405-ml403.dts to build
-the simpleImage.virtex405-ml403.
-
-Two special targets called 'zImage' and 'zImage.initrd' also exist.  These
-targets build all the default images as selected by the kernel configuration.
-Default images are selected by the boot wrapper Makefile
-(arch/powerpc/boot/Makefile) by adding targets to the $image-y variable.  Look
-at the Makefile to see which default image targets are available.
-
-How it is built
----------------
-arch/powerpc is designed to support multiplatform kernels, which means
-that a single vmlinux image can be booted on many different target boards.
-It also means that the boot wrapper must be able to wrap for many kinds of
-images on a single build.  The design decision was made to not use any
-conditional compilation code (#ifdef, etc) in the boot wrapper source code.
-All of the boot wrapper pieces are buildable at any time regardless of the
-kernel configuration.  Building all the wrapper bits on every kernel build
-also ensures that obscure parts of the wrapper are at the very least compile
-tested in a large variety of environments.
-
-The wrapper is adapted for different image types at link time by linking in
-just the wrapper bits that are appropriate for the image type.  The 'wrapper
-script' (found in arch/powerpc/boot/wrapper) is called by the Makefile and
-is responsible for selecting the correct wrapper bits for the image type.
-The arguments are well documented in the script's comment block, so they
-are not repeated here.  However, it is worth mentioning that the script
-uses the -p (platform) argument as the main method of deciding which wrapper
-bits to compile in.  Look for the large 'case "$platform" in' block in the
-middle of the script.  This is also the place where platform specific fixups
-can be selected by changing the link order.
-
-In particular, care should be taken when working with cuImages.  cuImage
-wrapper bits are very board specific and care should be taken to make sure
-the target you are trying to build is supported by the wrapper bits.
diff --git a/Documentation/powerpc/cpu_families.rst b/Documentation/powerpc/cpu_families.rst
new file mode 100644 (file)
index 0000000..1e063c5
--- /dev/null
@@ -0,0 +1,222 @@
+============
+CPU Families
+============
+
+This document tries to summarise some of the different cpu families that exist
+and are supported by arch/powerpc.
+
+
+Book3S (aka sPAPR)
+------------------
+
+- Hash MMU
+- Mix of 32 & 64 bit::
+
+   +--------------+                 +----------------+
+   |  Old POWER   | --------------> | RS64 (threads) |
+   +--------------+                 +----------------+
+          |
+          |
+          v
+   +--------------+                 +----------------+      +------+
+   |     601      | --------------> |      603       | ---> | e300 |
+   +--------------+                 +----------------+      +------+
+          |                                 |
+          |                                 |
+          v                                 v
+   +--------------+                 +----------------+      +-------+
+   |     604      |                 |    750 (G3)    | ---> | 750CX |
+   +--------------+                 +----------------+      +-------+
+          |                                 |                   |
+          |                                 |                   |
+          v                                 v                   v
+   +--------------+                 +----------------+      +-------+
+   | 620 (64 bit) |                 |      7400      |      | 750CL |
+   +--------------+                 +----------------+      +-------+
+          |                                 |                   |
+          |                                 |                   |
+          v                                 v                   v
+   +--------------+                 +----------------+      +-------+
+   |  POWER3/630  |                 |      7410      |      | 750FX |
+   +--------------+                 +----------------+      +-------+
+          |                                 |
+          |                                 |
+          v                                 v
+   +--------------+                 +----------------+
+   |   POWER3+    |                 |      7450      |
+   +--------------+                 +----------------+
+          |                                 |
+          |                                 |
+          v                                 v
+   +--------------+                 +----------------+
+   |    POWER4    |                 |      7455      |
+   +--------------+                 +----------------+
+          |                                 |
+          |                                 |
+          v                                 v
+   +--------------+     +-------+   +----------------+
+   |   POWER4+    | --> |  970  |   |      7447      |
+   +--------------+     +-------+   +----------------+
+          |                 |               |
+          |                 |               |
+          v                 v               v
+   +--------------+     +-------+   +----------------+
+   |    POWER5    |     | 970FX |   |      7448      |
+   +--------------+     +-------+   +----------------+
+          |                 |               |
+          |                 |               |
+          v                 v               v
+   +--------------+     +-------+   +----------------+
+   |   POWER5+    |     | 970MP |   |      e600      |
+   +--------------+     +-------+   +----------------+
+          |
+          |
+          v
+   +--------------+
+   |   POWER5++   |
+   +--------------+
+          |
+          |
+          v
+   +--------------+       +-------+
+   |    POWER6    | <-?-> | Cell  |
+   +--------------+       +-------+
+          |
+          |
+          v
+   +--------------+
+   |    POWER7    |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |   POWER7+    |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |    POWER8    |
+   +--------------+
+
+
+   +---------------+
+   | PA6T (64 bit) |
+   +---------------+
+
+
+IBM BookE
+---------
+
+- Software loaded TLB.
+- All 32 bit::
+
+   +--------------+
+   |     401      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |     403      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |     405      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |     440      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+     +----------------+
+   |     450      | --> |      BG/P      |
+   +--------------+     +----------------+
+          |
+          |
+          v
+   +--------------+
+   |     460      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |     476      |
+   +--------------+
+
+
+Motorola/Freescale 8xx
+----------------------
+
+- Software loaded with hardware assist.
+- All 32 bit::
+
+   +-------------+
+   | MPC8xx Core |
+   +-------------+
+
+
+Freescale BookE
+---------------
+
+- Software loaded TLB.
+- e6500 adds HW loaded indirect TLB entries.
+- Mix of 32 & 64 bit::
+
+   +--------------+
+   |     e200     |
+   +--------------+
+
+
+   +--------------------------------+
+   |              e500              |
+   +--------------------------------+
+                   |
+                   |
+                   v
+   +--------------------------------+
+   |             e500v2             |
+   +--------------------------------+
+                   |
+                   |
+                   v
+   +--------------------------------+
+   |        e500mc (Book3e)         |
+   +--------------------------------+
+                   |
+                   |
+                   v
+   +--------------------------------+
+   |          e5500 (64 bit)        |
+   +--------------------------------+
+                   |
+                   |
+                   v
+   +--------------------------------+
+   | e6500 (HW TLB) (Multithreaded) |
+   +--------------------------------+
+
+
+IBM A2 core
+-----------
+
+- Book3E, software loaded TLB + HW loaded indirect TLB entries.
+- 64 bit::
+
+   +--------------+     +----------------+
+   |   A2 core    | --> |      WSP       |
+   +--------------+     +----------------+
+           |
+           |
+           v
+   +--------------+
+   |     BG/Q     |
+   +--------------+
diff --git a/Documentation/powerpc/cpu_families.txt b/Documentation/powerpc/cpu_families.txt
deleted file mode 100644 (file)
index fc08e22..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-CPU Families
-============
-
-This document tries to summarise some of the different cpu families that exist
-and are supported by arch/powerpc.
-
-
-Book3S (aka sPAPR)
-------------------
-
- - Hash MMU
- - Mix of 32 & 64 bit
-
-   +--------------+                 +----------------+
-   |  Old POWER   | --------------> | RS64 (threads) |
-   +--------------+                 +----------------+
-          |
-          |
-          v
-   +--------------+                 +----------------+      +------+
-   |     601      | --------------> |      603       | ---> | e300 |
-   +--------------+                 +----------------+      +------+
-          |                                 |
-          |                                 |
-          v                                 v
-   +--------------+                 +----------------+      +-------+
-   |     604      |                 |    750 (G3)    | ---> | 750CX |
-   +--------------+                 +----------------+      +-------+
-          |                                 |                   |
-          |                                 |                   |
-          v                                 v                   v
-   +--------------+                 +----------------+      +-------+
-   | 620 (64 bit) |                 |      7400      |      | 750CL |
-   +--------------+                 +----------------+      +-------+
-          |                                 |                   |
-          |                                 |                   |
-          v                                 v                   v
-   +--------------+                 +----------------+      +-------+
-   |  POWER3/630  |                 |      7410      |      | 750FX |
-   +--------------+                 +----------------+      +-------+
-          |                                 |
-          |                                 |
-          v                                 v
-   +--------------+                 +----------------+
-   |   POWER3+    |                 |      7450      |
-   +--------------+                 +----------------+
-          |                                 |
-          |                                 |
-          v                                 v
-   +--------------+                 +----------------+
-   |    POWER4    |                 |      7455      |
-   +--------------+                 +----------------+
-          |                                 |
-          |                                 |
-          v                                 v
-   +--------------+     +-------+   +----------------+
-   |   POWER4+    | --> |  970  |   |      7447      |
-   +--------------+     +-------+   +----------------+
-          |                 |               |
-          |                 |               |
-          v                 v               v
-   +--------------+     +-------+   +----------------+
-   |    POWER5    |     | 970FX |   |      7448      |
-   +--------------+     +-------+   +----------------+
-          |                 |               |
-          |                 |               |
-          v                 v               v
-   +--------------+     +-------+   +----------------+
-   |   POWER5+    |     | 970MP |   |      e600      |
-   +--------------+     +-------+   +----------------+
-          |
-          |
-          v
-   +--------------+
-   |   POWER5++   |
-   +--------------+
-          |
-          |
-          v
-   +--------------+       +-------+
-   |    POWER6    | <-?-> | Cell  |
-   +--------------+       +-------+
-          |
-          |
-          v
-   +--------------+
-   |    POWER7    |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |   POWER7+    |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |    POWER8    |
-   +--------------+
-
-
-   +---------------+
-   | PA6T (64 bit) |
-   +---------------+
-
-
-IBM BookE
----------
-
- - Software loaded TLB.
- - All 32 bit
-
-   +--------------+
-   |     401      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |     403      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |     405      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |     440      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+     +----------------+
-   |     450      | --> |      BG/P      |
-   +--------------+     +----------------+
-          |
-          |
-          v
-   +--------------+
-   |     460      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |     476      |
-   +--------------+
-
-
-Motorola/Freescale 8xx
-----------------------
-
- - Software loaded with hardware assist.
- - All 32 bit
-
-   +-------------+
-   | MPC8xx Core |
-   +-------------+
-
-
-Freescale BookE
----------------
-
- - Software loaded TLB.
- - e6500 adds HW loaded indirect TLB entries.
- - Mix of 32 & 64 bit
-
-   +--------------+
-   |     e200     |
-   +--------------+
-
-
-   +--------------------------------+
-   |              e500              |
-   +--------------------------------+
-                   |
-                   |
-                   v
-   +--------------------------------+
-   |             e500v2             |
-   +--------------------------------+
-                   |
-                   |
-                   v
-   +--------------------------------+
-   |        e500mc (Book3e)         |
-   +--------------------------------+
-                   |
-                   |
-                   v
-   +--------------------------------+
-   |          e5500 (64 bit)        |
-   +--------------------------------+
-                   |
-                   |
-                   v
-   +--------------------------------+
-   | e6500 (HW TLB) (Multithreaded) |
-   +--------------------------------+
-
-
-IBM A2 core
------------
-
- - Book3E, software loaded TLB + HW loaded indirect TLB entries.
- - 64 bit
-
-   +--------------+     +----------------+
-   |   A2 core    | --> |      WSP       |
-   +--------------+     +----------------+
-           |
-           |
-           v
-   +--------------+
-   |     BG/Q     |
-   +--------------+
diff --git a/Documentation/powerpc/cpu_features.rst b/Documentation/powerpc/cpu_features.rst
new file mode 100644 (file)
index 0000000..b7bcdd2
--- /dev/null
@@ -0,0 +1,60 @@
+============
+CPU Features
+============
+
+Hollis Blanchard <hollis@austin.ibm.com>
+5 Jun 2002
+
+This document describes the system (including self-modifying code) used in the
+PPC Linux kernel to support a variety of PowerPC CPUs without requiring
+compile-time selection.
+
+Early in the boot process the ppc32 kernel detects the current CPU type and
+chooses a set of features accordingly. Some examples include Altivec support,
+split instruction and data caches, and if the CPU supports the DOZE and NAP
+sleep modes.
+
+Detection of the feature set is simple. A list of processors can be found in
+arch/powerpc/kernel/cputable.c. The PVR register is masked and compared with
+each value in the list. If a match is found, the cpu_features of cur_cpu_spec
+is assigned to the feature bitmask for this processor and a __setup_cpu
+function is called.
+
+C code may test 'cur_cpu_spec[smp_processor_id()]->cpu_features' for a
+particular feature bit. This is done in quite a few places, for example
+in ppc_setup_l2cr().
+
+Implementing cpufeatures in assembly is a little more involved. There are
+several paths that are performance-critical and would suffer if an array
+index, structure dereference, and conditional branch were added. To avoid the
+performance penalty but still allow for runtime (rather than compile-time) CPU
+selection, unused code is replaced by 'nop' instructions. This nop'ing is
+based on CPU 0's capabilities, so a multi-processor system with non-identical
+processors will not work (but such a system would likely have other problems
+anyways).
+
+After detecting the processor type, the kernel patches out sections of code
+that shouldn't be used by writing nop's over it. Using cpufeatures requires
+just 2 macros (found in arch/powerpc/include/asm/cputable.h), as seen in head.S
+transfer_to_handler::
+
+       #ifdef CONFIG_ALTIVEC
+       BEGIN_FTR_SECTION
+               mfspr   r22,SPRN_VRSAVE         /* if G4, save vrsave register value */
+               stw     r22,THREAD_VRSAVE(r23)
+       END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+       #endif /* CONFIG_ALTIVEC */
+
+If CPU 0 supports Altivec, the code is left untouched. If it doesn't, both
+instructions are replaced with nop's.
+
+The END_FTR_SECTION macro has two simpler variations: END_FTR_SECTION_IFSET
+and END_FTR_SECTION_IFCLR. These simply test if a flag is set (in
+cur_cpu_spec[0]->cpu_features) or is cleared, respectively. These two macros
+should be used in the majority of cases.
+
+The END_FTR_SECTION macros are implemented by storing information about this
+code in the '__ftr_fixup' ELF section. When do_cpu_ftr_fixups
+(arch/powerpc/kernel/misc.S) is invoked, it will iterate over the records in
+__ftr_fixup, and if the required feature is not present it will loop writing
+nop's from each BEGIN_FTR_SECTION to END_FTR_SECTION.
diff --git a/Documentation/powerpc/cpu_features.txt b/Documentation/powerpc/cpu_features.txt
deleted file mode 100644 (file)
index ae09df8..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-Hollis Blanchard <hollis@austin.ibm.com>
-5 Jun 2002
-
-This document describes the system (including self-modifying code) used in the
-PPC Linux kernel to support a variety of PowerPC CPUs without requiring
-compile-time selection.
-
-Early in the boot process the ppc32 kernel detects the current CPU type and
-chooses a set of features accordingly. Some examples include Altivec support,
-split instruction and data caches, and if the CPU supports the DOZE and NAP
-sleep modes.
-
-Detection of the feature set is simple. A list of processors can be found in
-arch/powerpc/kernel/cputable.c. The PVR register is masked and compared with
-each value in the list. If a match is found, the cpu_features of cur_cpu_spec
-is assigned to the feature bitmask for this processor and a __setup_cpu
-function is called.
-
-C code may test 'cur_cpu_spec[smp_processor_id()]->cpu_features' for a
-particular feature bit. This is done in quite a few places, for example
-in ppc_setup_l2cr().
-
-Implementing cpufeatures in assembly is a little more involved. There are
-several paths that are performance-critical and would suffer if an array
-index, structure dereference, and conditional branch were added. To avoid the
-performance penalty but still allow for runtime (rather than compile-time) CPU
-selection, unused code is replaced by 'nop' instructions. This nop'ing is
-based on CPU 0's capabilities, so a multi-processor system with non-identical
-processors will not work (but such a system would likely have other problems
-anyways).
-
-After detecting the processor type, the kernel patches out sections of code
-that shouldn't be used by writing nop's over it. Using cpufeatures requires
-just 2 macros (found in arch/powerpc/include/asm/cputable.h), as seen in head.S
-transfer_to_handler:
-
-       #ifdef CONFIG_ALTIVEC
-       BEGIN_FTR_SECTION
-               mfspr   r22,SPRN_VRSAVE         /* if G4, save vrsave register value */
-               stw     r22,THREAD_VRSAVE(r23)
-       END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-       #endif /* CONFIG_ALTIVEC */
-
-If CPU 0 supports Altivec, the code is left untouched. If it doesn't, both
-instructions are replaced with nop's.
-
-The END_FTR_SECTION macro has two simpler variations: END_FTR_SECTION_IFSET
-and END_FTR_SECTION_IFCLR. These simply test if a flag is set (in
-cur_cpu_spec[0]->cpu_features) or is cleared, respectively. These two macros
-should be used in the majority of cases.
-
-The END_FTR_SECTION macros are implemented by storing information about this
-code in the '__ftr_fixup' ELF section. When do_cpu_ftr_fixups
-(arch/powerpc/kernel/misc.S) is invoked, it will iterate over the records in
-__ftr_fixup, and if the required feature is not present it will loop writing
-nop's from each BEGIN_FTR_SECTION to END_FTR_SECTION.
diff --git a/Documentation/powerpc/cxl.rst b/Documentation/powerpc/cxl.rst
new file mode 100644 (file)
index 0000000..920546d
--- /dev/null
@@ -0,0 +1,467 @@
+====================================
+Coherent Accelerator Interface (CXL)
+====================================
+
+Introduction
+============
+
+    The coherent accelerator interface is designed to allow the
+    coherent connection of accelerators (FPGAs and other devices) to a
+    POWER system. These devices need to adhere to the Coherent
+    Accelerator Interface Architecture (CAIA).
+
+    IBM refers to this as the Coherent Accelerator Processor Interface
+    or CAPI. In the kernel it's referred to by the name CXL to avoid
+    confusion with the ISDN CAPI subsystem.
+
+    Coherent in this context means that the accelerator and CPUs can
+    both access system memory directly and with the same effective
+    addresses.
+
+
+Hardware overview
+=================
+
+    ::
+
+         POWER8/9             FPGA
+       +----------+        +---------+
+       |          |        |         |
+       |   CPU    |        |   AFU   |
+       |          |        |         |
+       |          |        |         |
+       |          |        |         |
+       +----------+        +---------+
+       |   PHB    |        |         |
+       |   +------+        |   PSL   |
+       |   | CAPP |<------>|         |
+       +---+------+  PCIE  +---------+
+
+    The POWER8/9 chip has a Coherently Attached Processor Proxy (CAPP)
+    unit which is part of the PCIe Host Bridge (PHB). This is managed
+    by Linux by calls into OPAL. Linux doesn't directly program the
+    CAPP.
+
+    The FPGA (or coherently attached device) consists of two parts.
+    The POWER Service Layer (PSL) and the Accelerator Function Unit
+    (AFU). The AFU is used to implement specific functionality behind
+    the PSL. The PSL, among other things, provides memory address
+    translation services to allow each AFU direct access to userspace
+    memory.
+
+    The AFU is the core part of the accelerator (eg. the compression,
+    crypto etc function). The kernel has no knowledge of the function
+    of the AFU. Only userspace interacts directly with the AFU.
+
+    The PSL provides the translation and interrupt services that the
+    AFU needs. This is what the kernel interacts with. For example, if
+    the AFU needs to read a particular effective address, it sends
+    that address to the PSL, the PSL then translates it, fetches the
+    data from memory and returns it to the AFU. If the PSL has a
+    translation miss, it interrupts the kernel and the kernel services
+    the fault. The context to which this fault is serviced is based on
+    who owns that acceleration function.
+
+    - POWER8 and PSL Version 8 are compliant to the CAIA Version 1.0.
+    - POWER9 and PSL Version 9 are compliant to the CAIA Version 2.0.
+
+    This PSL Version 9 provides new features such as:
+
+    * Interaction with the nest MMU on the P9 chip.
+    * Native DMA support.
+    * Supports sending ASB_Notify messages for host thread wakeup.
+    * Supports Atomic operations.
+    * etc.
+
+    Cards with a PSL9 won't work on a POWER8 system and cards with a
+    PSL8 won't work on a POWER9 system.
+
+AFU Modes
+=========
+
+    There are two programming modes supported by the AFU. Dedicated
+    and AFU directed. AFU may support one or both modes.
+
+    When using dedicated mode only one MMU context is supported. In
+    this mode, only one userspace process can use the accelerator at
+    time.
+
+    When using AFU directed mode, up to 16K simultaneous contexts can
+    be supported. This means up to 16K simultaneous userspace
+    applications may use the accelerator (although specific AFUs may
+    support fewer). In this mode, the AFU sends a 16 bit context ID
+    with each of its requests. This tells the PSL which context is
+    associated with each operation. If the PSL can't translate an
+    operation, the ID can also be accessed by the kernel so it can
+    determine the userspace context associated with an operation.
+
+
+MMIO space
+==========
+
+    A portion of the accelerator MMIO space can be directly mapped
+    from the AFU to userspace. Either the whole space can be mapped or
+    just a per context portion. The hardware is self describing, hence
+    the kernel can determine the offset and size of the per context
+    portion.
+
+
+Interrupts
+==========
+
+    AFUs may generate interrupts that are destined for userspace. These
+    are received by the kernel as hardware interrupts and passed onto
+    userspace by a read syscall documented below.
+
+    Data storage faults and error interrupts are handled by the kernel
+    driver.
+
+
+Work Element Descriptor (WED)
+=============================
+
+    The WED is a 64-bit parameter passed to the AFU when a context is
+    started. Its format is up to the AFU hence the kernel has no
+    knowledge of what it represents. Typically it will be the
+    effective address of a work queue or status block where the AFU
+    and userspace can share control and status information.
+
+
+
+
+User API
+========
+
+1. AFU character devices
+
+    For AFUs operating in AFU directed mode, two character device
+    files will be created. /dev/cxl/afu0.0m will correspond to a
+    master context and /dev/cxl/afu0.0s will correspond to a slave
+    context. Master contexts have access to the full MMIO space an
+    AFU provides. Slave contexts have access to only the per process
+    MMIO space an AFU provides.
+
+    For AFUs operating in dedicated process mode, the driver will
+    only create a single character device per AFU called
+    /dev/cxl/afu0.0d. This will have access to the entire MMIO space
+    that the AFU provides (like master contexts in AFU directed).
+
+    The types described below are defined in include/uapi/misc/cxl.h
+
+    The following file operations are supported on both slave and
+    master devices.
+
+    A userspace library libcxl is available here:
+
+       https://github.com/ibm-capi/libcxl
+
+    This provides a C interface to this kernel API.
+
+open
+----
+
+    Opens the device and allocates a file descriptor to be used with
+    the rest of the API.
+
+    A dedicated mode AFU only has one context and only allows the
+    device to be opened once.
+
+    An AFU directed mode AFU can have many contexts, the device can be
+    opened once for each context that is available.
+
+    When all available contexts are allocated the open call will fail
+    and return -ENOSPC.
+
+    Note:
+         IRQs need to be allocated for each context, which may limit
+          the number of contexts that can be created, and therefore
+          how many times the device can be opened. The POWER8 CAPP
+          supports 2040 IRQs and 3 are used by the kernel, so 2037 are
+          left. If 1 IRQ is needed per context, then only 2037
+          contexts can be allocated. If 4 IRQs are needed per context,
+          then only 2037/4 = 509 contexts can be allocated.
+
+
+ioctl
+-----
+
+    CXL_IOCTL_START_WORK:
+        Starts the AFU context and associates it with the current
+        process. Once this ioctl is successfully executed, all memory
+        mapped into this process is accessible to this AFU context
+        using the same effective addresses. No additional calls are
+        required to map/unmap memory. The AFU memory context will be
+        updated as userspace allocates and frees memory. This ioctl
+        returns once the AFU context is started.
+
+        Takes a pointer to a struct cxl_ioctl_start_work
+
+            ::
+
+                struct cxl_ioctl_start_work {
+                        __u64 flags;
+                        __u64 work_element_descriptor;
+                        __u64 amr;
+                        __s16 num_interrupts;
+                        __s16 reserved1;
+                        __s32 reserved2;
+                        __u64 reserved3;
+                        __u64 reserved4;
+                        __u64 reserved5;
+                        __u64 reserved6;
+                };
+
+            flags:
+                Indicates which optional fields in the structure are
+                valid.
+
+            work_element_descriptor:
+                The Work Element Descriptor (WED) is a 64-bit argument
+                defined by the AFU. Typically this is an effective
+                address pointing to an AFU specific structure
+                describing what work to perform.
+
+            amr:
+                Authority Mask Register (AMR), same as the powerpc
+                AMR. This field is only used by the kernel when the
+                corresponding CXL_START_WORK_AMR value is specified in
+                flags. If not specified the kernel will use a default
+                value of 0.
+
+            num_interrupts:
+                Number of userspace interrupts to request. This field
+                is only used by the kernel when the corresponding
+                CXL_START_WORK_NUM_IRQS value is specified in flags.
+                If not specified the minimum number required by the
+                AFU will be allocated. The min and max number can be
+                obtained from sysfs.
+
+            reserved fields:
+                For ABI padding and future extensions
+
+    CXL_IOCTL_GET_PROCESS_ELEMENT:
+        Get the current context id, also known as the process element.
+        The value is returned from the kernel as a __u32.
+
+
+mmap
+----
+
+    An AFU may have an MMIO space to facilitate communication with the
+    AFU. If it does, the MMIO space can be accessed via mmap. The size
+    and contents of this area are specific to the particular AFU. The
+    size can be discovered via sysfs.
+
+    In AFU directed mode, master contexts are allowed to map all of
+    the MMIO space and slave contexts are allowed to only map the per
+    process MMIO space associated with the context. In dedicated
+    process mode the entire MMIO space can always be mapped.
+
+    This mmap call must be done after the START_WORK ioctl.
+
+    Care should be taken when accessing MMIO space. Only 32 and 64-bit
+    accesses are supported by POWER8. Also, the AFU will be designed
+    with a specific endianness, so all MMIO accesses should consider
+    endianness (recommend endian(3) variants like: le64toh(),
+    be64toh() etc). These endian issues equally apply to shared memory
+    queues the WED may describe.
+
+
+read
+----
+
+    Reads events from the AFU. Blocks if no events are pending
+    (unless O_NONBLOCK is supplied). Returns -EIO in the case of an
+    unrecoverable error or if the card is removed.
+
+    read() will always return an integral number of events.
+
+    The buffer passed to read() must be at least 4K bytes.
+
+    The result of the read will be a buffer of one or more events,
+    each event is of type struct cxl_event, of varying size::
+
+            struct cxl_event {
+                    struct cxl_event_header header;
+                    union {
+                            struct cxl_event_afu_interrupt irq;
+                            struct cxl_event_data_storage fault;
+                            struct cxl_event_afu_error afu_error;
+                    };
+            };
+
+    The struct cxl_event_header is defined as
+
+        ::
+
+            struct cxl_event_header {
+                    __u16 type;
+                    __u16 size;
+                    __u16 process_element;
+                    __u16 reserved1;
+            };
+
+        type:
+            This defines the type of event. The type determines how
+            the rest of the event is structured. These types are
+            described below and defined by enum cxl_event_type.
+
+        size:
+            This is the size of the event in bytes including the
+            struct cxl_event_header. The start of the next event can
+            be found at this offset from the start of the current
+            event.
+
+        process_element:
+            Context ID of the event.
+
+        reserved field:
+            For future extensions and padding.
+
+    If the event type is CXL_EVENT_AFU_INTERRUPT then the event
+    structure is defined as
+
+        ::
+
+            struct cxl_event_afu_interrupt {
+                    __u16 flags;
+                    __u16 irq; /* Raised AFU interrupt number */
+                    __u32 reserved1;
+            };
+
+        flags:
+            These flags indicate which optional fields are present
+            in this struct. Currently all fields are mandatory.
+
+        irq:
+            The IRQ number sent by the AFU.
+
+        reserved field:
+            For future extensions and padding.
+
+    If the event type is CXL_EVENT_DATA_STORAGE then the event
+    structure is defined as
+
+        ::
+
+            struct cxl_event_data_storage {
+                    __u16 flags;
+                    __u16 reserved1;
+                    __u32 reserved2;
+                    __u64 addr;
+                    __u64 dsisr;
+                    __u64 reserved3;
+            };
+
+        flags:
+            These flags indicate which optional fields are present in
+            this struct. Currently all fields are mandatory.
+
+        address:
+            The address that the AFU unsuccessfully attempted to
+            access. Valid accesses will be handled transparently by the
+            kernel but invalid accesses will generate this event.
+
+        dsisr:
+            This field gives information on the type of fault. It is a
+            copy of the DSISR from the PSL hardware when the address
+            fault occurred. The form of the DSISR is as defined in the
+            CAIA.
+
+        reserved fields:
+            For future extensions
+
+    If the event type is CXL_EVENT_AFU_ERROR then the event structure
+    is defined as
+
+        ::
+
+            struct cxl_event_afu_error {
+                    __u16 flags;
+                    __u16 reserved1;
+                    __u32 reserved2;
+                    __u64 error;
+            };
+
+        flags:
+            These flags indicate which optional fields are present in
+            this struct. Currently all fields are Mandatory.
+
+        error:
+            Error status from the AFU. Defined by the AFU.
+
+        reserved fields:
+            For future extensions and padding
+
+
+2. Card character device (powerVM guest only)
+
+    In a powerVM guest, an extra character device is created for the
+    card. The device is only used to write (flash) a new image on the
+    FPGA accelerator. Once the image is written and verified, the
+    device tree is updated and the card is reset to reload the updated
+    image.
+
+open
+----
+
+    Opens the device and allocates a file descriptor to be used with
+    the rest of the API. The device can only be opened once.
+
+ioctl
+-----
+
+CXL_IOCTL_DOWNLOAD_IMAGE / CXL_IOCTL_VALIDATE_IMAGE:
+    Starts and controls flashing a new FPGA image. Partial
+    reconfiguration is not supported (yet), so the image must contain
+    a copy of the PSL and AFU(s). Since an image can be quite large,
+    the caller may have to iterate, splitting the image in smaller
+    chunks.
+
+    Takes a pointer to a struct cxl_adapter_image::
+
+        struct cxl_adapter_image {
+            __u64 flags;
+            __u64 data;
+            __u64 len_data;
+            __u64 len_image;
+            __u64 reserved1;
+            __u64 reserved2;
+            __u64 reserved3;
+            __u64 reserved4;
+        };
+
+    flags:
+        These flags indicate which optional fields are present in
+        this struct. Currently all fields are mandatory.
+
+    data:
+        Pointer to a buffer with part of the image to write to the
+        card.
+
+    len_data:
+        Size of the buffer pointed to by data.
+
+    len_image:
+        Full size of the image.
+
+
+Sysfs Class
+===========
+
+    A cxl sysfs class is added under /sys/class/cxl to facilitate
+    enumeration and tuning of the accelerators. Its layout is
+    described in Documentation/ABI/testing/sysfs-class-cxl
+
+
+Udev rules
+==========
+
+    The following udev rules could be used to create a symlink to the
+    most logical chardev to use in any programming mode (afuX.Yd for
+    dedicated, afuX.Ys for afu directed), since the API is virtually
+    identical for each::
+
+       SUBSYSTEM=="cxl", ATTRS{mode}=="dedicated_process", SYMLINK="cxl/%b"
+       SUBSYSTEM=="cxl", ATTRS{mode}=="afu_directed", \
+                         KERNEL=="afu[0-9]*.[0-9]*s", SYMLINK="cxl/%b"
diff --git a/Documentation/powerpc/cxl.txt b/Documentation/powerpc/cxl.txt
deleted file mode 100644 (file)
index c5e8d50..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-Coherent Accelerator Interface (CXL)
-====================================
-
-Introduction
-============
-
-    The coherent accelerator interface is designed to allow the
-    coherent connection of accelerators (FPGAs and other devices) to a
-    POWER system. These devices need to adhere to the Coherent
-    Accelerator Interface Architecture (CAIA).
-
-    IBM refers to this as the Coherent Accelerator Processor Interface
-    or CAPI. In the kernel it's referred to by the name CXL to avoid
-    confusion with the ISDN CAPI subsystem.
-
-    Coherent in this context means that the accelerator and CPUs can
-    both access system memory directly and with the same effective
-    addresses.
-
-
-Hardware overview
-=================
-
-         POWER8/9             FPGA
-       +----------+        +---------+
-       |          |        |         |
-       |   CPU    |        |   AFU   |
-       |          |        |         |
-       |          |        |         |
-       |          |        |         |
-       +----------+        +---------+
-       |   PHB    |        |         |
-       |   +------+        |   PSL   |
-       |   | CAPP |<------>|         |
-       +---+------+  PCIE  +---------+
-
-    The POWER8/9 chip has a Coherently Attached Processor Proxy (CAPP)
-    unit which is part of the PCIe Host Bridge (PHB). This is managed
-    by Linux by calls into OPAL. Linux doesn't directly program the
-    CAPP.
-
-    The FPGA (or coherently attached device) consists of two parts.
-    The POWER Service Layer (PSL) and the Accelerator Function Unit
-    (AFU). The AFU is used to implement specific functionality behind
-    the PSL. The PSL, among other things, provides memory address
-    translation services to allow each AFU direct access to userspace
-    memory.
-
-    The AFU is the core part of the accelerator (eg. the compression,
-    crypto etc function). The kernel has no knowledge of the function
-    of the AFU. Only userspace interacts directly with the AFU.
-
-    The PSL provides the translation and interrupt services that the
-    AFU needs. This is what the kernel interacts with. For example, if
-    the AFU needs to read a particular effective address, it sends
-    that address to the PSL, the PSL then translates it, fetches the
-    data from memory and returns it to the AFU. If the PSL has a
-    translation miss, it interrupts the kernel and the kernel services
-    the fault. The context to which this fault is serviced is based on
-    who owns that acceleration function.
-
-    POWER8 <-----> PSL Version 8 is compliant to the CAIA Version 1.0.
-    POWER9 <-----> PSL Version 9 is compliant to the CAIA Version 2.0.
-    This PSL Version 9 provides new features such as:
-    * Interaction with the nest MMU on the P9 chip.
-    * Native DMA support.
-    * Supports sending ASB_Notify messages for host thread wakeup.
-    * Supports Atomic operations.
-    * ....
-
-    Cards with a PSL9 won't work on a POWER8 system and cards with a
-    PSL8 won't work on a POWER9 system.
-
-AFU Modes
-=========
-
-    There are two programming modes supported by the AFU. Dedicated
-    and AFU directed. AFU may support one or both modes.
-
-    When using dedicated mode only one MMU context is supported. In
-    this mode, only one userspace process can use the accelerator at
-    time.
-
-    When using AFU directed mode, up to 16K simultaneous contexts can
-    be supported. This means up to 16K simultaneous userspace
-    applications may use the accelerator (although specific AFUs may
-    support fewer). In this mode, the AFU sends a 16 bit context ID
-    with each of its requests. This tells the PSL which context is
-    associated with each operation. If the PSL can't translate an
-    operation, the ID can also be accessed by the kernel so it can
-    determine the userspace context associated with an operation.
-
-
-MMIO space
-==========
-
-    A portion of the accelerator MMIO space can be directly mapped
-    from the AFU to userspace. Either the whole space can be mapped or
-    just a per context portion. The hardware is self describing, hence
-    the kernel can determine the offset and size of the per context
-    portion.
-
-
-Interrupts
-==========
-
-    AFUs may generate interrupts that are destined for userspace. These
-    are received by the kernel as hardware interrupts and passed onto
-    userspace by a read syscall documented below.
-
-    Data storage faults and error interrupts are handled by the kernel
-    driver.
-
-
-Work Element Descriptor (WED)
-=============================
-
-    The WED is a 64-bit parameter passed to the AFU when a context is
-    started. Its format is up to the AFU hence the kernel has no
-    knowledge of what it represents. Typically it will be the
-    effective address of a work queue or status block where the AFU
-    and userspace can share control and status information.
-
-
-
-
-User API
-========
-
-1. AFU character devices
-
-    For AFUs operating in AFU directed mode, two character device
-    files will be created. /dev/cxl/afu0.0m will correspond to a
-    master context and /dev/cxl/afu0.0s will correspond to a slave
-    context. Master contexts have access to the full MMIO space an
-    AFU provides. Slave contexts have access to only the per process
-    MMIO space an AFU provides.
-
-    For AFUs operating in dedicated process mode, the driver will
-    only create a single character device per AFU called
-    /dev/cxl/afu0.0d. This will have access to the entire MMIO space
-    that the AFU provides (like master contexts in AFU directed).
-
-    The types described below are defined in include/uapi/misc/cxl.h
-
-    The following file operations are supported on both slave and
-    master devices.
-
-    A userspace library libcxl is available here:
-       https://github.com/ibm-capi/libcxl
-    This provides a C interface to this kernel API.
-
-open
-----
-
-    Opens the device and allocates a file descriptor to be used with
-    the rest of the API.
-
-    A dedicated mode AFU only has one context and only allows the
-    device to be opened once.
-
-    An AFU directed mode AFU can have many contexts, the device can be
-    opened once for each context that is available.
-
-    When all available contexts are allocated the open call will fail
-    and return -ENOSPC.
-
-    Note: IRQs need to be allocated for each context, which may limit
-          the number of contexts that can be created, and therefore
-          how many times the device can be opened. The POWER8 CAPP
-          supports 2040 IRQs and 3 are used by the kernel, so 2037 are
-          left. If 1 IRQ is needed per context, then only 2037
-          contexts can be allocated. If 4 IRQs are needed per context,
-          then only 2037/4 = 509 contexts can be allocated.
-
-
-ioctl
------
-
-    CXL_IOCTL_START_WORK:
-        Starts the AFU context and associates it with the current
-        process. Once this ioctl is successfully executed, all memory
-        mapped into this process is accessible to this AFU context
-        using the same effective addresses. No additional calls are
-        required to map/unmap memory. The AFU memory context will be
-        updated as userspace allocates and frees memory. This ioctl
-        returns once the AFU context is started.
-
-        Takes a pointer to a struct cxl_ioctl_start_work:
-
-                struct cxl_ioctl_start_work {
-                        __u64 flags;
-                        __u64 work_element_descriptor;
-                        __u64 amr;
-                        __s16 num_interrupts;
-                        __s16 reserved1;
-                        __s32 reserved2;
-                        __u64 reserved3;
-                        __u64 reserved4;
-                        __u64 reserved5;
-                        __u64 reserved6;
-                };
-
-            flags:
-                Indicates which optional fields in the structure are
-                valid.
-
-            work_element_descriptor:
-                The Work Element Descriptor (WED) is a 64-bit argument
-                defined by the AFU. Typically this is an effective
-                address pointing to an AFU specific structure
-                describing what work to perform.
-
-            amr:
-                Authority Mask Register (AMR), same as the powerpc
-                AMR. This field is only used by the kernel when the
-                corresponding CXL_START_WORK_AMR value is specified in
-                flags. If not specified the kernel will use a default
-                value of 0.
-
-            num_interrupts:
-                Number of userspace interrupts to request. This field
-                is only used by the kernel when the corresponding
-                CXL_START_WORK_NUM_IRQS value is specified in flags.
-                If not specified the minimum number required by the
-                AFU will be allocated. The min and max number can be
-                obtained from sysfs.
-
-            reserved fields:
-                For ABI padding and future extensions
-
-    CXL_IOCTL_GET_PROCESS_ELEMENT:
-        Get the current context id, also known as the process element.
-        The value is returned from the kernel as a __u32.
-
-
-mmap
-----
-
-    An AFU may have an MMIO space to facilitate communication with the
-    AFU. If it does, the MMIO space can be accessed via mmap. The size
-    and contents of this area are specific to the particular AFU. The
-    size can be discovered via sysfs.
-
-    In AFU directed mode, master contexts are allowed to map all of
-    the MMIO space and slave contexts are allowed to only map the per
-    process MMIO space associated with the context. In dedicated
-    process mode the entire MMIO space can always be mapped.
-
-    This mmap call must be done after the START_WORK ioctl.
-
-    Care should be taken when accessing MMIO space. Only 32 and 64-bit
-    accesses are supported by POWER8. Also, the AFU will be designed
-    with a specific endianness, so all MMIO accesses should consider
-    endianness (recommend endian(3) variants like: le64toh(),
-    be64toh() etc). These endian issues equally apply to shared memory
-    queues the WED may describe.
-
-
-read
-----
-
-    Reads events from the AFU. Blocks if no events are pending
-    (unless O_NONBLOCK is supplied). Returns -EIO in the case of an
-    unrecoverable error or if the card is removed.
-
-    read() will always return an integral number of events.
-
-    The buffer passed to read() must be at least 4K bytes.
-
-    The result of the read will be a buffer of one or more events,
-    each event is of type struct cxl_event, of varying size.
-
-            struct cxl_event {
-                    struct cxl_event_header header;
-                    union {
-                            struct cxl_event_afu_interrupt irq;
-                            struct cxl_event_data_storage fault;
-                            struct cxl_event_afu_error afu_error;
-                    };
-            };
-
-    The struct cxl_event_header is defined as:
-
-            struct cxl_event_header {
-                    __u16 type;
-                    __u16 size;
-                    __u16 process_element;
-                    __u16 reserved1;
-            };
-
-        type:
-            This defines the type of event. The type determines how
-            the rest of the event is structured. These types are
-            described below and defined by enum cxl_event_type.
-
-        size:
-            This is the size of the event in bytes including the
-            struct cxl_event_header. The start of the next event can
-            be found at this offset from the start of the current
-            event.
-
-        process_element:
-            Context ID of the event.
-
-        reserved field:
-            For future extensions and padding.
-
-    If the event type is CXL_EVENT_AFU_INTERRUPT then the event
-    structure is defined as:
-
-            struct cxl_event_afu_interrupt {
-                    __u16 flags;
-                    __u16 irq; /* Raised AFU interrupt number */
-                    __u32 reserved1;
-            };
-
-        flags:
-            These flags indicate which optional fields are present
-            in this struct. Currently all fields are mandatory.
-
-        irq:
-            The IRQ number sent by the AFU.
-
-        reserved field:
-            For future extensions and padding.
-
-    If the event type is CXL_EVENT_DATA_STORAGE then the event
-    structure is defined as:
-
-            struct cxl_event_data_storage {
-                    __u16 flags;
-                    __u16 reserved1;
-                    __u32 reserved2;
-                    __u64 addr;
-                    __u64 dsisr;
-                    __u64 reserved3;
-            };
-
-        flags:
-            These flags indicate which optional fields are present in
-            this struct. Currently all fields are mandatory.
-
-        address:
-            The address that the AFU unsuccessfully attempted to
-            access. Valid accesses will be handled transparently by the
-            kernel but invalid accesses will generate this event.
-
-        dsisr:
-            This field gives information on the type of fault. It is a
-            copy of the DSISR from the PSL hardware when the address
-            fault occurred. The form of the DSISR is as defined in the
-            CAIA.
-
-        reserved fields:
-            For future extensions
-
-    If the event type is CXL_EVENT_AFU_ERROR then the event structure
-    is defined as:
-
-            struct cxl_event_afu_error {
-                    __u16 flags;
-                    __u16 reserved1;
-                    __u32 reserved2;
-                    __u64 error;
-            };
-
-        flags:
-            These flags indicate which optional fields are present in
-            this struct. Currently all fields are Mandatory.
-
-        error:
-            Error status from the AFU. Defined by the AFU.
-
-        reserved fields:
-            For future extensions and padding
-
-
-2. Card character device (powerVM guest only)
-
-    In a powerVM guest, an extra character device is created for the
-    card. The device is only used to write (flash) a new image on the
-    FPGA accelerator. Once the image is written and verified, the
-    device tree is updated and the card is reset to reload the updated
-    image.
-
-open
-----
-
-    Opens the device and allocates a file descriptor to be used with
-    the rest of the API. The device can only be opened once.
-
-ioctl
------
-
-CXL_IOCTL_DOWNLOAD_IMAGE:
-CXL_IOCTL_VALIDATE_IMAGE:
-    Starts and controls flashing a new FPGA image. Partial
-    reconfiguration is not supported (yet), so the image must contain
-    a copy of the PSL and AFU(s). Since an image can be quite large,
-    the caller may have to iterate, splitting the image in smaller
-    chunks.
-
-    Takes a pointer to a struct cxl_adapter_image:
-        struct cxl_adapter_image {
-            __u64 flags;
-            __u64 data;
-            __u64 len_data;
-            __u64 len_image;
-            __u64 reserved1;
-            __u64 reserved2;
-            __u64 reserved3;
-            __u64 reserved4;
-        };
-
-    flags:
-        These flags indicate which optional fields are present in
-        this struct. Currently all fields are mandatory.
-
-    data:
-        Pointer to a buffer with part of the image to write to the
-        card.
-
-    len_data:
-        Size of the buffer pointed to by data.
-
-    len_image:
-        Full size of the image.
-
-
-Sysfs Class
-===========
-
-    A cxl sysfs class is added under /sys/class/cxl to facilitate
-    enumeration and tuning of the accelerators. Its layout is
-    described in Documentation/ABI/testing/sysfs-class-cxl
-
-
-Udev rules
-==========
-
-    The following udev rules could be used to create a symlink to the
-    most logical chardev to use in any programming mode (afuX.Yd for
-    dedicated, afuX.Ys for afu directed), since the API is virtually
-    identical for each:
-
-       SUBSYSTEM=="cxl", ATTRS{mode}=="dedicated_process", SYMLINK="cxl/%b"
-       SUBSYSTEM=="cxl", ATTRS{mode}=="afu_directed", \
-                         KERNEL=="afu[0-9]*.[0-9]*s", SYMLINK="cxl/%b"
diff --git a/Documentation/powerpc/cxlflash.rst b/Documentation/powerpc/cxlflash.rst
new file mode 100644 (file)
index 0000000..cea6793
--- /dev/null
@@ -0,0 +1,433 @@
+================================
+Coherent Accelerator (CXL) Flash
+================================
+
+Introduction
+============
+
+    The IBM Power architecture provides support for CAPI (Coherent
+    Accelerator Power Interface), which is available to certain PCIe slots
+    on Power 8 systems. CAPI can be thought of as a special tunneling
+    protocol through PCIe that allow PCIe adapters to look like special
+    purpose co-processors which can read or write an application's
+    memory and generate page faults. As a result, the host interface to
+    an adapter running in CAPI mode does not require the data buffers to
+    be mapped to the device's memory (IOMMU bypass) nor does it require
+    memory to be pinned.
+
+    On Linux, Coherent Accelerator (CXL) kernel services present CAPI
+    devices as a PCI device by implementing a virtual PCI host bridge.
+    This abstraction simplifies the infrastructure and programming
+    model, allowing for drivers to look similar to other native PCI
+    device drivers.
+
+    CXL provides a mechanism by which user space applications can
+    directly talk to a device (network or storage) bypassing the typical
+    kernel/device driver stack. The CXL Flash Adapter Driver enables a
+    user space application direct access to Flash storage.
+
+    The CXL Flash Adapter Driver is a kernel module that sits in the
+    SCSI stack as a low level device driver (below the SCSI disk and
+    protocol drivers) for the IBM CXL Flash Adapter. This driver is
+    responsible for the initialization of the adapter, setting up the
+    special path for user space access, and performing error recovery. It
+    communicates directly the Flash Accelerator Functional Unit (AFU)
+    as described in Documentation/powerpc/cxl.rst.
+
+    The cxlflash driver supports two, mutually exclusive, modes of
+    operation at the device (LUN) level:
+
+        - Any flash device (LUN) can be configured to be accessed as a
+          regular disk device (i.e.: /dev/sdc). This is the default mode.
+
+        - Any flash device (LUN) can be configured to be accessed from
+          user space with a special block library. This mode further
+          specifies the means of accessing the device and provides for
+          either raw access to the entire LUN (referred to as direct
+          or physical LUN access) or access to a kernel/AFU-mediated
+          partition of the LUN (referred to as virtual LUN access). The
+          segmentation of a disk device into virtual LUNs is assisted
+          by special translation services provided by the Flash AFU.
+
+Overview
+========
+
+    The Coherent Accelerator Interface Architecture (CAIA) introduces a
+    concept of a master context. A master typically has special privileges
+    granted to it by the kernel or hypervisor allowing it to perform AFU
+    wide management and control. The master may or may not be involved
+    directly in each user I/O, but at the minimum is involved in the
+    initial setup before the user application is allowed to send requests
+    directly to the AFU.
+
+    The CXL Flash Adapter Driver establishes a master context with the
+    AFU. It uses memory mapped I/O (MMIO) for this control and setup. The
+    Adapter Problem Space Memory Map looks like this::
+
+                     +-------------------------------+
+                     |    512 * 64 KB User MMIO      |
+                     |        (per context)          |
+                     |       User Accessible         |
+                     +-------------------------------+
+                     |    512 * 128 B per context    |
+                     |    Provisioning and Control   |
+                     |   Trusted Process accessible  |
+                     +-------------------------------+
+                     |         64 KB Global          |
+                     |   Trusted Process accessible  |
+                     +-------------------------------+
+
+    This driver configures itself into the SCSI software stack as an
+    adapter driver. The driver is the only entity that is considered a
+    Trusted Process to program the Provisioning and Control and Global
+    areas in the MMIO Space shown above.  The master context driver
+    discovers all LUNs attached to the CXL Flash adapter and instantiates
+    scsi block devices (/dev/sdb, /dev/sdc etc.) for each unique LUN
+    seen from each path.
+
+    Once these scsi block devices are instantiated, an application
+    written to a specification provided by the block library may get
+    access to the Flash from user space (without requiring a system call).
+
+    This master context driver also provides a series of ioctls for this
+    block library to enable this user space access.  The driver supports
+    two modes for accessing the block device.
+
+    The first mode is called a virtual mode. In this mode a single scsi
+    block device (/dev/sdb) may be carved up into any number of distinct
+    virtual LUNs. The virtual LUNs may be resized as long as the sum of
+    the sizes of all the virtual LUNs, along with the meta-data associated
+    with it does not exceed the physical capacity.
+
+    The second mode is called the physical mode. In this mode a single
+    block device (/dev/sdb) may be opened directly by the block library
+    and the entire space for the LUN is available to the application.
+
+    Only the physical mode provides persistence of the data.  i.e. The
+    data written to the block device will survive application exit and
+    restart and also reboot. The virtual LUNs do not persist (i.e. do
+    not survive after the application terminates or the system reboots).
+
+
+Block library API
+=================
+
+    Applications intending to get access to the CXL Flash from user
+    space should use the block library, as it abstracts the details of
+    interfacing directly with the cxlflash driver that are necessary for
+    performing administrative actions (i.e.: setup, tear down, resize).
+    The block library can be thought of as a 'user' of services,
+    implemented as IOCTLs, that are provided by the cxlflash driver
+    specifically for devices (LUNs) operating in user space access
+    mode. While it is not a requirement that applications understand
+    the interface between the block library and the cxlflash driver,
+    a high-level overview of each supported service (IOCTL) is provided
+    below.
+
+    The block library can be found on GitHub:
+    http://github.com/open-power/capiflash
+
+
+CXL Flash Driver LUN IOCTLs
+===========================
+
+    Users, such as the block library, that wish to interface with a flash
+    device (LUN) via user space access need to use the services provided
+    by the cxlflash driver. As these services are implemented as ioctls,
+    a file descriptor handle must first be obtained in order to establish
+    the communication channel between a user and the kernel.  This file
+    descriptor is obtained by opening the device special file associated
+    with the scsi disk device (/dev/sdb) that was created during LUN
+    discovery. As per the location of the cxlflash driver within the
+    SCSI protocol stack, this open is actually not seen by the cxlflash
+    driver. Upon successful open, the user receives a file descriptor
+    (herein referred to as fd1) that should be used for issuing the
+    subsequent ioctls listed below.
+
+    The structure definitions for these IOCTLs are available in:
+    uapi/scsi/cxlflash_ioctl.h
+
+DK_CXLFLASH_ATTACH
+------------------
+
+    This ioctl obtains, initializes, and starts a context using the CXL
+    kernel services. These services specify a context id (u16) by which
+    to uniquely identify the context and its allocated resources. The
+    services additionally provide a second file descriptor (herein
+    referred to as fd2) that is used by the block library to initiate
+    memory mapped I/O (via mmap()) to the CXL flash device and poll for
+    completion events. This file descriptor is intentionally installed by
+    this driver and not the CXL kernel services to allow for intermediary
+    notification and access in the event of a non-user-initiated close(),
+    such as a killed process. This design point is described in further
+    detail in the description for the DK_CXLFLASH_DETACH ioctl.
+
+    There are a few important aspects regarding the "tokens" (context id
+    and fd2) that are provided back to the user:
+
+        - These tokens are only valid for the process under which they
+          were created. The child of a forked process cannot continue
+          to use the context id or file descriptor created by its parent
+          (see DK_CXLFLASH_VLUN_CLONE for further details).
+
+        - These tokens are only valid for the lifetime of the context and
+          the process under which they were created. Once either is
+          destroyed, the tokens are to be considered stale and subsequent
+          usage will result in errors.
+
+       - A valid adapter file descriptor (fd2 >= 0) is only returned on
+         the initial attach for a context. Subsequent attaches to an
+         existing context (DK_CXLFLASH_ATTACH_REUSE_CONTEXT flag present)
+         do not provide the adapter file descriptor as it was previously
+         made known to the application.
+
+        - When a context is no longer needed, the user shall detach from
+          the context via the DK_CXLFLASH_DETACH ioctl. When this ioctl
+         returns with a valid adapter file descriptor and the return flag
+         DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
+         close the adapter file descriptor following a successful detach.
+
+       - When this ioctl returns with a valid fd2 and the return flag
+         DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
+         close fd2 in the following circumstances:
+
+               + Following a successful detach of the last user of the context
+               + Following a successful recovery on the context's original fd2
+               + In the child process of a fork(), following a clone ioctl,
+                 on the fd2 associated with the source context
+
+        - At any time, a close on fd2 will invalidate the tokens. Applications
+         should exercise caution to only close fd2 when appropriate (outlined
+         in the previous bullet) to avoid premature loss of I/O.
+
+DK_CXLFLASH_USER_DIRECT
+-----------------------
+    This ioctl is responsible for transitioning the LUN to direct
+    (physical) mode access and configuring the AFU for direct access from
+    user space on a per-context basis. Additionally, the block size and
+    last logical block address (LBA) are returned to the user.
+
+    As mentioned previously, when operating in user space access mode,
+    LUNs may be accessed in whole or in part. Only one mode is allowed
+    at a time and if one mode is active (outstanding references exist),
+    requests to use the LUN in a different mode are denied.
+
+    The AFU is configured for direct access from user space by adding an
+    entry to the AFU's resource handle table. The index of the entry is
+    treated as a resource handle that is returned to the user. The user
+    is then able to use the handle to reference the LUN during I/O.
+
+DK_CXLFLASH_USER_VIRTUAL
+------------------------
+    This ioctl is responsible for transitioning the LUN to virtual mode
+    of access and configuring the AFU for virtual access from user space
+    on a per-context basis. Additionally, the block size and last logical
+    block address (LBA) are returned to the user.
+
+    As mentioned previously, when operating in user space access mode,
+    LUNs may be accessed in whole or in part. Only one mode is allowed
+    at a time and if one mode is active (outstanding references exist),
+    requests to use the LUN in a different mode are denied.
+
+    The AFU is configured for virtual access from user space by adding
+    an entry to the AFU's resource handle table. The index of the entry
+    is treated as a resource handle that is returned to the user. The
+    user is then able to use the handle to reference the LUN during I/O.
+
+    By default, the virtual LUN is created with a size of 0. The user
+    would need to use the DK_CXLFLASH_VLUN_RESIZE ioctl to adjust the grow
+    the virtual LUN to a desired size. To avoid having to perform this
+    resize for the initial creation of the virtual LUN, the user has the
+    option of specifying a size as part of the DK_CXLFLASH_USER_VIRTUAL
+    ioctl, such that when success is returned to the user, the
+    resource handle that is provided is already referencing provisioned
+    storage. This is reflected by the last LBA being a non-zero value.
+
+    When a LUN is accessible from more than one port, this ioctl will
+    return with the DK_CXLFLASH_ALL_PORTS_ACTIVE return flag set. This
+    provides the user with a hint that I/O can be retried in the event
+    of an I/O error as the LUN can be reached over multiple paths.
+
+DK_CXLFLASH_VLUN_RESIZE
+-----------------------
+    This ioctl is responsible for resizing a previously created virtual
+    LUN and will fail if invoked upon a LUN that is not in virtual
+    mode. Upon success, an updated last LBA is returned to the user
+    indicating the new size of the virtual LUN associated with the
+    resource handle.
+
+    The partitioning of virtual LUNs is jointly mediated by the cxlflash
+    driver and the AFU. An allocation table is kept for each LUN that is
+    operating in the virtual mode and used to program a LUN translation
+    table that the AFU references when provided with a resource handle.
+
+    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
+    In addition to returning a failure to user, cxlflash will also schedule
+    an asynchronous AFU reset. Should the user choose to retry the operation,
+    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
+    can either retry the operation or treat it as a failure.
+
+DK_CXLFLASH_RELEASE
+-------------------
+    This ioctl is responsible for releasing a previously obtained
+    reference to either a physical or virtual LUN. This can be
+    thought of as the inverse of the DK_CXLFLASH_USER_DIRECT or
+    DK_CXLFLASH_USER_VIRTUAL ioctls. Upon success, the resource handle
+    is no longer valid and the entry in the resource handle table is
+    made available to be used again.
+
+    As part of the release process for virtual LUNs, the virtual LUN
+    is first resized to 0 to clear out and free the translation tables
+    associated with the virtual LUN reference.
+
+DK_CXLFLASH_DETACH
+------------------
+    This ioctl is responsible for unregistering a context with the
+    cxlflash driver and release outstanding resources that were
+    not explicitly released via the DK_CXLFLASH_RELEASE ioctl. Upon
+    success, all "tokens" which had been provided to the user from the
+    DK_CXLFLASH_ATTACH onward are no longer valid.
+
+    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
+    attach, the application _must_ close the fd2 associated with the context
+    following the detach of the final user of the context.
+
+DK_CXLFLASH_VLUN_CLONE
+----------------------
+    This ioctl is responsible for cloning a previously created
+    context to a more recently created context. It exists solely to
+    support maintaining user space access to storage after a process
+    forks. Upon success, the child process (which invoked the ioctl)
+    will have access to the same LUNs via the same resource handle(s)
+    as the parent, but under a different context.
+
+    Context sharing across processes is not supported with CXL and
+    therefore each fork must be met with establishing a new context
+    for the child process. This ioctl simplifies the state management
+    and playback required by a user in such a scenario. When a process
+    forks, child process can clone the parents context by first creating
+    a context (via DK_CXLFLASH_ATTACH) and then using this ioctl to
+    perform the clone from the parent to the child.
+
+    The clone itself is fairly simple. The resource handle and lun
+    translation tables are copied from the parent context to the child's
+    and then synced with the AFU.
+
+    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
+    attach, the application _must_ close the fd2 associated with the source
+    context (still resident/accessible in the parent process) following the
+    clone. This is to avoid a stale entry in the file descriptor table of the
+    child process.
+
+    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
+    In addition to returning a failure to user, cxlflash will also schedule
+    an asynchronous AFU reset. Should the user choose to retry the operation,
+    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
+    can either retry the operation or treat it as a failure.
+
+DK_CXLFLASH_VERIFY
+------------------
+    This ioctl is used to detect various changes such as the capacity of
+    the disk changing, the number of LUNs visible changing, etc. In cases
+    where the changes affect the application (such as a LUN resize), the
+    cxlflash driver will report the changed state to the application.
+
+    The user calls in when they want to validate that a LUN hasn't been
+    changed in response to a check condition. As the user is operating out
+    of band from the kernel, they will see these types of events without
+    the kernel's knowledge. When encountered, the user's architected
+    behavior is to call in to this ioctl, indicating what they want to
+    verify and passing along any appropriate information. For now, only
+    verifying a LUN change (ie: size different) with sense data is
+    supported.
+
+DK_CXLFLASH_RECOVER_AFU
+-----------------------
+    This ioctl is used to drive recovery (if such an action is warranted)
+    of a specified user context. Any state associated with the user context
+    is re-established upon successful recovery.
+
+    User contexts are put into an error condition when the device needs to
+    be reset or is terminating. Users are notified of this error condition
+    by seeing all 0xF's on an MMIO read. Upon encountering this, the
+    architected behavior for a user is to call into this ioctl to recover
+    their context. A user may also call into this ioctl at any time to
+    check if the device is operating normally. If a failure is returned
+    from this ioctl, the user is expected to gracefully clean up their
+    context via release/detach ioctls. Until they do, the context they
+    hold is not relinquished. The user may also optionally exit the process
+    at which time the context/resources they held will be freed as part of
+    the release fop.
+
+    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
+    attach, the application _must_ unmap and close the fd2 associated with the
+    original context following this ioctl returning success and indicating that
+    the context was recovered (DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET).
+
+DK_CXLFLASH_MANAGE_LUN
+----------------------
+    This ioctl is used to switch a LUN from a mode where it is available
+    for file-system access (legacy), to a mode where it is set aside for
+    exclusive user space access (superpipe). In case a LUN is visible
+    across multiple ports and adapters, this ioctl is used to uniquely
+    identify each LUN by its World Wide Node Name (WWNN).
+
+
+CXL Flash Driver Host IOCTLs
+============================
+
+    Each host adapter instance that is supported by the cxlflash driver
+    has a special character device associated with it to enable a set of
+    host management function. These character devices are hosted in a
+    class dedicated for cxlflash and can be accessed via `/dev/cxlflash/*`.
+
+    Applications can be written to perform various functions using the
+    host ioctl APIs below.
+
+    The structure definitions for these IOCTLs are available in:
+    uapi/scsi/cxlflash_ioctl.h
+
+HT_CXLFLASH_LUN_PROVISION
+-------------------------
+    This ioctl is used to create and delete persistent LUNs on cxlflash
+    devices that lack an external LUN management interface. It is only
+    valid when used with AFUs that support the LUN provision capability.
+
+    When sufficient space is available, LUNs can be created by specifying
+    the target port to host the LUN and a desired size in 4K blocks. Upon
+    success, the LUN ID and WWID of the created LUN will be returned and
+    the SCSI bus can be scanned to detect the change in LUN topology. Note
+    that partial allocations are not supported. Should a creation fail due
+    to a space issue, the target port can be queried for its current LUN
+    geometry.
+
+    To remove a LUN, the device must first be disassociated from the Linux
+    SCSI subsystem. The LUN deletion can then be initiated by specifying a
+    target port and LUN ID. Upon success, the LUN geometry associated with
+    the port will be updated to reflect new number of provisioned LUNs and
+    available capacity.
+
+    To query the LUN geometry of a port, the target port is specified and
+    upon success, the following information is presented:
+
+        - Maximum number of provisioned LUNs allowed for the port
+        - Current number of provisioned LUNs for the port
+        - Maximum total capacity of provisioned LUNs for the port (4K blocks)
+        - Current total capacity of provisioned LUNs for the port (4K blocks)
+
+    With this information, the number of available LUNs and capacity can be
+    can be calculated.
+
+HT_CXLFLASH_AFU_DEBUG
+---------------------
+    This ioctl is used to debug AFUs by supporting a command pass-through
+    interface. It is only valid when used with AFUs that support the AFU
+    debug capability.
+
+    With exception of buffer management, AFU debug commands are opaque to
+    cxlflash and treated as pass-through. For debug commands that do require
+    data transfer, the user supplies an adequately sized data buffer and must
+    specify the data transfer direction with respect to the host. There is a
+    maximum transfer size of 256K imposed. Note that partial read completions
+    are not supported - when errors are experienced with a host read data
+    transfer, the data buffer is not copied back to the user.
diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.txt
deleted file mode 100644 (file)
index a64bdaa..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-Introduction
-============
-
-    The IBM Power architecture provides support for CAPI (Coherent
-    Accelerator Power Interface), which is available to certain PCIe slots
-    on Power 8 systems. CAPI can be thought of as a special tunneling
-    protocol through PCIe that allow PCIe adapters to look like special
-    purpose co-processors which can read or write an application's
-    memory and generate page faults. As a result, the host interface to
-    an adapter running in CAPI mode does not require the data buffers to
-    be mapped to the device's memory (IOMMU bypass) nor does it require
-    memory to be pinned.
-
-    On Linux, Coherent Accelerator (CXL) kernel services present CAPI
-    devices as a PCI device by implementing a virtual PCI host bridge.
-    This abstraction simplifies the infrastructure and programming
-    model, allowing for drivers to look similar to other native PCI
-    device drivers.
-
-    CXL provides a mechanism by which user space applications can
-    directly talk to a device (network or storage) bypassing the typical
-    kernel/device driver stack. The CXL Flash Adapter Driver enables a
-    user space application direct access to Flash storage.
-
-    The CXL Flash Adapter Driver is a kernel module that sits in the
-    SCSI stack as a low level device driver (below the SCSI disk and
-    protocol drivers) for the IBM CXL Flash Adapter. This driver is
-    responsible for the initialization of the adapter, setting up the
-    special path for user space access, and performing error recovery. It
-    communicates directly the Flash Accelerator Functional Unit (AFU)
-    as described in Documentation/powerpc/cxl.txt.
-
-    The cxlflash driver supports two, mutually exclusive, modes of
-    operation at the device (LUN) level:
-
-        - Any flash device (LUN) can be configured to be accessed as a
-          regular disk device (i.e.: /dev/sdc). This is the default mode.
-
-        - Any flash device (LUN) can be configured to be accessed from
-          user space with a special block library. This mode further
-          specifies the means of accessing the device and provides for
-          either raw access to the entire LUN (referred to as direct
-          or physical LUN access) or access to a kernel/AFU-mediated
-          partition of the LUN (referred to as virtual LUN access). The
-          segmentation of a disk device into virtual LUNs is assisted
-          by special translation services provided by the Flash AFU.
-
-Overview
-========
-
-    The Coherent Accelerator Interface Architecture (CAIA) introduces a
-    concept of a master context. A master typically has special privileges
-    granted to it by the kernel or hypervisor allowing it to perform AFU
-    wide management and control. The master may or may not be involved
-    directly in each user I/O, but at the minimum is involved in the
-    initial setup before the user application is allowed to send requests
-    directly to the AFU.
-
-    The CXL Flash Adapter Driver establishes a master context with the
-    AFU. It uses memory mapped I/O (MMIO) for this control and setup. The
-    Adapter Problem Space Memory Map looks like this:
-
-                     +-------------------------------+
-                     |    512 * 64 KB User MMIO      |
-                     |        (per context)          |
-                     |       User Accessible         |
-                     +-------------------------------+
-                     |    512 * 128 B per context    |
-                     |    Provisioning and Control   |
-                     |   Trusted Process accessible  |
-                     +-------------------------------+
-                     |         64 KB Global          |
-                     |   Trusted Process accessible  |
-                     +-------------------------------+
-
-    This driver configures itself into the SCSI software stack as an
-    adapter driver. The driver is the only entity that is considered a
-    Trusted Process to program the Provisioning and Control and Global
-    areas in the MMIO Space shown above.  The master context driver
-    discovers all LUNs attached to the CXL Flash adapter and instantiates
-    scsi block devices (/dev/sdb, /dev/sdc etc.) for each unique LUN
-    seen from each path.
-
-    Once these scsi block devices are instantiated, an application
-    written to a specification provided by the block library may get
-    access to the Flash from user space (without requiring a system call).
-
-    This master context driver also provides a series of ioctls for this
-    block library to enable this user space access.  The driver supports
-    two modes for accessing the block device.
-
-    The first mode is called a virtual mode. In this mode a single scsi
-    block device (/dev/sdb) may be carved up into any number of distinct
-    virtual LUNs. The virtual LUNs may be resized as long as the sum of
-    the sizes of all the virtual LUNs, along with the meta-data associated
-    with it does not exceed the physical capacity.
-
-    The second mode is called the physical mode. In this mode a single
-    block device (/dev/sdb) may be opened directly by the block library
-    and the entire space for the LUN is available to the application.
-
-    Only the physical mode provides persistence of the data.  i.e. The
-    data written to the block device will survive application exit and
-    restart and also reboot. The virtual LUNs do not persist (i.e. do
-    not survive after the application terminates or the system reboots).
-
-
-Block library API
-=================
-
-    Applications intending to get access to the CXL Flash from user
-    space should use the block library, as it abstracts the details of
-    interfacing directly with the cxlflash driver that are necessary for
-    performing administrative actions (i.e.: setup, tear down, resize).
-    The block library can be thought of as a 'user' of services,
-    implemented as IOCTLs, that are provided by the cxlflash driver
-    specifically for devices (LUNs) operating in user space access
-    mode. While it is not a requirement that applications understand
-    the interface between the block library and the cxlflash driver,
-    a high-level overview of each supported service (IOCTL) is provided
-    below.
-
-    The block library can be found on GitHub:
-    http://github.com/open-power/capiflash
-
-
-CXL Flash Driver LUN IOCTLs
-===========================
-
-    Users, such as the block library, that wish to interface with a flash
-    device (LUN) via user space access need to use the services provided
-    by the cxlflash driver. As these services are implemented as ioctls,
-    a file descriptor handle must first be obtained in order to establish
-    the communication channel between a user and the kernel.  This file
-    descriptor is obtained by opening the device special file associated
-    with the scsi disk device (/dev/sdb) that was created during LUN
-    discovery. As per the location of the cxlflash driver within the
-    SCSI protocol stack, this open is actually not seen by the cxlflash
-    driver. Upon successful open, the user receives a file descriptor
-    (herein referred to as fd1) that should be used for issuing the
-    subsequent ioctls listed below.
-
-    The structure definitions for these IOCTLs are available in:
-    uapi/scsi/cxlflash_ioctl.h
-
-DK_CXLFLASH_ATTACH
-------------------
-
-    This ioctl obtains, initializes, and starts a context using the CXL
-    kernel services. These services specify a context id (u16) by which
-    to uniquely identify the context and its allocated resources. The
-    services additionally provide a second file descriptor (herein
-    referred to as fd2) that is used by the block library to initiate
-    memory mapped I/O (via mmap()) to the CXL flash device and poll for
-    completion events. This file descriptor is intentionally installed by
-    this driver and not the CXL kernel services to allow for intermediary
-    notification and access in the event of a non-user-initiated close(),
-    such as a killed process. This design point is described in further
-    detail in the description for the DK_CXLFLASH_DETACH ioctl.
-
-    There are a few important aspects regarding the "tokens" (context id
-    and fd2) that are provided back to the user:
-
-        - These tokens are only valid for the process under which they
-          were created. The child of a forked process cannot continue
-          to use the context id or file descriptor created by its parent
-          (see DK_CXLFLASH_VLUN_CLONE for further details).
-
-        - These tokens are only valid for the lifetime of the context and
-          the process under which they were created. Once either is
-          destroyed, the tokens are to be considered stale and subsequent
-          usage will result in errors.
-
-       - A valid adapter file descriptor (fd2 >= 0) is only returned on
-         the initial attach for a context. Subsequent attaches to an
-         existing context (DK_CXLFLASH_ATTACH_REUSE_CONTEXT flag present)
-         do not provide the adapter file descriptor as it was previously
-         made known to the application.
-
-        - When a context is no longer needed, the user shall detach from
-          the context via the DK_CXLFLASH_DETACH ioctl. When this ioctl
-         returns with a valid adapter file descriptor and the return flag
-         DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
-         close the adapter file descriptor following a successful detach.
-
-       - When this ioctl returns with a valid fd2 and the return flag
-         DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
-         close fd2 in the following circumstances:
-
-               + Following a successful detach of the last user of the context
-               + Following a successful recovery on the context's original fd2
-               + In the child process of a fork(), following a clone ioctl,
-                 on the fd2 associated with the source context
-
-        - At any time, a close on fd2 will invalidate the tokens. Applications
-         should exercise caution to only close fd2 when appropriate (outlined
-         in the previous bullet) to avoid premature loss of I/O.
-
-DK_CXLFLASH_USER_DIRECT
------------------------
-    This ioctl is responsible for transitioning the LUN to direct
-    (physical) mode access and configuring the AFU for direct access from
-    user space on a per-context basis. Additionally, the block size and
-    last logical block address (LBA) are returned to the user.
-
-    As mentioned previously, when operating in user space access mode,
-    LUNs may be accessed in whole or in part. Only one mode is allowed
-    at a time and if one mode is active (outstanding references exist),
-    requests to use the LUN in a different mode are denied.
-
-    The AFU is configured for direct access from user space by adding an
-    entry to the AFU's resource handle table. The index of the entry is
-    treated as a resource handle that is returned to the user. The user
-    is then able to use the handle to reference the LUN during I/O.
-
-DK_CXLFLASH_USER_VIRTUAL
-------------------------
-    This ioctl is responsible for transitioning the LUN to virtual mode
-    of access and configuring the AFU for virtual access from user space
-    on a per-context basis. Additionally, the block size and last logical
-    block address (LBA) are returned to the user.
-
-    As mentioned previously, when operating in user space access mode,
-    LUNs may be accessed in whole or in part. Only one mode is allowed
-    at a time and if one mode is active (outstanding references exist),
-    requests to use the LUN in a different mode are denied.
-
-    The AFU is configured for virtual access from user space by adding
-    an entry to the AFU's resource handle table. The index of the entry
-    is treated as a resource handle that is returned to the user. The
-    user is then able to use the handle to reference the LUN during I/O.
-
-    By default, the virtual LUN is created with a size of 0. The user
-    would need to use the DK_CXLFLASH_VLUN_RESIZE ioctl to adjust the grow
-    the virtual LUN to a desired size. To avoid having to perform this
-    resize for the initial creation of the virtual LUN, the user has the
-    option of specifying a size as part of the DK_CXLFLASH_USER_VIRTUAL
-    ioctl, such that when success is returned to the user, the
-    resource handle that is provided is already referencing provisioned
-    storage. This is reflected by the last LBA being a non-zero value.
-
-    When a LUN is accessible from more than one port, this ioctl will
-    return with the DK_CXLFLASH_ALL_PORTS_ACTIVE return flag set. This
-    provides the user with a hint that I/O can be retried in the event
-    of an I/O error as the LUN can be reached over multiple paths.
-
-DK_CXLFLASH_VLUN_RESIZE
------------------------
-    This ioctl is responsible for resizing a previously created virtual
-    LUN and will fail if invoked upon a LUN that is not in virtual
-    mode. Upon success, an updated last LBA is returned to the user
-    indicating the new size of the virtual LUN associated with the
-    resource handle.
-
-    The partitioning of virtual LUNs is jointly mediated by the cxlflash
-    driver and the AFU. An allocation table is kept for each LUN that is
-    operating in the virtual mode and used to program a LUN translation
-    table that the AFU references when provided with a resource handle.
-
-    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
-    In addition to returning a failure to user, cxlflash will also schedule
-    an asynchronous AFU reset. Should the user choose to retry the operation,
-    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
-    can either retry the operation or treat it as a failure.
-
-DK_CXLFLASH_RELEASE
--------------------
-    This ioctl is responsible for releasing a previously obtained
-    reference to either a physical or virtual LUN. This can be
-    thought of as the inverse of the DK_CXLFLASH_USER_DIRECT or
-    DK_CXLFLASH_USER_VIRTUAL ioctls. Upon success, the resource handle
-    is no longer valid and the entry in the resource handle table is
-    made available to be used again.
-
-    As part of the release process for virtual LUNs, the virtual LUN
-    is first resized to 0 to clear out and free the translation tables
-    associated with the virtual LUN reference.
-
-DK_CXLFLASH_DETACH
-------------------
-    This ioctl is responsible for unregistering a context with the
-    cxlflash driver and release outstanding resources that were
-    not explicitly released via the DK_CXLFLASH_RELEASE ioctl. Upon
-    success, all "tokens" which had been provided to the user from the
-    DK_CXLFLASH_ATTACH onward are no longer valid.
-
-    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
-    attach, the application _must_ close the fd2 associated with the context
-    following the detach of the final user of the context.
-
-DK_CXLFLASH_VLUN_CLONE
-----------------------
-    This ioctl is responsible for cloning a previously created
-    context to a more recently created context. It exists solely to
-    support maintaining user space access to storage after a process
-    forks. Upon success, the child process (which invoked the ioctl)
-    will have access to the same LUNs via the same resource handle(s)
-    as the parent, but under a different context.
-
-    Context sharing across processes is not supported with CXL and
-    therefore each fork must be met with establishing a new context
-    for the child process. This ioctl simplifies the state management
-    and playback required by a user in such a scenario. When a process
-    forks, child process can clone the parents context by first creating
-    a context (via DK_CXLFLASH_ATTACH) and then using this ioctl to
-    perform the clone from the parent to the child.
-
-    The clone itself is fairly simple. The resource handle and lun
-    translation tables are copied from the parent context to the child's
-    and then synced with the AFU.
-
-    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
-    attach, the application _must_ close the fd2 associated with the source
-    context (still resident/accessible in the parent process) following the
-    clone. This is to avoid a stale entry in the file descriptor table of the
-    child process.
-
-    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
-    In addition to returning a failure to user, cxlflash will also schedule
-    an asynchronous AFU reset. Should the user choose to retry the operation,
-    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
-    can either retry the operation or treat it as a failure.
-
-DK_CXLFLASH_VERIFY
-------------------
-    This ioctl is used to detect various changes such as the capacity of
-    the disk changing, the number of LUNs visible changing, etc. In cases
-    where the changes affect the application (such as a LUN resize), the
-    cxlflash driver will report the changed state to the application.
-
-    The user calls in when they want to validate that a LUN hasn't been
-    changed in response to a check condition. As the user is operating out
-    of band from the kernel, they will see these types of events without
-    the kernel's knowledge. When encountered, the user's architected
-    behavior is to call in to this ioctl, indicating what they want to
-    verify and passing along any appropriate information. For now, only
-    verifying a LUN change (ie: size different) with sense data is
-    supported.
-
-DK_CXLFLASH_RECOVER_AFU
------------------------
-    This ioctl is used to drive recovery (if such an action is warranted)
-    of a specified user context. Any state associated with the user context
-    is re-established upon successful recovery.
-
-    User contexts are put into an error condition when the device needs to
-    be reset or is terminating. Users are notified of this error condition
-    by seeing all 0xF's on an MMIO read. Upon encountering this, the
-    architected behavior for a user is to call into this ioctl to recover
-    their context. A user may also call into this ioctl at any time to
-    check if the device is operating normally. If a failure is returned
-    from this ioctl, the user is expected to gracefully clean up their
-    context via release/detach ioctls. Until they do, the context they
-    hold is not relinquished. The user may also optionally exit the process
-    at which time the context/resources they held will be freed as part of
-    the release fop.
-
-    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
-    attach, the application _must_ unmap and close the fd2 associated with the
-    original context following this ioctl returning success and indicating that
-    the context was recovered (DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET).
-
-DK_CXLFLASH_MANAGE_LUN
-----------------------
-    This ioctl is used to switch a LUN from a mode where it is available
-    for file-system access (legacy), to a mode where it is set aside for
-    exclusive user space access (superpipe). In case a LUN is visible
-    across multiple ports and adapters, this ioctl is used to uniquely
-    identify each LUN by its World Wide Node Name (WWNN).
-
-
-CXL Flash Driver Host IOCTLs
-============================
-
-    Each host adapter instance that is supported by the cxlflash driver
-    has a special character device associated with it to enable a set of
-    host management function. These character devices are hosted in a
-    class dedicated for cxlflash and can be accessed via /dev/cxlflash/*.
-
-    Applications can be written to perform various functions using the
-    host ioctl APIs below.
-
-    The structure definitions for these IOCTLs are available in:
-    uapi/scsi/cxlflash_ioctl.h
-
-HT_CXLFLASH_LUN_PROVISION
--------------------------
-    This ioctl is used to create and delete persistent LUNs on cxlflash
-    devices that lack an external LUN management interface. It is only
-    valid when used with AFUs that support the LUN provision capability.
-
-    When sufficient space is available, LUNs can be created by specifying
-    the target port to host the LUN and a desired size in 4K blocks. Upon
-    success, the LUN ID and WWID of the created LUN will be returned and
-    the SCSI bus can be scanned to detect the change in LUN topology. Note
-    that partial allocations are not supported. Should a creation fail due
-    to a space issue, the target port can be queried for its current LUN
-    geometry.
-
-    To remove a LUN, the device must first be disassociated from the Linux
-    SCSI subsystem. The LUN deletion can then be initiated by specifying a
-    target port and LUN ID. Upon success, the LUN geometry associated with
-    the port will be updated to reflect new number of provisioned LUNs and
-    available capacity.
-
-    To query the LUN geometry of a port, the target port is specified and
-    upon success, the following information is presented:
-
-        - Maximum number of provisioned LUNs allowed for the port
-        - Current number of provisioned LUNs for the port
-        - Maximum total capacity of provisioned LUNs for the port (4K blocks)
-        - Current total capacity of provisioned LUNs for the port (4K blocks)
-
-    With this information, the number of available LUNs and capacity can be
-    can be calculated.
-
-HT_CXLFLASH_AFU_DEBUG
----------------------
-    This ioctl is used to debug AFUs by supporting a command pass-through
-    interface. It is only valid when used with AFUs that support the AFU
-    debug capability.
-
-    With exception of buffer management, AFU debug commands are opaque to
-    cxlflash and treated as pass-through. For debug commands that do require
-    data transfer, the user supplies an adequately sized data buffer and must
-    specify the data transfer direction with respect to the host. There is a
-    maximum transfer size of 256K imposed. Note that partial read completions
-    are not supported - when errors are experienced with a host read data
-    transfer, the data buffer is not copied back to the user.
diff --git a/Documentation/powerpc/dawr-power9.rst b/Documentation/powerpc/dawr-power9.rst
new file mode 100644 (file)
index 0000000..c96ab6b
--- /dev/null
@@ -0,0 +1,93 @@
+=====================
+DAWR issues on POWER9
+=====================
+
+On POWER9 the Data Address Watchpoint Register (DAWR) can cause a checkstop
+if it points to cache inhibited (CI) memory. Currently Linux has no way to
+disinguish CI memory when configuring the DAWR, so (for now) the DAWR is
+disabled by this commit::
+
+    commit 9654153158d3e0684a1bdb76dbababdb7111d5a0
+    Author: Michael Neuling <mikey@neuling.org>
+    Date:   Tue Mar 27 15:37:24 2018 +1100
+    powerpc: Disable DAWR in the base POWER9 CPU features
+
+Technical Details:
+==================
+
+DAWR has 6 different ways of being set.
+1) ptrace
+2) h_set_mode(DAWR)
+3) h_set_dabr()
+4) kvmppc_set_one_reg()
+5) xmon
+
+For ptrace, we now advertise zero breakpoints on POWER9 via the
+PPC_PTRACE_GETHWDBGINFO call. This results in GDB falling back to
+software emulation of the watchpoint (which is slow).
+
+h_set_mode(DAWR) and h_set_dabr() will now return an error to the
+guest on a POWER9 host. Current Linux guests ignore this error, so
+they will silently not get the DAWR.
+
+kvmppc_set_one_reg() will store the value in the vcpu but won't
+actually set it on POWER9 hardware. This is done so we don't break
+migration from POWER8 to POWER9, at the cost of silently losing the
+DAWR on the migration.
+
+For xmon, the 'bd' command will return an error on P9.
+
+Consequences for users
+======================
+
+For GDB watchpoints (ie 'watch' command) on POWER9 bare metal , GDB
+will accept the command. Unfortunately since there is no hardware
+support for the watchpoint, GDB will software emulate the watchpoint
+making it run very slowly.
+
+The same will also be true for any guests started on a POWER9
+host. The watchpoint will fail and GDB will fall back to software
+emulation.
+
+If a guest is started on a POWER8 host, GDB will accept the watchpoint
+and configure the hardware to use the DAWR. This will run at full
+speed since it can use the hardware emulation. Unfortunately if this
+guest is migrated to a POWER9 host, the watchpoint will be lost on the
+POWER9. Loads and stores to the watchpoint locations will not be
+trapped in GDB. The watchpoint is remembered, so if the guest is
+migrated back to the POWER8 host, it will start working again.
+
+Force enabling the DAWR
+=======================
+Kernels (since ~v5.2) have an option to force enable the DAWR via::
+
+  echo Y > /sys/kernel/debug/powerpc/dawr_enable_dangerous
+
+This enables the DAWR even on POWER9.
+
+This is a dangerous setting, USE AT YOUR OWN RISK.
+
+Some users may not care about a bad user crashing their box
+(ie. single user/desktop systems) and really want the DAWR.  This
+allows them to force enable DAWR.
+
+This flag can also be used to disable DAWR access. Once this is
+cleared, all DAWR access should be cleared immediately and your
+machine once again safe from crashing.
+
+Userspace may get confused by toggling this. If DAWR is force
+enabled/disabled between getting the number of breakpoints (via
+PTRACE_GETHWDBGINFO) and setting the breakpoint, userspace will get an
+inconsistent view of what's available. Similarly for guests.
+
+For the DAWR to be enabled in a KVM guest, the DAWR needs to be force
+enabled in the host AND the guest. For this reason, this won't work on
+POWERVM as it doesn't allow the HCALL to work. Writes of 'Y' to the
+dawr_enable_dangerous file will fail if the hypervisor doesn't support
+writing the DAWR.
+
+To double check the DAWR is working, run this kernel selftest:
+
+  tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
+
+Any errors/failures/skips mean something is wrong.
diff --git a/Documentation/powerpc/dscr.rst b/Documentation/powerpc/dscr.rst
new file mode 100644 (file)
index 0000000..2ab9900
--- /dev/null
@@ -0,0 +1,87 @@
+===================================
+DSCR (Data Stream Control Register)
+===================================
+
+DSCR register in powerpc allows user to have some control of prefetch of data
+stream in the processor. Please refer to the ISA documents or related manual
+for more detailed information regarding how to use this DSCR to attain this
+control of the prefetches . This document here provides an overview of kernel
+support for DSCR, related kernel objects, it's functionalities and exported
+user interface.
+
+(A) Data Structures:
+
+       (1) thread_struct::
+
+               dscr            /* Thread DSCR value */
+               dscr_inherit    /* Thread has changed default DSCR */
+
+       (2) PACA::
+
+               dscr_default    /* per-CPU DSCR default value */
+
+       (3) sysfs.c::
+
+               dscr_default    /* System DSCR default value */
+
+(B) Scheduler Changes:
+
+       Scheduler will write the per-CPU DSCR default which is stored in the
+       CPU's PACA value into the register if the thread has dscr_inherit value
+       cleared which means that it has not changed the default DSCR till now.
+       If the dscr_inherit value is set which means that it has changed the
+       default DSCR value, scheduler will write the changed value which will
+       now be contained in thread struct's dscr into the register instead of
+       the per-CPU default PACA based DSCR value.
+
+       NOTE: Please note here that the system wide global DSCR value never
+       gets used directly in the scheduler process context switch at all.
+
+(C) SYSFS Interface:
+
+       - Global DSCR default:          /sys/devices/system/cpu/dscr_default
+       - CPU specific DSCR default:    /sys/devices/system/cpu/cpuN/dscr
+
+       Changing the global DSCR default in the sysfs will change all the CPU
+       specific DSCR defaults immediately in their PACA structures. Again if
+       the current process has the dscr_inherit clear, it also writes the new
+       value into every CPU's DSCR register right away and updates the current
+       thread's DSCR value as well.
+
+       Changing the CPU specific DSCR default value in the sysfs does exactly
+       the same thing as above but unlike the global one above, it just changes
+       stuff for that particular CPU instead for all the CPUs on the system.
+
+(D) User Space Instructions:
+
+       The DSCR register can be accessed in the user space using any of these
+       two SPR numbers available for that purpose.
+
+       (1) Problem state SPR:          0x03    (Un-privileged, POWER8 only)
+       (2) Privileged state SPR:       0x11    (Privileged)
+
+       Accessing DSCR through privileged SPR number (0x11) from user space
+       works, as it is emulated following an illegal instruction exception
+       inside the kernel. Both mfspr and mtspr instructions are emulated.
+
+       Accessing DSCR through user level SPR (0x03) from user space will first
+       create a facility unavailable exception. Inside this exception handler
+       all mfspr instruction based read attempts will get emulated and returned
+       where as the first mtspr instruction based write attempts will enable
+       the DSCR facility for the next time around (both for read and write) by
+       setting DSCR facility in the FSCR register.
+
+(E) Specifics about 'dscr_inherit':
+
+       The thread struct element 'dscr_inherit' represents whether the thread
+       in question has attempted and changed the DSCR itself using any of the
+       following methods. This element signifies whether the thread wants to
+       use the CPU default DSCR value or its own changed DSCR value in the
+       kernel.
+
+               (1) mtspr instruction   (SPR number 0x03)
+               (2) mtspr instruction   (SPR number 0x11)
+               (3) ptrace interface    (Explicitly set user DSCR value)
+
+       Any child of the process created after this event in the process inherits
+       this same behaviour as well.
diff --git a/Documentation/powerpc/dscr.txt b/Documentation/powerpc/dscr.txt
deleted file mode 100644 (file)
index ece300c..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-                       DSCR (Data Stream Control Register)
-               ================================================
-
-DSCR register in powerpc allows user to have some control of prefetch of data
-stream in the processor. Please refer to the ISA documents or related manual
-for more detailed information regarding how to use this DSCR to attain this
-control of the prefetches . This document here provides an overview of kernel
-support for DSCR, related kernel objects, it's functionalities and exported
-user interface.
-
-(A) Data Structures:
-
-       (1) thread_struct:
-               dscr            /* Thread DSCR value */
-               dscr_inherit    /* Thread has changed default DSCR */
-
-       (2) PACA:
-               dscr_default    /* per-CPU DSCR default value */
-
-       (3) sysfs.c:
-               dscr_default    /* System DSCR default value */
-
-(B) Scheduler Changes:
-
-       Scheduler will write the per-CPU DSCR default which is stored in the
-       CPU's PACA value into the register if the thread has dscr_inherit value
-       cleared which means that it has not changed the default DSCR till now.
-       If the dscr_inherit value is set which means that it has changed the
-       default DSCR value, scheduler will write the changed value which will
-       now be contained in thread struct's dscr into the register instead of
-       the per-CPU default PACA based DSCR value.
-
-       NOTE: Please note here that the system wide global DSCR value never
-       gets used directly in the scheduler process context switch at all.
-
-(C) SYSFS Interface:
-
-       Global DSCR default:            /sys/devices/system/cpu/dscr_default
-       CPU specific DSCR default:      /sys/devices/system/cpu/cpuN/dscr
-
-       Changing the global DSCR default in the sysfs will change all the CPU
-       specific DSCR defaults immediately in their PACA structures. Again if
-       the current process has the dscr_inherit clear, it also writes the new
-       value into every CPU's DSCR register right away and updates the current
-       thread's DSCR value as well.
-
-       Changing the CPU specific DSCR default value in the sysfs does exactly
-       the same thing as above but unlike the global one above, it just changes
-       stuff for that particular CPU instead for all the CPUs on the system.
-
-(D) User Space Instructions:
-
-       The DSCR register can be accessed in the user space using any of these
-       two SPR numbers available for that purpose.
-
-       (1) Problem state SPR:          0x03    (Un-privileged, POWER8 only)
-       (2) Privileged state SPR:       0x11    (Privileged)
-
-       Accessing DSCR through privileged SPR number (0x11) from user space
-       works, as it is emulated following an illegal instruction exception
-       inside the kernel. Both mfspr and mtspr instructions are emulated.
-
-       Accessing DSCR through user level SPR (0x03) from user space will first
-       create a facility unavailable exception. Inside this exception handler
-       all mfspr instruction based read attempts will get emulated and returned
-       where as the first mtspr instruction based write attempts will enable
-       the DSCR facility for the next time around (both for read and write) by
-       setting DSCR facility in the FSCR register.
-
-(E) Specifics about 'dscr_inherit':
-
-       The thread struct element 'dscr_inherit' represents whether the thread
-       in question has attempted and changed the DSCR itself using any of the
-       following methods. This element signifies whether the thread wants to
-       use the CPU default DSCR value or its own changed DSCR value in the
-       kernel.
-
-               (1) mtspr instruction   (SPR number 0x03)
-               (2) mtspr instruction   (SPR number 0x11)
-               (3) ptrace interface    (Explicitly set user DSCR value)
-
-       Any child of the process created after this event in the process inherits
-       this same behaviour as well.
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.rst b/Documentation/powerpc/eeh-pci-error-recovery.rst
new file mode 100644 (file)
index 0000000..438a87e
--- /dev/null
@@ -0,0 +1,336 @@
+==========================
+PCI Bus EEH Error Recovery
+==========================
+
+Linas Vepstas <linas@austin.ibm.com>
+
+12 January 2005
+
+
+Overview:
+---------
+The IBM POWER-based pSeries and iSeries computers include PCI bus
+controller chips that have extended capabilities for detecting and
+reporting a large variety of PCI bus error conditions.  These features
+go under the name of "EEH", for "Enhanced Error Handling".  The EEH
+hardware features allow PCI bus errors to be cleared and a PCI
+card to be "rebooted", without also having to reboot the operating
+system.
+
+This is in contrast to traditional PCI error handling, where the
+PCI chip is wired directly to the CPU, and an error would cause
+a CPU machine-check/check-stop condition, halting the CPU entirely.
+Another "traditional" technique is to ignore such errors, which
+can lead to data corruption, both of user data or of kernel data,
+hung/unresponsive adapters, or system crashes/lockups.  Thus,
+the idea behind EEH is that the operating system can become more
+reliable and robust by protecting it from PCI errors, and giving
+the OS the ability to "reboot"/recover individual PCI devices.
+
+Future systems from other vendors, based on the PCI-E specification,
+may contain similar features.
+
+
+Causes of EEH Errors
+--------------------
+EEH was originally designed to guard against hardware failure, such
+as PCI cards dying from heat, humidity, dust, vibration and bad
+electrical connections. The vast majority of EEH errors seen in
+"real life" are due to either poorly seated PCI cards, or,
+unfortunately quite commonly, due to device driver bugs, device firmware
+bugs, and sometimes PCI card hardware bugs.
+
+The most common software bug, is one that causes the device to
+attempt to DMA to a location in system memory that has not been
+reserved for DMA access for that card.  This is a powerful feature,
+as it prevents what; otherwise, would have been silent memory
+corruption caused by the bad DMA.  A number of device driver
+bugs have been found and fixed in this way over the past few
+years.  Other possible causes of EEH errors include data or
+address line parity errors (for example, due to poor electrical
+connectivity due to a poorly seated card), and PCI-X split-completion
+errors (due to software, device firmware, or device PCI hardware bugs).
+The vast majority of "true hardware failures" can be cured by
+physically removing and re-seating the PCI card.
+
+
+Detection and Recovery
+----------------------
+In the following discussion, a generic overview of how to detect
+and recover from EEH errors will be presented. This is followed
+by an overview of how the current implementation in the Linux
+kernel does it.  The actual implementation is subject to change,
+and some of the finer points are still being debated.  These
+may in turn be swayed if or when other architectures implement
+similar functionality.
+
+When a PCI Host Bridge (PHB, the bus controller connecting the
+PCI bus to the system CPU electronics complex) detects a PCI error
+condition, it will "isolate" the affected PCI card.  Isolation
+will block all writes (either to the card from the system, or
+from the card to the system), and it will cause all reads to
+return all-ff's (0xff, 0xffff, 0xffffffff for 8/16/32-bit reads).
+This value was chosen because it is the same value you would
+get if the device was physically unplugged from the slot.
+This includes access to PCI memory, I/O space, and PCI config
+space.  Interrupts; however, will continued to be delivered.
+
+Detection and recovery are performed with the aid of ppc64
+firmware.  The programming interfaces in the Linux kernel
+into the firmware are referred to as RTAS (Run-Time Abstraction
+Services).  The Linux kernel does not (should not) access
+the EEH function in the PCI chipsets directly, primarily because
+there are a number of different chipsets out there, each with
+different interfaces and quirks. The firmware provides a
+uniform abstraction layer that will work with all pSeries
+and iSeries hardware (and be forwards-compatible).
+
+If the OS or device driver suspects that a PCI slot has been
+EEH-isolated, there is a firmware call it can make to determine if
+this is the case. If so, then the device driver should put itself
+into a consistent state (given that it won't be able to complete any
+pending work) and start recovery of the card.  Recovery normally
+would consist of resetting the PCI device (holding the PCI #RST
+line high for two seconds), followed by setting up the device
+config space (the base address registers (BAR's), latency timer,
+cache line size, interrupt line, and so on).  This is followed by a
+reinitialization of the device driver.  In a worst-case scenario,
+the power to the card can be toggled, at least on hot-plug-capable
+slots.  In principle, layers far above the device driver probably
+do not need to know that the PCI card has been "rebooted" in this
+way; ideally, there should be at most a pause in Ethernet/disk/USB
+I/O while the card is being reset.
+
+If the card cannot be recovered after three or four resets, the
+kernel/device driver should assume the worst-case scenario, that the
+card has died completely, and report this error to the sysadmin.
+In addition, error messages are reported through RTAS and also through
+syslogd (/var/log/messages) to alert the sysadmin of PCI resets.
+The correct way to deal with failed adapters is to use the standard
+PCI hotplug tools to remove and replace the dead card.
+
+
+Current PPC64 Linux EEH Implementation
+--------------------------------------
+At this time, a generic EEH recovery mechanism has been implemented,
+so that individual device drivers do not need to be modified to support
+EEH recovery.  This generic mechanism piggy-backs on the PCI hotplug
+infrastructure,  and percolates events up through the userspace/udev
+infrastructure.  Following is a detailed description of how this is
+accomplished.
+
+EEH must be enabled in the PHB's very early during the boot process,
+and if a PCI slot is hot-plugged. The former is performed by
+eeh_init() in arch/powerpc/platforms/pseries/eeh.c, and the later by
+drivers/pci/hotplug/pSeries_pci.c calling in to the eeh.c code.
+EEH must be enabled before a PCI scan of the device can proceed.
+Current Power5 hardware will not work unless EEH is enabled;
+although older Power4 can run with it disabled.  Effectively,
+EEH can no longer be turned off.  PCI devices *must* be
+registered with the EEH code; the EEH code needs to know about
+the I/O address ranges of the PCI device in order to detect an
+error.  Given an arbitrary address, the routine
+pci_get_device_by_addr() will find the pci device associated
+with that address (if any).
+
+The default arch/powerpc/include/asm/io.h macros readb(), inb(), insb(),
+etc. include a check to see if the i/o read returned all-0xff's.
+If so, these make a call to eeh_dn_check_failure(), which in turn
+asks the firmware if the all-ff's value is the sign of a true EEH
+error.  If it is not, processing continues as normal.  The grand
+total number of these false alarms or "false positives" can be
+seen in /proc/ppc64/eeh (subject to change).  Normally, almost
+all of these occur during boot, when the PCI bus is scanned, where
+a large number of 0xff reads are part of the bus scan procedure.
+
+If a frozen slot is detected, code in
+arch/powerpc/platforms/pseries/eeh.c will print a stack trace to
+syslog (/var/log/messages).  This stack trace has proven to be very
+useful to device-driver authors for finding out at what point the EEH
+error was detected, as the error itself usually occurs slightly
+beforehand.
+
+Next, it uses the Linux kernel notifier chain/work queue mechanism to
+allow any interested parties to find out about the failure.  Device
+drivers, or other parts of the kernel, can use
+`eeh_register_notifier(struct notifier_block *)` to find out about EEH
+events.  The event will include a pointer to the pci device, the
+device node and some state info.  Receivers of the event can "do as
+they wish"; the default handler will be described further in this
+section.
+
+To assist in the recovery of the device, eeh.c exports the
+following functions:
+
+rtas_set_slot_reset()
+   assert the  PCI #RST line for 1/8th of a second
+rtas_configure_bridge()
+   ask firmware to configure any PCI bridges
+   located topologically under the pci slot.
+eeh_save_bars() and eeh_restore_bars():
+   save and restore the PCI
+   config-space info for a device and any devices under it.
+
+
+A handler for the EEH notifier_block events is implemented in
+drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
+It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
+This last call causes the device driver for the card to be stopped,
+which causes uevents to go out to user space. This triggers
+user-space scripts that might issue commands such as "ifdown eth0"
+for ethernet cards, and so on.  This handler then sleeps for 5 seconds,
+hoping to give the user-space scripts enough time to complete.
+It then resets the PCI card, reconfigures the device BAR's, and
+any bridges underneath. It then calls rpaphp_enable_pci_slot(),
+which restarts the device driver and triggers more user-space
+events (for example, calling "ifup eth0" for ethernet cards).
+
+
+Device Shutdown and User-Space Events
+-------------------------------------
+This section documents what happens when a pci slot is unconfigured,
+focusing on how the device driver gets shut down, and on how the
+events get delivered to user-space scripts.
+
+Following is an example sequence of events that cause a device driver
+close function to be called during the first phase of an EEH reset.
+The following sequence is an example of the pcnet32 device driver::
+
+    rpa_php_unconfig_pci_adapter (struct slot *)  // in rpaphp_pci.c
+    {
+      calls
+      pci_remove_bus_device (struct pci_dev *) // in /drivers/pci/remove.c
+      {
+        calls
+        pci_destroy_dev (struct pci_dev *)
+        {
+          calls
+          device_unregister (&dev->dev) // in /drivers/base/core.c
+          {
+            calls
+            device_del (struct device *)
+            {
+              calls
+              bus_remove_device() // in /drivers/base/bus.c
+              {
+                calls
+                device_release_driver()
+                {
+                  calls
+                  struct device_driver->remove() which is just
+                  pci_device_remove()  // in /drivers/pci/pci_driver.c
+                  {
+                    calls
+                    struct pci_driver->remove() which is just
+                    pcnet32_remove_one() // in /drivers/net/pcnet32.c
+                    {
+                      calls
+                      unregister_netdev() // in /net/core/dev.c
+                      {
+                        calls
+                        dev_close()  // in /net/core/dev.c
+                        {
+                           calls dev->stop();
+                           which is just pcnet32_close() // in pcnet32.c
+                           {
+                             which does what you wanted
+                             to stop the device
+                           }
+                        }
+                     }
+                   which
+                   frees pcnet32 device driver memory
+                }
+     }}}}}}
+
+
+in drivers/pci/pci_driver.c,
+struct device_driver->remove() is just pci_device_remove()
+which calls struct pci_driver->remove() which is pcnet32_remove_one()
+which calls unregister_netdev()  (in net/core/dev.c)
+which calls dev_close()  (in net/core/dev.c)
+which calls dev->stop() which is pcnet32_close()
+which then does the appropriate shutdown.
+
+---
+
+Following is the analogous stack trace for events sent to user-space
+when the pci device is unconfigured::
+
+  rpa_php_unconfig_pci_adapter() {             // in rpaphp_pci.c
+    calls
+    pci_remove_bus_device (struct pci_dev *) { // in /drivers/pci/remove.c
+      calls
+      pci_destroy_dev (struct pci_dev *) {
+        calls
+        device_unregister (&dev->dev) {        // in /drivers/base/core.c
+          calls
+          device_del(struct device * dev) {    // in /drivers/base/core.c
+            calls
+            kobject_del() {                    //in /libs/kobject.c
+              calls
+              kobject_uevent() {               // in /libs/kobject.c
+                calls
+                kset_uevent() {                // in /lib/kobject.c
+                  calls
+                  kset->uevent_ops->uevent()   // which is really just
+                  a call to
+                  dev_uevent() {               // in /drivers/base/core.c
+                    calls
+                    dev->bus->uevent() which is really just a call to
+                    pci_uevent () {            // in drivers/pci/hotplug.c
+                      which prints device name, etc....
+                   }
+                 }
+                 then kobject_uevent() sends a netlink uevent to userspace
+                 --> userspace uevent
+                 (during early boot, nobody listens to netlink events and
+                 kobject_uevent() executes uevent_helper[], which runs the
+                 event process /sbin/hotplug)
+             }
+           }
+           kobject_del() then calls sysfs_remove_dir(), which would
+           trigger any user-space daemon that was watching /sysfs,
+           and notice the delete event.
+
+
+Pro's and Con's of the Current Design
+-------------------------------------
+There are several issues with the current EEH software recovery design,
+which may be addressed in future revisions.  But first, note that the
+big plus of the current design is that no changes need to be made to
+individual device drivers, so that the current design throws a wide net.
+The biggest negative of the design is that it potentially disturbs
+network daemons and file systems that didn't need to be disturbed.
+
+-  A minor complaint is that resetting the network card causes
+   user-space back-to-back ifdown/ifup burps that potentially disturb
+   network daemons, that didn't need to even know that the pci
+   card was being rebooted.
+
+-  A more serious concern is that the same reset, for SCSI devices,
+   causes havoc to mounted file systems.  Scripts cannot post-facto
+   unmount a file system without flushing pending buffers, but this
+   is impossible, because I/O has already been stopped.  Thus,
+   ideally, the reset should happen at or below the block layer,
+   so that the file systems are not disturbed.
+
+   Reiserfs does not tolerate errors returned from the block device.
+   Ext3fs seems to be tolerant, retrying reads/writes until it does
+   succeed. Both have been only lightly tested in this scenario.
+
+   The SCSI-generic subsystem already has built-in code for performing
+   SCSI device resets, SCSI bus resets, and SCSI host-bus-adapter
+   (HBA) resets.  These are cascaded into a chain of attempted
+   resets if a SCSI command fails. These are completely hidden
+   from the block layer.  It would be very natural to add an EEH
+   reset into this chain of events.
+
+-  If a SCSI error occurs for the root device, all is lost unless
+   the sysadmin had the foresight to run /bin, /sbin, /etc, /var
+   and so on, out of ramdisk/tmpfs.
+
+
+Conclusions
+-----------
+There's forward progress ...
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt
deleted file mode 100644 (file)
index 6781892..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-
-
-                      PCI Bus EEH Error Recovery
-                      --------------------------
-                           Linas Vepstas
-                       <linas@austin.ibm.com>
-                          12 January 2005
-
-
-Overview:
----------
-The IBM POWER-based pSeries and iSeries computers include PCI bus
-controller chips that have extended capabilities for detecting and
-reporting a large variety of PCI bus error conditions.  These features
-go under the name of "EEH", for "Enhanced Error Handling".  The EEH
-hardware features allow PCI bus errors to be cleared and a PCI
-card to be "rebooted", without also having to reboot the operating
-system.
-
-This is in contrast to traditional PCI error handling, where the
-PCI chip is wired directly to the CPU, and an error would cause
-a CPU machine-check/check-stop condition, halting the CPU entirely.
-Another "traditional" technique is to ignore such errors, which
-can lead to data corruption, both of user data or of kernel data,
-hung/unresponsive adapters, or system crashes/lockups.  Thus,
-the idea behind EEH is that the operating system can become more
-reliable and robust by protecting it from PCI errors, and giving
-the OS the ability to "reboot"/recover individual PCI devices.
-
-Future systems from other vendors, based on the PCI-E specification,
-may contain similar features.
-
-
-Causes of EEH Errors
---------------------
-EEH was originally designed to guard against hardware failure, such
-as PCI cards dying from heat, humidity, dust, vibration and bad
-electrical connections. The vast majority of EEH errors seen in
-"real life" are due to either poorly seated PCI cards, or,
-unfortunately quite commonly, due to device driver bugs, device firmware
-bugs, and sometimes PCI card hardware bugs.
-
-The most common software bug, is one that causes the device to
-attempt to DMA to a location in system memory that has not been
-reserved for DMA access for that card.  This is a powerful feature,
-as it prevents what; otherwise, would have been silent memory
-corruption caused by the bad DMA.  A number of device driver
-bugs have been found and fixed in this way over the past few
-years.  Other possible causes of EEH errors include data or
-address line parity errors (for example, due to poor electrical
-connectivity due to a poorly seated card), and PCI-X split-completion
-errors (due to software, device firmware, or device PCI hardware bugs).
-The vast majority of "true hardware failures" can be cured by
-physically removing and re-seating the PCI card.
-
-
-Detection and Recovery
-----------------------
-In the following discussion, a generic overview of how to detect
-and recover from EEH errors will be presented. This is followed
-by an overview of how the current implementation in the Linux
-kernel does it.  The actual implementation is subject to change,
-and some of the finer points are still being debated.  These
-may in turn be swayed if or when other architectures implement
-similar functionality.
-
-When a PCI Host Bridge (PHB, the bus controller connecting the
-PCI bus to the system CPU electronics complex) detects a PCI error
-condition, it will "isolate" the affected PCI card.  Isolation
-will block all writes (either to the card from the system, or
-from the card to the system), and it will cause all reads to
-return all-ff's (0xff, 0xffff, 0xffffffff for 8/16/32-bit reads).
-This value was chosen because it is the same value you would
-get if the device was physically unplugged from the slot.
-This includes access to PCI memory, I/O space, and PCI config
-space.  Interrupts; however, will continued to be delivered.
-
-Detection and recovery are performed with the aid of ppc64
-firmware.  The programming interfaces in the Linux kernel
-into the firmware are referred to as RTAS (Run-Time Abstraction
-Services).  The Linux kernel does not (should not) access
-the EEH function in the PCI chipsets directly, primarily because
-there are a number of different chipsets out there, each with
-different interfaces and quirks. The firmware provides a
-uniform abstraction layer that will work with all pSeries
-and iSeries hardware (and be forwards-compatible).
-
-If the OS or device driver suspects that a PCI slot has been
-EEH-isolated, there is a firmware call it can make to determine if
-this is the case. If so, then the device driver should put itself
-into a consistent state (given that it won't be able to complete any
-pending work) and start recovery of the card.  Recovery normally
-would consist of resetting the PCI device (holding the PCI #RST
-line high for two seconds), followed by setting up the device
-config space (the base address registers (BAR's), latency timer,
-cache line size, interrupt line, and so on).  This is followed by a
-reinitialization of the device driver.  In a worst-case scenario,
-the power to the card can be toggled, at least on hot-plug-capable
-slots.  In principle, layers far above the device driver probably
-do not need to know that the PCI card has been "rebooted" in this
-way; ideally, there should be at most a pause in Ethernet/disk/USB
-I/O while the card is being reset.
-
-If the card cannot be recovered after three or four resets, the
-kernel/device driver should assume the worst-case scenario, that the
-card has died completely, and report this error to the sysadmin.
-In addition, error messages are reported through RTAS and also through
-syslogd (/var/log/messages) to alert the sysadmin of PCI resets.
-The correct way to deal with failed adapters is to use the standard
-PCI hotplug tools to remove and replace the dead card.
-
-
-Current PPC64 Linux EEH Implementation
---------------------------------------
-At this time, a generic EEH recovery mechanism has been implemented,
-so that individual device drivers do not need to be modified to support
-EEH recovery.  This generic mechanism piggy-backs on the PCI hotplug
-infrastructure,  and percolates events up through the userspace/udev
-infrastructure.  Following is a detailed description of how this is
-accomplished.
-
-EEH must be enabled in the PHB's very early during the boot process,
-and if a PCI slot is hot-plugged. The former is performed by
-eeh_init() in arch/powerpc/platforms/pseries/eeh.c, and the later by
-drivers/pci/hotplug/pSeries_pci.c calling in to the eeh.c code.
-EEH must be enabled before a PCI scan of the device can proceed.
-Current Power5 hardware will not work unless EEH is enabled;
-although older Power4 can run with it disabled.  Effectively,
-EEH can no longer be turned off.  PCI devices *must* be
-registered with the EEH code; the EEH code needs to know about
-the I/O address ranges of the PCI device in order to detect an
-error.  Given an arbitrary address, the routine
-pci_get_device_by_addr() will find the pci device associated
-with that address (if any).
-
-The default arch/powerpc/include/asm/io.h macros readb(), inb(), insb(),
-etc. include a check to see if the i/o read returned all-0xff's.
-If so, these make a call to eeh_dn_check_failure(), which in turn
-asks the firmware if the all-ff's value is the sign of a true EEH
-error.  If it is not, processing continues as normal.  The grand
-total number of these false alarms or "false positives" can be
-seen in /proc/ppc64/eeh (subject to change).  Normally, almost
-all of these occur during boot, when the PCI bus is scanned, where
-a large number of 0xff reads are part of the bus scan procedure.
-
-If a frozen slot is detected, code in 
-arch/powerpc/platforms/pseries/eeh.c will print a stack trace to 
-syslog (/var/log/messages).  This stack trace has proven to be very 
-useful to device-driver authors for finding out at what point the EEH 
-error was detected, as the error itself usually occurs slightly 
-beforehand.
-
-Next, it uses the Linux kernel notifier chain/work queue mechanism to
-allow any interested parties to find out about the failure.  Device
-drivers, or other parts of the kernel, can use
-eeh_register_notifier(struct notifier_block *) to find out about EEH
-events.  The event will include a pointer to the pci device, the
-device node and some state info.  Receivers of the event can "do as
-they wish"; the default handler will be described further in this
-section.
-
-To assist in the recovery of the device, eeh.c exports the
-following functions:
-
-rtas_set_slot_reset() -- assert the  PCI #RST line for 1/8th of a second
-rtas_configure_bridge() -- ask firmware to configure any PCI bridges
-   located topologically under the pci slot.
-eeh_save_bars() and eeh_restore_bars(): save and restore the PCI
-   config-space info for a device and any devices under it.
-
-
-A handler for the EEH notifier_block events is implemented in
-drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
-It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
-This last call causes the device driver for the card to be stopped,
-which causes uevents to go out to user space. This triggers
-user-space scripts that might issue commands such as "ifdown eth0"
-for ethernet cards, and so on.  This handler then sleeps for 5 seconds,
-hoping to give the user-space scripts enough time to complete.
-It then resets the PCI card, reconfigures the device BAR's, and
-any bridges underneath. It then calls rpaphp_enable_pci_slot(),
-which restarts the device driver and triggers more user-space
-events (for example, calling "ifup eth0" for ethernet cards).
-
-
-Device Shutdown and User-Space Events
--------------------------------------
-This section documents what happens when a pci slot is unconfigured,
-focusing on how the device driver gets shut down, and on how the
-events get delivered to user-space scripts.
-
-Following is an example sequence of events that cause a device driver
-close function to be called during the first phase of an EEH reset.
-The following sequence is an example of the pcnet32 device driver.
-
-    rpa_php_unconfig_pci_adapter (struct slot *)  // in rpaphp_pci.c
-    {
-      calls
-      pci_remove_bus_device (struct pci_dev *) // in /drivers/pci/remove.c
-      {
-        calls
-        pci_destroy_dev (struct pci_dev *)
-        {
-          calls
-          device_unregister (&dev->dev) // in /drivers/base/core.c
-          {
-            calls
-            device_del (struct device *)
-            {
-              calls
-              bus_remove_device() // in /drivers/base/bus.c
-              {
-                calls
-                device_release_driver()
-                {
-                  calls
-                  struct device_driver->remove() which is just
-                  pci_device_remove()  // in /drivers/pci/pci_driver.c
-                  {
-                    calls
-                    struct pci_driver->remove() which is just
-                    pcnet32_remove_one() // in /drivers/net/pcnet32.c
-                    {
-                      calls
-                      unregister_netdev() // in /net/core/dev.c
-                      {
-                        calls
-                        dev_close()  // in /net/core/dev.c
-                        {
-                           calls dev->stop();
-                           which is just pcnet32_close() // in pcnet32.c
-                           {
-                             which does what you wanted
-                             to stop the device
-                           }
-                        }
-                     }
-                   which
-                   frees pcnet32 device driver memory
-                }
-     }}}}}}
-
-
-    in drivers/pci/pci_driver.c,
-    struct device_driver->remove() is just pci_device_remove()
-    which calls struct pci_driver->remove() which is pcnet32_remove_one()
-    which calls unregister_netdev()  (in net/core/dev.c)
-    which calls dev_close()  (in net/core/dev.c)
-    which calls dev->stop() which is pcnet32_close()
-    which then does the appropriate shutdown.
-
----
-Following is the analogous stack trace for events sent to user-space
-when the pci device is unconfigured.
-
-rpa_php_unconfig_pci_adapter() {             // in rpaphp_pci.c
-  calls
-  pci_remove_bus_device (struct pci_dev *) { // in /drivers/pci/remove.c
-    calls
-    pci_destroy_dev (struct pci_dev *) {
-      calls
-      device_unregister (&dev->dev) {        // in /drivers/base/core.c
-        calls
-        device_del(struct device * dev) {    // in /drivers/base/core.c
-          calls
-          kobject_del() {                    //in /libs/kobject.c
-            calls
-            kobject_uevent() {               // in /libs/kobject.c
-              calls
-              kset_uevent() {                // in /lib/kobject.c
-                calls
-                kset->uevent_ops->uevent()   // which is really just
-                a call to
-                dev_uevent() {               // in /drivers/base/core.c
-                  calls
-                  dev->bus->uevent() which is really just a call to
-                  pci_uevent () {            // in drivers/pci/hotplug.c
-                    which prints device name, etc....
-                 }
-               }
-               then kobject_uevent() sends a netlink uevent to userspace
-               --> userspace uevent
-               (during early boot, nobody listens to netlink events and
-               kobject_uevent() executes uevent_helper[], which runs the
-               event process /sbin/hotplug)
-           }
-         }
-         kobject_del() then calls sysfs_remove_dir(), which would
-         trigger any user-space daemon that was watching /sysfs,
-         and notice the delete event.
-
-
-Pro's and Con's of the Current Design
--------------------------------------
-There are several issues with the current EEH software recovery design,
-which may be addressed in future revisions.  But first, note that the
-big plus of the current design is that no changes need to be made to
-individual device drivers, so that the current design throws a wide net.
-The biggest negative of the design is that it potentially disturbs
-network daemons and file systems that didn't need to be disturbed.
-
--- A minor complaint is that resetting the network card causes
-   user-space back-to-back ifdown/ifup burps that potentially disturb
-   network daemons, that didn't need to even know that the pci
-   card was being rebooted.
-
--- A more serious concern is that the same reset, for SCSI devices,
-   causes havoc to mounted file systems.  Scripts cannot post-facto
-   unmount a file system without flushing pending buffers, but this
-   is impossible, because I/O has already been stopped.  Thus,
-   ideally, the reset should happen at or below the block layer,
-   so that the file systems are not disturbed.
-
-   Reiserfs does not tolerate errors returned from the block device.
-   Ext3fs seems to be tolerant, retrying reads/writes until it does
-   succeed. Both have been only lightly tested in this scenario.
-
-   The SCSI-generic subsystem already has built-in code for performing
-   SCSI device resets, SCSI bus resets, and SCSI host-bus-adapter
-   (HBA) resets.  These are cascaded into a chain of attempted
-   resets if a SCSI command fails. These are completely hidden
-   from the block layer.  It would be very natural to add an EEH
-   reset into this chain of events.
-
--- If a SCSI error occurs for the root device, all is lost unless
-   the sysadmin had the foresight to run /bin, /sbin, /etc, /var
-   and so on, out of ramdisk/tmpfs.
-
-
-Conclusions
------------
-There's forward progress ...
-
-
diff --git a/Documentation/powerpc/firmware-assisted-dump.rst b/Documentation/powerpc/firmware-assisted-dump.rst
new file mode 100644 (file)
index 0000000..9ca1283
--- /dev/null
@@ -0,0 +1,301 @@
+======================
+Firmware-Assisted Dump
+======================
+
+July 2011
+
+The goal of firmware-assisted dump is to enable the dump of
+a crashed system, and to do so from a fully-reset system, and
+to minimize the total elapsed time until the system is back
+in production use.
+
+- Firmware assisted dump (fadump) infrastructure is intended to replace
+  the existing phyp assisted dump.
+- Fadump uses the same firmware interfaces and memory reservation model
+  as phyp assisted dump.
+- Unlike phyp dump, fadump exports the memory dump through /proc/vmcore
+  in the ELF format in the same way as kdump. This helps us reuse the
+  kdump infrastructure for dump capture and filtering.
+- Unlike phyp dump, userspace tool does not need to refer any sysfs
+  interface while reading /proc/vmcore.
+- Unlike phyp dump, fadump allows user to release all the memory reserved
+  for dump, with a single operation of echo 1 > /sys/kernel/fadump_release_mem.
+- Once enabled through kernel boot parameter, fadump can be
+  started/stopped through /sys/kernel/fadump_registered interface (see
+  sysfs files section below) and can be easily integrated with kdump
+  service start/stop init scripts.
+
+Comparing with kdump or other strategies, firmware-assisted
+dump offers several strong, practical advantages:
+
+-  Unlike kdump, the system has been reset, and loaded
+   with a fresh copy of the kernel.  In particular,
+   PCI and I/O devices have been reinitialized and are
+   in a clean, consistent state.
+-  Once the dump is copied out, the memory that held the dump
+   is immediately available to the running kernel. And therefore,
+   unlike kdump, fadump doesn't need a 2nd reboot to get back
+   the system to the production configuration.
+
+The above can only be accomplished by coordination with,
+and assistance from the Power firmware. The procedure is
+as follows:
+
+-  The first kernel registers the sections of memory with the
+   Power firmware for dump preservation during OS initialization.
+   These registered sections of memory are reserved by the first
+   kernel during early boot.
+
+-  When a system crashes, the Power firmware will save
+   the low memory (boot memory of size larger of 5% of system RAM
+   or 256MB) of RAM to the previous registered region. It will
+   also save system registers, and hardware PTE's.
+
+   NOTE:
+         The term 'boot memory' means size of the low memory chunk
+         that is required for a kernel to boot successfully when
+         booted with restricted memory. By default, the boot memory
+         size will be the larger of 5% of system RAM or 256MB.
+         Alternatively, user can also specify boot memory size
+         through boot parameter 'crashkernel=' which will override
+         the default calculated size. Use this option if default
+         boot memory size is not sufficient for second kernel to
+         boot successfully. For syntax of crashkernel= parameter,
+         refer to Documentation/admin-guide/kdump/kdump.rst. If any offset is
+         provided in crashkernel= parameter, it will be ignored
+         as fadump uses a predefined offset to reserve memory
+         for boot memory dump preservation in case of a crash.
+
+-  After the low memory (boot memory) area has been saved, the
+   firmware will reset PCI and other hardware state.  It will
+   *not* clear the RAM. It will then launch the bootloader, as
+   normal.
+
+-  The freshly booted kernel will notice that there is a new
+   node (ibm,dump-kernel) in the device tree, indicating that
+   there is crash data available from a previous boot. During
+   the early boot OS will reserve rest of the memory above
+   boot memory size effectively booting with restricted memory
+   size. This will make sure that the second kernel will not
+   touch any of the dump memory area.
+
+-  User-space tools will read /proc/vmcore to obtain the contents
+   of memory, which holds the previous crashed kernel dump in ELF
+   format. The userspace tools may copy this info to disk, or
+   network, nas, san, iscsi, etc. as desired.
+
+-  Once the userspace tool is done saving dump, it will echo
+   '1' to /sys/kernel/fadump_release_mem to release the reserved
+   memory back to general use, except the memory required for
+   next firmware-assisted dump registration.
+
+   e.g.::
+
+     # echo 1 > /sys/kernel/fadump_release_mem
+
+Please note that the firmware-assisted dump feature
+is only available on Power6 and above systems with recent
+firmware versions.
+
+Implementation details:
+-----------------------
+
+During boot, a check is made to see if firmware supports
+this feature on that particular machine. If it does, then
+we check to see if an active dump is waiting for us. If yes
+then everything but boot memory size of RAM is reserved during
+early boot (See Fig. 2). This area is released once we finish
+collecting the dump from user land scripts (e.g. kdump scripts)
+that are run. If there is dump data, then the
+/sys/kernel/fadump_release_mem file is created, and the reserved
+memory is held.
+
+If there is no waiting dump data, then only the memory required
+to hold CPU state, HPTE region, boot memory dump and elfcore
+header, is usually reserved at an offset greater than boot memory
+size (see Fig. 1). This area is *not* released: this region will
+be kept permanently reserved, so that it can act as a receptacle
+for a copy of the boot memory content in addition to CPU state
+and HPTE region, in the case a crash does occur. Since this reserved
+memory area is used only after the system crash, there is no point in
+blocking this significant chunk of memory from production kernel.
+Hence, the implementation uses the Linux kernel's Contiguous Memory
+Allocator (CMA) for memory reservation if CMA is configured for kernel.
+With CMA reservation this memory will be available for applications to
+use it, while kernel is prevented from using it. With this fadump will
+still be able to capture all of the kernel memory and most of the user
+space memory except the user pages that were present in CMA region::
+
+  o Memory Reservation during first kernel
+
+  Low memory                                         Top of memory
+  0      boot memory size                                       |
+  |           |                |<--Reserved dump area -->|      |
+  V           V                |   Permanent Reservation |      V
+  +-----------+----------/ /---+---+----+-----------+----+------+
+  |           |                |CPU|HPTE|  DUMP     |ELF |      |
+  +-----------+----------/ /---+---+----+-----------+----+------+
+        |                                           ^
+        |                                           |
+        \                                           /
+         -------------------------------------------
+          Boot memory content gets transferred to
+          reserved area by firmware at the time of
+          crash
+                   Fig. 1
+
+  o Memory Reservation during second kernel after crash
+
+  Low memory                                        Top of memory
+  0      boot memory size                                       |
+  |           |<------------- Reserved dump area ----------- -->|
+  V           V                                                 V
+  +-----------+----------/ /---+---+----+-----------+----+------+
+  |           |                |CPU|HPTE|  DUMP     |ELF |      |
+  +-----------+----------/ /---+---+----+-----------+----+------+
+        |                                              |
+        V                                              V
+   Used by second                                /proc/vmcore
+   kernel to boot
+                   Fig. 2
+
+Currently the dump will be copied from /proc/vmcore to a
+a new file upon user intervention. The dump data available through
+/proc/vmcore will be in ELF format. Hence the existing kdump
+infrastructure (kdump scripts) to save the dump works fine with
+minor modifications.
+
+The tools to examine the dump will be same as the ones
+used for kdump.
+
+How to enable firmware-assisted dump (fadump):
+----------------------------------------------
+
+1. Set config option CONFIG_FA_DUMP=y and build kernel.
+2. Boot into linux kernel with 'fadump=on' kernel cmdline option.
+   By default, fadump reserved memory will be initialized as CMA area.
+   Alternatively, user can boot linux kernel with 'fadump=nocma' to
+   prevent fadump to use CMA.
+3. Optionally, user can also set 'crashkernel=' kernel cmdline
+   to specify size of the memory to reserve for boot memory dump
+   preservation.
+
+NOTE:
+     1. 'fadump_reserve_mem=' parameter has been deprecated. Instead
+        use 'crashkernel=' to specify size of the memory to reserve
+        for boot memory dump preservation.
+     2. If firmware-assisted dump fails to reserve memory then it
+        will fallback to existing kdump mechanism if 'crashkernel='
+        option is set at kernel cmdline.
+     3. if user wants to capture all of user space memory and ok with
+        reserved memory not available to production system, then
+        'fadump=nocma' kernel parameter can be used to fallback to
+        old behaviour.
+
+Sysfs/debugfs files:
+--------------------
+
+Firmware-assisted dump feature uses sysfs file system to hold
+the control files and debugfs file to display memory reserved region.
+
+Here is the list of files under kernel sysfs:
+
+ /sys/kernel/fadump_enabled
+    This is used to display the fadump status.
+
+    - 0 = fadump is disabled
+    - 1 = fadump is enabled
+
+    This interface can be used by kdump init scripts to identify if
+    fadump is enabled in the kernel and act accordingly.
+
+ /sys/kernel/fadump_registered
+    This is used to display the fadump registration status as well
+    as to control (start/stop) the fadump registration.
+
+    - 0 = fadump is not registered.
+    - 1 = fadump is registered and ready to handle system crash.
+
+    To register fadump echo 1 > /sys/kernel/fadump_registered and
+    echo 0 > /sys/kernel/fadump_registered for un-register and stop the
+    fadump. Once the fadump is un-registered, the system crash will not
+    be handled and vmcore will not be captured. This interface can be
+    easily integrated with kdump service start/stop.
+
+ /sys/kernel/fadump_release_mem
+    This file is available only when fadump is active during
+    second kernel. This is used to release the reserved memory
+    region that are held for saving crash dump. To release the
+    reserved memory echo 1 to it::
+
+       echo 1  > /sys/kernel/fadump_release_mem
+
+    After echo 1, the content of the /sys/kernel/debug/powerpc/fadump_region
+    file will change to reflect the new memory reservations.
+
+    The existing userspace tools (kdump infrastructure) can be easily
+    enhanced to use this interface to release the memory reserved for
+    dump and continue without 2nd reboot.
+
+Here is the list of files under powerpc debugfs:
+(Assuming debugfs is mounted on /sys/kernel/debug directory.)
+
+ /sys/kernel/debug/powerpc/fadump_region
+    This file shows the reserved memory regions if fadump is
+    enabled otherwise this file is empty. The output format
+    is::
+
+      <region>: [<start>-<end>] <reserved-size> bytes, Dumped: <dump-size>
+
+    e.g.
+    Contents when fadump is registered during first kernel::
+
+      # cat /sys/kernel/debug/powerpc/fadump_region
+      CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x0
+      HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x0
+      DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x0
+
+    Contents when fadump is active during second kernel::
+
+      # cat /sys/kernel/debug/powerpc/fadump_region
+      CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x40020
+      HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x1000
+      DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x10000000
+          : [0x00000010000000-0x0000006ffaffff] 0x5ffb0000 bytes, Dumped: 0x5ffb0000
+
+NOTE:
+      Please refer to Documentation/filesystems/debugfs.txt on
+      how to mount the debugfs filesystem.
+
+
+TODO:
+-----
+ - Need to come up with the better approach to find out more
+   accurate boot memory size that is required for a kernel to
+   boot successfully when booted with restricted memory.
+ - The fadump implementation introduces a fadump crash info structure
+   in the scratch area before the ELF core header. The idea of introducing
+   this structure is to pass some important crash info data to the second
+   kernel which will help second kernel to populate ELF core header with
+   correct data before it gets exported through /proc/vmcore. The current
+   design implementation does not address a possibility of introducing
+   additional fields (in future) to this structure without affecting
+   compatibility. Need to come up with the better approach to address this.
+
+   The possible approaches are:
+
+       1. Introduce version field for version tracking, bump up the version
+       whenever a new field is added to the structure in future. The version
+       field can be used to find out what fields are valid for the current
+       version of the structure.
+       2. Reserve the area of predefined size (say PAGE_SIZE) for this
+       structure and have unused area as reserved (initialized to zero)
+       for future field additions.
+
+   The advantage of approach 1 over 2 is we don't need to reserve extra space.
+
+Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+
+This document is based on the original documentation written for phyp
+
+assisted dump by Linas Vepstas and Manish Ahuja.
diff --git a/Documentation/powerpc/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.txt
deleted file mode 100644 (file)
index 10e7f4d..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-
-                   Firmware-Assisted Dump
-                   ------------------------
-                       July 2011
-
-The goal of firmware-assisted dump is to enable the dump of
-a crashed system, and to do so from a fully-reset system, and
-to minimize the total elapsed time until the system is back
-in production use.
-
-- Firmware assisted dump (fadump) infrastructure is intended to replace
-  the existing phyp assisted dump.
-- Fadump uses the same firmware interfaces and memory reservation model
-  as phyp assisted dump.
-- Unlike phyp dump, fadump exports the memory dump through /proc/vmcore
-  in the ELF format in the same way as kdump. This helps us reuse the
-  kdump infrastructure for dump capture and filtering.
-- Unlike phyp dump, userspace tool does not need to refer any sysfs
-  interface while reading /proc/vmcore.
-- Unlike phyp dump, fadump allows user to release all the memory reserved
-  for dump, with a single operation of echo 1 > /sys/kernel/fadump_release_mem.
-- Once enabled through kernel boot parameter, fadump can be
-  started/stopped through /sys/kernel/fadump_registered interface (see
-  sysfs files section below) and can be easily integrated with kdump
-  service start/stop init scripts.
-
-Comparing with kdump or other strategies, firmware-assisted
-dump offers several strong, practical advantages:
-
--- Unlike kdump, the system has been reset, and loaded
-   with a fresh copy of the kernel.  In particular,
-   PCI and I/O devices have been reinitialized and are
-   in a clean, consistent state.
--- Once the dump is copied out, the memory that held the dump
-   is immediately available to the running kernel. And therefore,
-   unlike kdump, fadump doesn't need a 2nd reboot to get back
-   the system to the production configuration.
-
-The above can only be accomplished by coordination with,
-and assistance from the Power firmware. The procedure is
-as follows:
-
--- The first kernel registers the sections of memory with the
-   Power firmware for dump preservation during OS initialization.
-   These registered sections of memory are reserved by the first
-   kernel during early boot.
-
--- When a system crashes, the Power firmware will save
-   the low memory (boot memory of size larger of 5% of system RAM
-   or 256MB) of RAM to the previous registered region. It will
-   also save system registers, and hardware PTE's.
-
-   NOTE: The term 'boot memory' means size of the low memory chunk
-         that is required for a kernel to boot successfully when
-         booted with restricted memory. By default, the boot memory
-         size will be the larger of 5% of system RAM or 256MB.
-         Alternatively, user can also specify boot memory size
-         through boot parameter 'crashkernel=' which will override
-         the default calculated size. Use this option if default
-         boot memory size is not sufficient for second kernel to
-         boot successfully. For syntax of crashkernel= parameter,
-         refer to Documentation/admin-guide/kdump/kdump.rst. If any offset is
-         provided in crashkernel= parameter, it will be ignored
-         as fadump uses a predefined offset to reserve memory
-         for boot memory dump preservation in case of a crash.
-
--- After the low memory (boot memory) area has been saved, the
-   firmware will reset PCI and other hardware state.  It will
-   *not* clear the RAM. It will then launch the bootloader, as
-   normal.
-
--- The freshly booted kernel will notice that there is a new
-   node (ibm,dump-kernel) in the device tree, indicating that
-   there is crash data available from a previous boot. During
-   the early boot OS will reserve rest of the memory above
-   boot memory size effectively booting with restricted memory
-   size. This will make sure that the second kernel will not
-   touch any of the dump memory area.
-
--- User-space tools will read /proc/vmcore to obtain the contents
-   of memory, which holds the previous crashed kernel dump in ELF
-   format. The userspace tools may copy this info to disk, or
-   network, nas, san, iscsi, etc. as desired.
-
--- Once the userspace tool is done saving dump, it will echo
-   '1' to /sys/kernel/fadump_release_mem to release the reserved
-   memory back to general use, except the memory required for
-   next firmware-assisted dump registration.
-
-   e.g.
-     # echo 1 > /sys/kernel/fadump_release_mem
-
-Please note that the firmware-assisted dump feature
-is only available on Power6 and above systems with recent
-firmware versions.
-
-Implementation details:
-----------------------
-
-During boot, a check is made to see if firmware supports
-this feature on that particular machine. If it does, then
-we check to see if an active dump is waiting for us. If yes
-then everything but boot memory size of RAM is reserved during
-early boot (See Fig. 2). This area is released once we finish
-collecting the dump from user land scripts (e.g. kdump scripts)
-that are run. If there is dump data, then the
-/sys/kernel/fadump_release_mem file is created, and the reserved
-memory is held.
-
-If there is no waiting dump data, then only the memory required
-to hold CPU state, HPTE region, boot memory dump and elfcore
-header, is usually reserved at an offset greater than boot memory
-size (see Fig. 1). This area is *not* released: this region will
-be kept permanently reserved, so that it can act as a receptacle
-for a copy of the boot memory content in addition to CPU state
-and HPTE region, in the case a crash does occur. Since this reserved
-memory area is used only after the system crash, there is no point in
-blocking this significant chunk of memory from production kernel.
-Hence, the implementation uses the Linux kernel's Contiguous Memory
-Allocator (CMA) for memory reservation if CMA is configured for kernel.
-With CMA reservation this memory will be available for applications to
-use it, while kernel is prevented from using it. With this fadump will
-still be able to capture all of the kernel memory and most of the user
-space memory except the user pages that were present in CMA region.
-
-  o Memory Reservation during first kernel
-
-  Low memory                                         Top of memory
-  0      boot memory size                                       |
-  |           |                |<--Reserved dump area -->|      |
-  V           V                |   Permanent Reservation |      V
-  +-----------+----------/ /---+---+----+-----------+----+------+
-  |           |                |CPU|HPTE|  DUMP     |ELF |      |
-  +-----------+----------/ /---+---+----+-----------+----+------+
-        |                                           ^
-        |                                           |
-        \                                           /
-         -------------------------------------------
-          Boot memory content gets transferred to
-          reserved area by firmware at the time of
-          crash
-                   Fig. 1
-
-  o Memory Reservation during second kernel after crash
-
-  Low memory                                        Top of memory
-  0      boot memory size                                       |
-  |           |<------------- Reserved dump area ----------- -->|
-  V           V                                                 V
-  +-----------+----------/ /---+---+----+-----------+----+------+
-  |           |                |CPU|HPTE|  DUMP     |ELF |      |
-  +-----------+----------/ /---+---+----+-----------+----+------+
-        |                                              |
-        V                                              V
-   Used by second                                /proc/vmcore
-   kernel to boot
-                   Fig. 2
-
-Currently the dump will be copied from /proc/vmcore to a
-a new file upon user intervention. The dump data available through
-/proc/vmcore will be in ELF format. Hence the existing kdump
-infrastructure (kdump scripts) to save the dump works fine with
-minor modifications.
-
-The tools to examine the dump will be same as the ones
-used for kdump.
-
-How to enable firmware-assisted dump (fadump):
--------------------------------------
-
-1. Set config option CONFIG_FA_DUMP=y and build kernel.
-2. Boot into linux kernel with 'fadump=on' kernel cmdline option.
-   By default, fadump reserved memory will be initialized as CMA area.
-   Alternatively, user can boot linux kernel with 'fadump=nocma' to
-   prevent fadump to use CMA.
-3. Optionally, user can also set 'crashkernel=' kernel cmdline
-   to specify size of the memory to reserve for boot memory dump
-   preservation.
-
-NOTE: 1. 'fadump_reserve_mem=' parameter has been deprecated. Instead
-         use 'crashkernel=' to specify size of the memory to reserve
-         for boot memory dump preservation.
-      2. If firmware-assisted dump fails to reserve memory then it
-         will fallback to existing kdump mechanism if 'crashkernel='
-         option is set at kernel cmdline.
-      3. if user wants to capture all of user space memory and ok with
-         reserved memory not available to production system, then
-         'fadump=nocma' kernel parameter can be used to fallback to
-         old behaviour.
-
-Sysfs/debugfs files:
-------------
-
-Firmware-assisted dump feature uses sysfs file system to hold
-the control files and debugfs file to display memory reserved region.
-
-Here is the list of files under kernel sysfs:
-
- /sys/kernel/fadump_enabled
-
-    This is used to display the fadump status.
-    0 = fadump is disabled
-    1 = fadump is enabled
-
-    This interface can be used by kdump init scripts to identify if
-    fadump is enabled in the kernel and act accordingly.
-
- /sys/kernel/fadump_registered
-
-    This is used to display the fadump registration status as well
-    as to control (start/stop) the fadump registration.
-    0 = fadump is not registered.
-    1 = fadump is registered and ready to handle system crash.
-
-    To register fadump echo 1 > /sys/kernel/fadump_registered and
-    echo 0 > /sys/kernel/fadump_registered for un-register and stop the
-    fadump. Once the fadump is un-registered, the system crash will not
-    be handled and vmcore will not be captured. This interface can be
-    easily integrated with kdump service start/stop.
-
- /sys/kernel/fadump_release_mem
-
-    This file is available only when fadump is active during
-    second kernel. This is used to release the reserved memory
-    region that are held for saving crash dump. To release the
-    reserved memory echo 1 to it:
-
-    echo 1  > /sys/kernel/fadump_release_mem
-
-    After echo 1, the content of the /sys/kernel/debug/powerpc/fadump_region
-    file will change to reflect the new memory reservations.
-
-    The existing userspace tools (kdump infrastructure) can be easily
-    enhanced to use this interface to release the memory reserved for
-    dump and continue without 2nd reboot.
-
-Here is the list of files under powerpc debugfs:
-(Assuming debugfs is mounted on /sys/kernel/debug directory.)
-
- /sys/kernel/debug/powerpc/fadump_region
-
-    This file shows the reserved memory regions if fadump is
-    enabled otherwise this file is empty. The output format
-    is:
-    <region>: [<start>-<end>] <reserved-size> bytes, Dumped: <dump-size>
-
-    e.g.
-    Contents when fadump is registered during first kernel
-
-    # cat /sys/kernel/debug/powerpc/fadump_region
-    CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x0
-    HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x0
-    DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x0
-
-    Contents when fadump is active during second kernel
-
-    # cat /sys/kernel/debug/powerpc/fadump_region
-    CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x40020
-    HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x1000
-    DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x10000000
-        : [0x00000010000000-0x0000006ffaffff] 0x5ffb0000 bytes, Dumped: 0x5ffb0000
-
-NOTE: Please refer to Documentation/filesystems/debugfs.txt on
-      how to mount the debugfs filesystem.
-
-
-TODO:
------
- o Need to come up with the better approach to find out more
-   accurate boot memory size that is required for a kernel to
-   boot successfully when booted with restricted memory.
- o The fadump implementation introduces a fadump crash info structure
-   in the scratch area before the ELF core header. The idea of introducing
-   this structure is to pass some important crash info data to the second
-   kernel which will help second kernel to populate ELF core header with
-   correct data before it gets exported through /proc/vmcore. The current
-   design implementation does not address a possibility of introducing
-   additional fields (in future) to this structure without affecting
-   compatibility. Need to come up with the better approach to address this.
-   The possible approaches are:
-       1. Introduce version field for version tracking, bump up the version
-       whenever a new field is added to the structure in future. The version
-       field can be used to find out what fields are valid for the current
-       version of the structure.
-       2. Reserve the area of predefined size (say PAGE_SIZE) for this
-       structure and have unused area as reserved (initialized to zero)
-       for future field additions.
-   The advantage of approach 1 over 2 is we don't need to reserve extra space.
----
-Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
-This document is based on the original documentation written for phyp
-assisted dump by Linas Vepstas and Manish Ahuja.
diff --git a/Documentation/powerpc/hvcs.rst b/Documentation/powerpc/hvcs.rst
new file mode 100644 (file)
index 0000000..6808acd
--- /dev/null
@@ -0,0 +1,581 @@
+===============================================================
+HVCS IBM "Hypervisor Virtual Console Server" Installation Guide
+===============================================================
+
+for Linux Kernel 2.6.4+
+
+Copyright (C) 2004 IBM Corporation
+
+.. ===========================================================================
+.. NOTE:Eight space tabs are the optimum editor setting for reading this file.
+.. ===========================================================================
+
+
+Author(s): Ryan S. Arnold <rsa@us.ibm.com>
+
+Date Created: March, 02, 2004
+Last Changed: August, 24, 2004
+
+.. Table of contents:
+
+       1.  Driver Introduction:
+       2.  System Requirements
+       3.  Build Options:
+               3.1  Built-in:
+               3.2  Module:
+       4.  Installation:
+       5.  Connection:
+       6.  Disconnection:
+       7.  Configuration:
+       8.  Questions & Answers:
+       9.  Reporting Bugs:
+
+1. Driver Introduction:
+=======================
+
+This is the device driver for the IBM Hypervisor Virtual Console Server,
+"hvcs".  The IBM hvcs provides a tty driver interface to allow Linux user
+space applications access to the system consoles of logically partitioned
+operating systems (Linux and AIX) running on the same partitioned Power5
+ppc64 system.  Physical hardware consoles per partition are not practical
+on this hardware so system consoles are accessed by this driver using
+firmware interfaces to virtual terminal devices.
+
+2. System Requirements:
+=======================
+
+This device driver was written using 2.6.4 Linux kernel APIs and will only
+build and run on kernels of this version or later.
+
+This driver was written to operate solely on IBM Power5 ppc64 hardware
+though some care was taken to abstract the architecture dependent firmware
+calls from the driver code.
+
+Sysfs must be mounted on the system so that the user can determine which
+major and minor numbers are associated with each vty-server.  Directions
+for sysfs mounting are outside the scope of this document.
+
+3. Build Options:
+=================
+
+The hvcs driver registers itself as a tty driver.  The tty layer
+dynamically allocates a block of major and minor numbers in a quantity
+requested by the registering driver.  The hvcs driver asks the tty layer
+for 64 of these major/minor numbers by default to use for hvcs device node
+entries.
+
+If the default number of device entries is adequate then this driver can be
+built into the kernel.  If not, the default can be over-ridden by inserting
+the driver as a module with insmod parameters.
+
+3.1 Built-in:
+-------------
+
+The following menuconfig example demonstrates selecting to build this
+driver into the kernel::
+
+       Device Drivers  --->
+               Character devices  --->
+                       <*> IBM Hypervisor Virtual Console Server Support
+
+Begin the kernel make process.
+
+3.2 Module:
+-----------
+
+The following menuconfig example demonstrates selecting to build this
+driver as a kernel module::
+
+       Device Drivers  --->
+               Character devices  --->
+                       <M> IBM Hypervisor Virtual Console Server Support
+
+The make process will build the following kernel modules:
+
+       - hvcs.ko
+       - hvcserver.ko
+
+To insert the module with the default allocation execute the following
+commands in the order they appear::
+
+       insmod hvcserver.ko
+       insmod hvcs.ko
+
+The hvcserver module contains architecture specific firmware calls and must
+be inserted first, otherwise the hvcs module will not find some of the
+symbols it expects.
+
+To override the default use an insmod parameter as follows (requesting 4
+tty devices as an example)::
+
+       insmod hvcs.ko hvcs_parm_num_devs=4
+
+There is a maximum number of dev entries that can be specified on insmod.
+We think that 1024 is currently a decent maximum number of server adapters
+to allow.  This can always be changed by modifying the constant in the
+source file before building.
+
+NOTE: The length of time it takes to insmod the driver seems to be related
+to the number of tty interfaces the registering driver requests.
+
+In order to remove the driver module execute the following command::
+
+       rmmod hvcs.ko
+
+The recommended method for installing hvcs as a module is to use depmod to
+build a current modules.dep file in /lib/modules/`uname -r` and then
+execute::
+
+       modprobe hvcs hvcs_parm_num_devs=4
+
+The modules.dep file indicates that hvcserver.ko needs to be inserted
+before hvcs.ko and modprobe uses this file to smartly insert the modules in
+the proper order.
+
+The following modprobe command is used to remove hvcs and hvcserver in the
+proper order::
+
+       modprobe -r hvcs
+
+4. Installation:
+================
+
+The tty layer creates sysfs entries which contain the major and minor
+numbers allocated for the hvcs driver.  The following snippet of "tree"
+output of the sysfs directory shows where these numbers are presented::
+
+       sys/
+       |-- *other sysfs base dirs*
+       |
+       |-- class
+       |   |-- *other classes of devices*
+       |   |
+       |   `-- tty
+       |       |-- *other tty devices*
+       |       |
+       |       |-- hvcs0
+       |       |   `-- dev
+       |       |-- hvcs1
+       |       |   `-- dev
+       |       |-- hvcs2
+       |       |   `-- dev
+       |       |-- hvcs3
+       |       |   `-- dev
+       |       |
+       |       |-- *other tty devices*
+       |
+       |-- *other sysfs base dirs*
+
+For the above examples the following output is a result of cat'ing the
+"dev" entry in the hvcs directory::
+
+       Pow5:/sys/class/tty/hvcs0/ # cat dev
+       254:0
+
+       Pow5:/sys/class/tty/hvcs1/ # cat dev
+       254:1
+
+       Pow5:/sys/class/tty/hvcs2/ # cat dev
+       254:2
+
+       Pow5:/sys/class/tty/hvcs3/ # cat dev
+       254:3
+
+The output from reading the "dev" attribute is the char device major and
+minor numbers that the tty layer has allocated for this driver's use.  Most
+systems running hvcs will already have the device entries created or udev
+will do it automatically.
+
+Given the example output above, to manually create a /dev/hvcs* node entry
+mknod can be used as follows::
+
+       mknod /dev/hvcs0 c 254 0
+       mknod /dev/hvcs1 c 254 1
+       mknod /dev/hvcs2 c 254 2
+       mknod /dev/hvcs3 c 254 3
+
+Using mknod to manually create the device entries makes these device nodes
+persistent.  Once created they will exist prior to the driver insmod.
+
+Attempting to connect an application to /dev/hvcs* prior to insertion of
+the hvcs module will result in an error message similar to the following::
+
+       "/dev/hvcs*: No such device".
+
+NOTE: Just because there is a device node present doesn't mean that there
+is a vty-server device configured for that node.
+
+5. Connection
+=============
+
+Since this driver controls devices that provide a tty interface a user can
+interact with the device node entries using any standard tty-interactive
+method (e.g. "cat", "dd", "echo").  The intent of this driver however, is
+to provide real time console interaction with a Linux partition's console,
+which requires the use of applications that provide bi-directional,
+interactive I/O with a tty device.
+
+Applications (e.g. "minicom" and "screen") that act as terminal emulators
+or perform terminal type control sequence conversion on the data being
+passed through them are NOT acceptable for providing interactive console
+I/O.  These programs often emulate antiquated terminal types (vt100 and
+ANSI) and expect inbound data to take the form of one of these supported
+terminal types but they either do not convert, or do not _adequately_
+convert, outbound data into the terminal type of the terminal which invoked
+them (though screen makes an attempt and can apparently be configured with
+much termcap wrestling.)
+
+For this reason kermit and cu are two of the recommended applications for
+interacting with a Linux console via an hvcs device.  These programs simply
+act as a conduit for data transfer to and from the tty device.  They do not
+require inbound data to take the form of a particular terminal type, nor do
+they cook outbound data to a particular terminal type.
+
+In order to ensure proper functioning of console applications one must make
+sure that once connected to a /dev/hvcs console that the console's $TERM
+env variable is set to the exact terminal type of the terminal emulator
+used to launch the interactive I/O application.  If one is using xterm and
+kermit to connect to /dev/hvcs0 when the console prompt becomes available
+one should "export TERM=xterm" on the console.  This tells ncurses
+applications that are invoked from the console that they should output
+control sequences that xterm can understand.
+
+As a precautionary measure an hvcs user should always "exit" from their
+session before disconnecting an application such as kermit from the device
+node.  If this is not done, the next user to connect to the console will
+continue using the previous user's logged in session which includes
+using the $TERM variable that the previous user supplied.
+
+Hotplug add and remove of vty-server adapters affects which /dev/hvcs* node
+is used to connect to each vty-server adapter.  In order to determine which
+vty-server adapter is associated with which /dev/hvcs* node a special sysfs
+attribute has been added to each vty-server sysfs entry.  This entry is
+called "index" and showing it reveals an integer that refers to the
+/dev/hvcs* entry to use to connect to that device.  For instance cating the
+index attribute of vty-server adapter 30000004 shows the following::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat index
+       2
+
+This index of '2' means that in order to connect to vty-server adapter
+30000004 the user should interact with /dev/hvcs2.
+
+It should be noted that due to the system hotplug I/O capabilities of a
+system the /dev/hvcs* entry that interacts with a particular vty-server
+adapter is not guaranteed to remain the same across system reboots.  Look
+in the Q & A section for more on this issue.
+
+6. Disconnection
+================
+
+As a security feature to prevent the delivery of stale data to an
+unintended target the Power5 system firmware disables the fetching of data
+and discards that data when a connection between a vty-server and a vty has
+been severed.  As an example, when a vty-server is immediately disconnected
+from a vty following output of data to the vty the vty adapter may not have
+enough time between when it received the data interrupt and when the
+connection was severed to fetch the data from firmware before the fetch is
+disabled by firmware.
+
+When hvcs is being used to serve consoles this behavior is not a huge issue
+because the adapter stays connected for large amounts of time following
+almost all data writes.  When hvcs is being used as a tty conduit to tunnel
+data between two partitions [see Q & A below] this is a huge problem
+because the standard Linux behavior when cat'ing or dd'ing data to a device
+is to open the tty, send the data, and then close the tty.  If this driver
+manually terminated vty-server connections on tty close this would close
+the vty-server and vty connection before the target vty has had a chance to
+fetch the data.
+
+Additionally, disconnecting a vty-server and vty only on module removal or
+adapter removal is impractical because other vty-servers in other
+partitions may require the usage of the target vty at any time.
+
+Due to this behavioral restriction disconnection of vty-servers from the
+connected vty is a manual procedure using a write to a sysfs attribute
+outlined below, on the other hand the initial vty-server connection to a
+vty is established automatically by this driver.  Manual vty-server
+connection is never required.
+
+In order to terminate the connection between a vty-server and vty the
+"vterm_state" sysfs attribute within each vty-server's sysfs entry is used.
+Reading this attribute reveals the current connection state of the
+vty-server adapter.  A zero means that the vty-server is not connected to a
+vty.  A one indicates that a connection is active.
+
+Writing a '0' (zero) to the vterm_state attribute will disconnect the VTERM
+connection between the vty-server and target vty ONLY if the vterm_state
+previously read '1'.  The write directive is ignored if the vterm_state
+read '0' or if any value other than '0' was written to the vterm_state
+attribute.  The following example will show the method used for verifying
+the vty-server connection status and disconnecting a vty-server connection::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
+       1
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo 0 > vterm_state
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
+       0
+
+All vty-server connections are automatically terminated when the device is
+hotplug removed and when the module is removed.
+
+7. Configuration
+================
+
+Each vty-server has a sysfs entry in the /sys/devices/vio directory, which
+is symlinked in several other sysfs tree directories, notably under the
+hvcs driver entry, which looks like the following example::
+
+       Pow5:/sys/bus/vio/drivers/hvcs # ls
+       .  ..  30000003  30000004  rescan
+
+By design, firmware notifies the hvcs driver of vty-server lifetimes and
+partner vty removals but not the addition of partner vtys.  Since an HMC
+Super Admin can add partner info dynamically we have provided the hvcs
+driver sysfs directory with the "rescan" update attribute which will query
+firmware and update the partner info for all the vty-servers that this
+driver manages.  Writing a '1' to the attribute triggers the update.  An
+explicit example follows:
+
+       Pow5:/sys/bus/vio/drivers/hvcs # echo 1 > rescan
+
+Reading the attribute will indicate a state of '1' or '0'.  A one indicates
+that an update is in process.  A zero indicates that an update has
+completed or was never executed.
+
+Vty-server entries in this directory are a 32 bit partition unique unit
+address that is created by firmware.  An example vty-server sysfs entry
+looks like the following::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
+       .   current_vty   devspec       name          partner_vtys
+       ..  index         partner_clcs  vterm_state
+
+Each entry is provided, by default with a "name" attribute.  Reading the
+"name" attribute will reveal the device type as shown in the following
+example::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000003 # cat name
+       vty-server
+
+Each entry is also provided, by default, with a "devspec" attribute which
+reveals the full device specification when read, as shown in the following
+example::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat devspec
+       /vdevice/vty-server@30000004
+
+Each vty-server sysfs dir is provided with two read-only attributes that
+provide lists of easily parsed partner vty data: "partner_vtys" and
+"partner_clcs"::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_vtys
+       30000000
+       30000001
+       30000002
+       30000000
+       30000000
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_clcs
+       U5112.428.103048A-V3-C0
+       U5112.428.103048A-V3-C2
+       U5112.428.103048A-V3-C3
+       U5112.428.103048A-V4-C0
+       U5112.428.103048A-V5-C0
+
+Reading partner_vtys returns a list of partner vtys.  Vty unit address
+numbering is only per-partition-unique so entries will frequently repeat.
+
+Reading partner_clcs returns a list of "converged location codes" which are
+composed of a system serial number followed by "-V*", where the '*' is the
+target partition number, and "-C*", where the '*' is the slot of the
+adapter.  The first vty partner corresponds to the first clc item, the
+second vty partner to the second clc item, etc.
+
+A vty-server can only be connected to a single vty at a time.  The entry,
+"current_vty" prints the clc of the currently selected partner vty when
+read.
+
+The current_vty can be changed by writing a valid partner clc to the entry
+as in the following example::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo U5112.428.10304
+       8A-V4-C0 > current_vty
+
+Changing the current_vty when a vty-server is already connected to a vty
+does not affect the current connection.  The change takes effect when the
+currently open connection is freed.
+
+Information on the "vterm_state" attribute was covered earlier on the
+chapter entitled "disconnection".
+
+8. Questions & Answers:
+=======================
+
+Q: What are the security concerns involving hvcs?
+
+A: There are three main security concerns:
+
+       1. The creator of the /dev/hvcs* nodes has the ability to restrict
+       the access of the device entries to certain users or groups.  It
+       may be best to create a special hvcs group privilege for providing
+       access to system consoles.
+
+       2. To provide network security when grabbing the console it is
+       suggested that the user connect to the console hosting partition
+       using a secure method, such as SSH or sit at a hardware console.
+
+       3. Make sure to exit the user session when done with a console or
+       the next vty-server connection (which may be from another
+       partition) will experience the previously logged in session.
+
+---------------------------------------------------------------------------
+
+Q: How do I multiplex a console that I grab through hvcs so that other
+people can see it:
+
+A: You can use "screen" to directly connect to the /dev/hvcs* device and
+setup a session on your machine with the console group privileges.  As
+pointed out earlier by default screen doesn't provide the termcap settings
+for most terminal emulators to provide adequate character conversion from
+term type "screen" to others.  This means that curses based programs may
+not display properly in screen sessions.
+
+---------------------------------------------------------------------------
+
+Q: Why are the colors all messed up?
+Q: Why are the control characters acting strange or not working?
+Q: Why is the console output all strange and unintelligible?
+
+A: Please see the preceding section on "Connection" for a discussion of how
+applications can affect the display of character control sequences.
+Additionally, just because you logged into the console using and xterm
+doesn't mean someone else didn't log into the console with the HMC console
+(vt320) before you and leave the session logged in.  The best thing to do
+is to export TERM to the terminal type of your terminal emulator when you
+get the console.  Additionally make sure to "exit" the console before you
+disconnect from the console.  This will ensure that the next user gets
+their own TERM type set when they login.
+
+---------------------------------------------------------------------------
+
+Q: When I try to CONNECT kermit to an hvcs device I get:
+"Sorry, can't open connection: /dev/hvcs*"What is happening?
+
+A: Some other Power5 console mechanism has a connection to the vty and
+isn't giving it up.  You can try to force disconnect the consoles from the
+HMC by right clicking on the partition and then selecting "close terminal".
+Otherwise you have to hunt down the people who have console authority.  It
+is possible that you already have the console open using another kermit
+session and just forgot about it.  Please review the console options for
+Power5 systems to determine the many ways a system console can be held.
+
+OR
+
+A: Another user may not have a connectivity method currently attached to a
+/dev/hvcs device but the vterm_state may reveal that they still have the
+vty-server connection established.  They need to free this using the method
+outlined in the section on "Disconnection" in order for others to connect
+to the target vty.
+
+OR
+
+A: The user profile you are using to execute kermit probably doesn't have
+permissions to use the /dev/hvcs* device.
+
+OR
+
+A: You probably haven't inserted the hvcs.ko module yet but the /dev/hvcs*
+entry still exists (on systems without udev).
+
+OR
+
+A: There is not a corresponding vty-server device that maps to an existing
+/dev/hvcs* entry.
+
+---------------------------------------------------------------------------
+
+Q: When I try to CONNECT kermit to an hvcs device I get:
+"Sorry, write access to UUCP lockfile directory denied."
+
+A: The /dev/hvcs* entry you have specified doesn't exist where you said it
+does?  Maybe you haven't inserted the module (on systems with udev).
+
+---------------------------------------------------------------------------
+
+Q: If I already have one Linux partition installed can I use hvcs on said
+partition to provide the console for the install of a second Linux
+partition?
+
+A: Yes granted that your are connected to the /dev/hvcs* device using
+kermit or cu or some other program that doesn't provide terminal emulation.
+
+---------------------------------------------------------------------------
+
+Q: Can I connect to more than one partition's console at a time using this
+driver?
+
+A: Yes.  Of course this means that there must be more than one vty-server
+configured for this partition and each must point to a disconnected vty.
+
+---------------------------------------------------------------------------
+
+Q: Does the hvcs driver support dynamic (hotplug) addition of devices?
+
+A: Yes, if you have dlpar and hotplug enabled for your system and it has
+been built into the kernel the hvcs drivers is configured to dynamically
+handle additions of new devices and removals of unused devices.
+
+---------------------------------------------------------------------------
+
+Q: For some reason /dev/hvcs* doesn't map to the same vty-server adapter
+after a reboot.  What happened?
+
+A: Assignment of vty-server adapters to /dev/hvcs* entries is always done
+in the order that the adapters are exposed.  Due to hotplug capabilities of
+this driver assignment of hotplug added vty-servers may be in a different
+order than how they would be exposed on module load.  Rebooting or
+reloading the module after dynamic addition may result in the /dev/hvcs*
+and vty-server coupling changing if a vty-server adapter was added in a
+slot between two other vty-server adapters.  Refer to the section above
+on how to determine which vty-server goes with which /dev/hvcs* node.
+Hint; look at the sysfs "index" attribute for the vty-server.
+
+---------------------------------------------------------------------------
+
+Q: Can I use /dev/hvcs* as a conduit to another partition and use a tty
+device on that partition as the other end of the pipe?
+
+A: Yes, on Power5 platforms the hvc_console driver provides a tty interface
+for extra /dev/hvc* devices (where /dev/hvc0 is most likely the console).
+In order to get a tty conduit working between the two partitions the HMC
+Super Admin must create an additional "serial server" for the target
+partition with the HMC gui which will show up as /dev/hvc* when the target
+partition is rebooted.
+
+The HMC Super Admin then creates an additional "serial client" for the
+current partition and points this at the target partition's newly created
+"serial server" adapter (remember the slot).  This shows up as an
+additional /dev/hvcs* device.
+
+Now a program on the target system can be configured to read or write to
+/dev/hvc* and another program on the current partition can be configured to
+read or write to /dev/hvcs*.  Now you have a tty conduit between two
+partitions.
+
+---------------------------------------------------------------------------
+
+9. Reporting Bugs:
+==================
+
+The proper channel for reporting bugs is either through the Linux OS
+distribution company that provided your OS or by posting issues to the
+PowerPC development mailing list at:
+
+linuxppc-dev@lists.ozlabs.org
+
+This request is to provide a documented and searchable public exchange
+of the problems and solutions surrounding this driver for the benefit of
+all users.
diff --git a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.txt
deleted file mode 100644 (file)
index a730ca5..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-===========================================================================
-                                  HVCS
-       IBM "Hypervisor Virtual Console Server" Installation Guide
-                         for Linux Kernel 2.6.4+
-                   Copyright (C) 2004 IBM Corporation
-
-===========================================================================
-NOTE:Eight space tabs are the optimum editor setting for reading this file.
-===========================================================================
-
-              Author(s) :  Ryan S. Arnold <rsa@us.ibm.com>
-                      Date Created: March, 02, 2004
-                      Last Changed: August, 24, 2004
-
----------------------------------------------------------------------------
-Table of contents:
-
-       1.  Driver Introduction:
-       2.  System Requirements
-       3.  Build Options:
-               3.1  Built-in:
-               3.2  Module:
-       4.  Installation:
-       5.  Connection:
-       6.  Disconnection:
-       7.  Configuration:
-       8.  Questions & Answers:
-       9.  Reporting Bugs:
-
----------------------------------------------------------------------------
-1. Driver Introduction:
-
-This is the device driver for the IBM Hypervisor Virtual Console Server,
-"hvcs".  The IBM hvcs provides a tty driver interface to allow Linux user
-space applications access to the system consoles of logically partitioned
-operating systems (Linux and AIX) running on the same partitioned Power5
-ppc64 system.  Physical hardware consoles per partition are not practical
-on this hardware so system consoles are accessed by this driver using
-firmware interfaces to virtual terminal devices.
-
----------------------------------------------------------------------------
-2. System Requirements:
-
-This device driver was written using 2.6.4 Linux kernel APIs and will only
-build and run on kernels of this version or later.
-
-This driver was written to operate solely on IBM Power5 ppc64 hardware
-though some care was taken to abstract the architecture dependent firmware
-calls from the driver code.
-
-Sysfs must be mounted on the system so that the user can determine which
-major and minor numbers are associated with each vty-server.  Directions
-for sysfs mounting are outside the scope of this document.
-
----------------------------------------------------------------------------
-3. Build Options:
-
-The hvcs driver registers itself as a tty driver.  The tty layer
-dynamically allocates a block of major and minor numbers in a quantity
-requested by the registering driver.  The hvcs driver asks the tty layer
-for 64 of these major/minor numbers by default to use for hvcs device node
-entries.
-
-If the default number of device entries is adequate then this driver can be
-built into the kernel.  If not, the default can be over-ridden by inserting
-the driver as a module with insmod parameters.
-
----------------------------------------------------------------------------
-3.1 Built-in:
-
-The following menuconfig example demonstrates selecting to build this
-driver into the kernel.
-
-       Device Drivers  --->
-               Character devices  --->
-                       <*> IBM Hypervisor Virtual Console Server Support
-
-Begin the kernel make process.
-
----------------------------------------------------------------------------
-3.2 Module:
-
-The following menuconfig example demonstrates selecting to build this
-driver as a kernel module.
-
-       Device Drivers  --->
-               Character devices  --->
-                       <M> IBM Hypervisor Virtual Console Server Support
-
-The make process will build the following kernel modules:
-
-       hvcs.ko
-       hvcserver.ko
-
-To insert the module with the default allocation execute the following
-commands in the order they appear:
-
-       insmod hvcserver.ko
-       insmod hvcs.ko
-
-The hvcserver module contains architecture specific firmware calls and must
-be inserted first, otherwise the hvcs module will not find some of the
-symbols it expects.
-
-To override the default use an insmod parameter as follows (requesting 4
-tty devices as an example):
-
-       insmod hvcs.ko hvcs_parm_num_devs=4
-
-There is a maximum number of dev entries that can be specified on insmod.
-We think that 1024 is currently a decent maximum number of server adapters
-to allow.  This can always be changed by modifying the constant in the
-source file before building.
-
-NOTE: The length of time it takes to insmod the driver seems to be related
-to the number of tty interfaces the registering driver requests.
-
-In order to remove the driver module execute the following command:
-
-       rmmod hvcs.ko
-
-The recommended method for installing hvcs as a module is to use depmod to
-build a current modules.dep file in /lib/modules/`uname -r` and then
-execute:
-
-modprobe hvcs hvcs_parm_num_devs=4
-
-The modules.dep file indicates that hvcserver.ko needs to be inserted
-before hvcs.ko and modprobe uses this file to smartly insert the modules in
-the proper order.
-
-The following modprobe command is used to remove hvcs and hvcserver in the
-proper order:
-
-modprobe -r hvcs
-
----------------------------------------------------------------------------
-4. Installation:
-
-The tty layer creates sysfs entries which contain the major and minor
-numbers allocated for the hvcs driver.  The following snippet of "tree"
-output of the sysfs directory shows where these numbers are presented:
-
-       sys/
-       |-- *other sysfs base dirs*
-       |
-       |-- class
-       |   |-- *other classes of devices*
-       |   |
-       |   `-- tty
-       |       |-- *other tty devices*
-       |       |
-       |       |-- hvcs0
-       |       |   `-- dev
-       |       |-- hvcs1
-       |       |   `-- dev
-       |       |-- hvcs2
-       |       |   `-- dev
-       |       |-- hvcs3
-       |       |   `-- dev
-       |       |
-       |       |-- *other tty devices*
-       |
-       |-- *other sysfs base dirs*
-
-For the above examples the following output is a result of cat'ing the
-"dev" entry in the hvcs directory:
-
-       Pow5:/sys/class/tty/hvcs0/ # cat dev
-       254:0
-
-       Pow5:/sys/class/tty/hvcs1/ # cat dev
-       254:1
-
-       Pow5:/sys/class/tty/hvcs2/ # cat dev
-       254:2
-
-       Pow5:/sys/class/tty/hvcs3/ # cat dev
-       254:3
-
-The output from reading the "dev" attribute is the char device major and
-minor numbers that the tty layer has allocated for this driver's use.  Most
-systems running hvcs will already have the device entries created or udev
-will do it automatically.
-
-Given the example output above, to manually create a /dev/hvcs* node entry
-mknod can be used as follows:
-
-       mknod /dev/hvcs0 c 254 0
-       mknod /dev/hvcs1 c 254 1
-       mknod /dev/hvcs2 c 254 2
-       mknod /dev/hvcs3 c 254 3
-
-Using mknod to manually create the device entries makes these device nodes
-persistent.  Once created they will exist prior to the driver insmod.
-
-Attempting to connect an application to /dev/hvcs* prior to insertion of
-the hvcs module will result in an error message similar to the following:
-
-       "/dev/hvcs*: No such device".
-
-NOTE: Just because there is a device node present doesn't mean that there
-is a vty-server device configured for that node.
-
----------------------------------------------------------------------------
-5. Connection
-
-Since this driver controls devices that provide a tty interface a user can
-interact with the device node entries using any standard tty-interactive
-method (e.g. "cat", "dd", "echo").  The intent of this driver however, is
-to provide real time console interaction with a Linux partition's console,
-which requires the use of applications that provide bi-directional,
-interactive I/O with a tty device.
-
-Applications (e.g. "minicom" and "screen") that act as terminal emulators
-or perform terminal type control sequence conversion on the data being
-passed through them are NOT acceptable for providing interactive console
-I/O.  These programs often emulate antiquated terminal types (vt100 and
-ANSI) and expect inbound data to take the form of one of these supported
-terminal types but they either do not convert, or do not _adequately_
-convert, outbound data into the terminal type of the terminal which invoked
-them (though screen makes an attempt and can apparently be configured with
-much termcap wrestling.)
-
-For this reason kermit and cu are two of the recommended applications for
-interacting with a Linux console via an hvcs device.  These programs simply
-act as a conduit for data transfer to and from the tty device.  They do not
-require inbound data to take the form of a particular terminal type, nor do
-they cook outbound data to a particular terminal type.
-
-In order to ensure proper functioning of console applications one must make
-sure that once connected to a /dev/hvcs console that the console's $TERM
-env variable is set to the exact terminal type of the terminal emulator
-used to launch the interactive I/O application.  If one is using xterm and
-kermit to connect to /dev/hvcs0 when the console prompt becomes available
-one should "export TERM=xterm" on the console.  This tells ncurses
-applications that are invoked from the console that they should output
-control sequences that xterm can understand.
-
-As a precautionary measure an hvcs user should always "exit" from their
-session before disconnecting an application such as kermit from the device
-node.  If this is not done, the next user to connect to the console will
-continue using the previous user's logged in session which includes
-using the $TERM variable that the previous user supplied.
-
-Hotplug add and remove of vty-server adapters affects which /dev/hvcs* node
-is used to connect to each vty-server adapter.  In order to determine which
-vty-server adapter is associated with which /dev/hvcs* node a special sysfs
-attribute has been added to each vty-server sysfs entry.  This entry is
-called "index" and showing it reveals an integer that refers to the
-/dev/hvcs* entry to use to connect to that device.  For instance cating the
-index attribute of vty-server adapter 30000004 shows the following.
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat index
-       2
-
-This index of '2' means that in order to connect to vty-server adapter
-30000004 the user should interact with /dev/hvcs2.
-
-It should be noted that due to the system hotplug I/O capabilities of a
-system the /dev/hvcs* entry that interacts with a particular vty-server
-adapter is not guaranteed to remain the same across system reboots.  Look
-in the Q & A section for more on this issue.
-
----------------------------------------------------------------------------
-6. Disconnection
-
-As a security feature to prevent the delivery of stale data to an
-unintended target the Power5 system firmware disables the fetching of data
-and discards that data when a connection between a vty-server and a vty has
-been severed.  As an example, when a vty-server is immediately disconnected
-from a vty following output of data to the vty the vty adapter may not have
-enough time between when it received the data interrupt and when the
-connection was severed to fetch the data from firmware before the fetch is
-disabled by firmware.
-
-When hvcs is being used to serve consoles this behavior is not a huge issue
-because the adapter stays connected for large amounts of time following
-almost all data writes.  When hvcs is being used as a tty conduit to tunnel
-data between two partitions [see Q & A below] this is a huge problem
-because the standard Linux behavior when cat'ing or dd'ing data to a device
-is to open the tty, send the data, and then close the tty.  If this driver
-manually terminated vty-server connections on tty close this would close
-the vty-server and vty connection before the target vty has had a chance to
-fetch the data.
-
-Additionally, disconnecting a vty-server and vty only on module removal or
-adapter removal is impractical because other vty-servers in other
-partitions may require the usage of the target vty at any time.
-
-Due to this behavioral restriction disconnection of vty-servers from the
-connected vty is a manual procedure using a write to a sysfs attribute
-outlined below, on the other hand the initial vty-server connection to a
-vty is established automatically by this driver.  Manual vty-server
-connection is never required.
-
-In order to terminate the connection between a vty-server and vty the
-"vterm_state" sysfs attribute within each vty-server's sysfs entry is used.
-Reading this attribute reveals the current connection state of the
-vty-server adapter.  A zero means that the vty-server is not connected to a
-vty.  A one indicates that a connection is active.
-
-Writing a '0' (zero) to the vterm_state attribute will disconnect the VTERM
-connection between the vty-server and target vty ONLY if the vterm_state
-previously read '1'.  The write directive is ignored if the vterm_state
-read '0' or if any value other than '0' was written to the vterm_state
-attribute.  The following example will show the method used for verifying
-the vty-server connection status and disconnecting a vty-server connection.
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
-       1
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo 0 > vterm_state
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
-       0
-
-All vty-server connections are automatically terminated when the device is
-hotplug removed and when the module is removed.
-
----------------------------------------------------------------------------
-7. Configuration
-
-Each vty-server has a sysfs entry in the /sys/devices/vio directory, which
-is symlinked in several other sysfs tree directories, notably under the
-hvcs driver entry, which looks like the following example:
-
-       Pow5:/sys/bus/vio/drivers/hvcs # ls
-       .  ..  30000003  30000004  rescan
-
-By design, firmware notifies the hvcs driver of vty-server lifetimes and
-partner vty removals but not the addition of partner vtys.  Since an HMC
-Super Admin can add partner info dynamically we have provided the hvcs
-driver sysfs directory with the "rescan" update attribute which will query
-firmware and update the partner info for all the vty-servers that this
-driver manages.  Writing a '1' to the attribute triggers the update.  An
-explicit example follows:
-
-       Pow5:/sys/bus/vio/drivers/hvcs # echo 1 > rescan
-
-Reading the attribute will indicate a state of '1' or '0'.  A one indicates
-that an update is in process.  A zero indicates that an update has
-completed or was never executed.
-
-Vty-server entries in this directory are a 32 bit partition unique unit
-address that is created by firmware.  An example vty-server sysfs entry
-looks like the following:
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
-       .   current_vty   devspec       name          partner_vtys
-       ..  index         partner_clcs  vterm_state
-
-Each entry is provided, by default with a "name" attribute.  Reading the
-"name" attribute will reveal the device type as shown in the following
-example:
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000003 # cat name
-       vty-server
-
-Each entry is also provided, by default, with a "devspec" attribute which
-reveals the full device specification when read, as shown in the following
-example:
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat devspec
-       /vdevice/vty-server@30000004
-
-Each vty-server sysfs dir is provided with two read-only attributes that
-provide lists of easily parsed partner vty data: "partner_vtys" and
-"partner_clcs".
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_vtys
-       30000000
-       30000001
-       30000002
-       30000000
-       30000000
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_clcs
-       U5112.428.103048A-V3-C0
-       U5112.428.103048A-V3-C2
-       U5112.428.103048A-V3-C3
-       U5112.428.103048A-V4-C0
-       U5112.428.103048A-V5-C0
-
-Reading partner_vtys returns a list of partner vtys.  Vty unit address
-numbering is only per-partition-unique so entries will frequently repeat.
-
-Reading partner_clcs returns a list of "converged location codes" which are
-composed of a system serial number followed by "-V*", where the '*' is the
-target partition number, and "-C*", where the '*' is the slot of the
-adapter.  The first vty partner corresponds to the first clc item, the
-second vty partner to the second clc item, etc.
-
-A vty-server can only be connected to a single vty at a time.  The entry,
-"current_vty" prints the clc of the currently selected partner vty when
-read.
-
-The current_vty can be changed by writing a valid partner clc to the entry
-as in the following example:
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo U5112.428.10304
-       8A-V4-C0 > current_vty
-
-Changing the current_vty when a vty-server is already connected to a vty
-does not affect the current connection.  The change takes effect when the
-currently open connection is freed.
-
-Information on the "vterm_state" attribute was covered earlier on the
-chapter entitled "disconnection".
-
----------------------------------------------------------------------------
-8. Questions & Answers:
-===========================================================================
-Q: What are the security concerns involving hvcs?
-
-A: There are three main security concerns:
-
-       1. The creator of the /dev/hvcs* nodes has the ability to restrict
-       the access of the device entries to certain users or groups.  It
-       may be best to create a special hvcs group privilege for providing
-       access to system consoles.
-
-       2. To provide network security when grabbing the console it is
-       suggested that the user connect to the console hosting partition
-       using a secure method, such as SSH or sit at a hardware console.
-
-       3. Make sure to exit the user session when done with a console or
-       the next vty-server connection (which may be from another
-       partition) will experience the previously logged in session.
-
----------------------------------------------------------------------------
-Q: How do I multiplex a console that I grab through hvcs so that other
-people can see it:
-
-A: You can use "screen" to directly connect to the /dev/hvcs* device and
-setup a session on your machine with the console group privileges.  As
-pointed out earlier by default screen doesn't provide the termcap settings
-for most terminal emulators to provide adequate character conversion from
-term type "screen" to others.  This means that curses based programs may
-not display properly in screen sessions.
-
----------------------------------------------------------------------------
-Q: Why are the colors all messed up?
-Q: Why are the control characters acting strange or not working?
-Q: Why is the console output all strange and unintelligible?
-
-A: Please see the preceding section on "Connection" for a discussion of how
-applications can affect the display of character control sequences.
-Additionally, just because you logged into the console using and xterm
-doesn't mean someone else didn't log into the console with the HMC console
-(vt320) before you and leave the session logged in.  The best thing to do
-is to export TERM to the terminal type of your terminal emulator when you
-get the console.  Additionally make sure to "exit" the console before you
-disconnect from the console.  This will ensure that the next user gets
-their own TERM type set when they login.
-
----------------------------------------------------------------------------
-Q: When I try to CONNECT kermit to an hvcs device I get:
-"Sorry, can't open connection: /dev/hvcs*"What is happening?
-
-A: Some other Power5 console mechanism has a connection to the vty and
-isn't giving it up.  You can try to force disconnect the consoles from the
-HMC by right clicking on the partition and then selecting "close terminal".
-Otherwise you have to hunt down the people who have console authority.  It
-is possible that you already have the console open using another kermit
-session and just forgot about it.  Please review the console options for
-Power5 systems to determine the many ways a system console can be held.
-
-OR
-
-A: Another user may not have a connectivity method currently attached to a
-/dev/hvcs device but the vterm_state may reveal that they still have the
-vty-server connection established.  They need to free this using the method
-outlined in the section on "Disconnection" in order for others to connect
-to the target vty.
-
-OR
-
-A: The user profile you are using to execute kermit probably doesn't have
-permissions to use the /dev/hvcs* device.
-
-OR
-
-A: You probably haven't inserted the hvcs.ko module yet but the /dev/hvcs*
-entry still exists (on systems without udev).
-
-OR
-
-A: There is not a corresponding vty-server device that maps to an existing
-/dev/hvcs* entry.
-
----------------------------------------------------------------------------
-Q: When I try to CONNECT kermit to an hvcs device I get:
-"Sorry, write access to UUCP lockfile directory denied."
-
-A: The /dev/hvcs* entry you have specified doesn't exist where you said it
-does?  Maybe you haven't inserted the module (on systems with udev).
-
----------------------------------------------------------------------------
-Q: If I already have one Linux partition installed can I use hvcs on said
-partition to provide the console for the install of a second Linux
-partition?
-
-A: Yes granted that your are connected to the /dev/hvcs* device using
-kermit or cu or some other program that doesn't provide terminal emulation.
-
----------------------------------------------------------------------------
-Q: Can I connect to more than one partition's console at a time using this
-driver?
-
-A: Yes.  Of course this means that there must be more than one vty-server
-configured for this partition and each must point to a disconnected vty.
-
----------------------------------------------------------------------------
-Q: Does the hvcs driver support dynamic (hotplug) addition of devices?
-
-A: Yes, if you have dlpar and hotplug enabled for your system and it has
-been built into the kernel the hvcs drivers is configured to dynamically
-handle additions of new devices and removals of unused devices.
-
----------------------------------------------------------------------------
-Q: For some reason /dev/hvcs* doesn't map to the same vty-server adapter
-after a reboot.  What happened?
-
-A: Assignment of vty-server adapters to /dev/hvcs* entries is always done
-in the order that the adapters are exposed.  Due to hotplug capabilities of
-this driver assignment of hotplug added vty-servers may be in a different
-order than how they would be exposed on module load.  Rebooting or
-reloading the module after dynamic addition may result in the /dev/hvcs*
-and vty-server coupling changing if a vty-server adapter was added in a
-slot between two other vty-server adapters.  Refer to the section above
-on how to determine which vty-server goes with which /dev/hvcs* node.
-Hint; look at the sysfs "index" attribute for the vty-server.
-
----------------------------------------------------------------------------
-Q: Can I use /dev/hvcs* as a conduit to another partition and use a tty
-device on that partition as the other end of the pipe?
-
-A: Yes, on Power5 platforms the hvc_console driver provides a tty interface
-for extra /dev/hvc* devices (where /dev/hvc0 is most likely the console).
-In order to get a tty conduit working between the two partitions the HMC
-Super Admin must create an additional "serial server" for the target
-partition with the HMC gui which will show up as /dev/hvc* when the target
-partition is rebooted.
-
-The HMC Super Admin then creates an additional "serial client" for the
-current partition and points this at the target partition's newly created
-"serial server" adapter (remember the slot).  This shows up as an
-additional /dev/hvcs* device.
-
-Now a program on the target system can be configured to read or write to
-/dev/hvc* and another program on the current partition can be configured to
-read or write to /dev/hvcs*.  Now you have a tty conduit between two
-partitions.
-
----------------------------------------------------------------------------
-9. Reporting Bugs:
-
-The proper channel for reporting bugs is either through the Linux OS
-distribution company that provided your OS or by posting issues to the
-PowerPC development mailing list at:
-
-linuxppc-dev@lists.ozlabs.org
-
-This request is to provide a documented and searchable public exchange
-of the problems and solutions surrounding this driver for the benefit of
-all users.
diff --git a/Documentation/powerpc/index.rst b/Documentation/powerpc/index.rst
new file mode 100644 (file)
index 0000000..549b1cd
--- /dev/null
@@ -0,0 +1,34 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======
+powerpc
+=======
+
+.. toctree::
+    :maxdepth: 1
+
+    bootwrapper
+    cpu_families
+    cpu_features
+    cxl
+    cxlflash
+    dawr-power9
+    dscr
+    eeh-pci-error-recovery
+    firmware-assisted-dump
+    hvcs
+    isa-versions
+    mpc52xx
+    pci_iov_resource_on_powernv
+    pmu-ebb
+    ptrace
+    qe_firmware
+    syscall64-abi
+    transactional_memory
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
index 66c24140ebf108c4b58e9b3c6b80e5a32d25caad..a363d8c1603c942ff9eaf958e07dff483336c3bc 100644 (file)
@@ -1,13 +1,12 @@
-:orphan:
-
+==========================
 CPU to ISA Version Mapping
 ==========================
 
 Mapping of some CPU versions to relevant ISA versions.
 
-========= ====================
+========= ====================================================================
 CPU       Architecture version
-========= ====================
+========= ====================================================================
 Power9    Power ISA v3.0B
 Power8    Power ISA v2.07
 Power7    Power ISA v2.06
@@ -24,7 +23,7 @@ PPC970    - PowerPC User Instruction Set Architecture Book I v2.01
           - PowerPC Virtual Environment Architecture Book II v2.01
           - PowerPC Operating Environment Architecture Book III v2.01
           - Plus Altivec/VMX ~= 2.03
-========= ====================
+========= ====================================================================
 
 
 Key Features
@@ -60,9 +59,9 @@ Power5     No
 PPC970     No
 ========== ====
 
-========== ====================
+========== ====================================
 CPU        Transactional Memory
-========== ====================
+========== ====================================
 Power9     Yes (* see transactional_memory.txt)
 Power8     Yes
 Power7     No
@@ -73,4 +72,4 @@ Power5++   No
 Power5+    No
 Power5     No
 PPC970     No
-========== ====================
+========== ====================================
diff --git a/Documentation/powerpc/mpc52xx.rst b/Documentation/powerpc/mpc52xx.rst
new file mode 100644 (file)
index 0000000..8676ac6
--- /dev/null
@@ -0,0 +1,43 @@
+=============================
+Linux 2.6.x on MPC52xx family
+=============================
+
+For the latest info, go to http://www.246tNt.com/mpc52xx/
+
+To compile/use :
+
+  - U-Boot::
+
+     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
+        if you wish to ).
+     # make lite5200_defconfig
+     # make uImage
+
+     then, on U-boot:
+     => tftpboot 200000 uImage
+     => tftpboot 400000 pRamdisk
+     => bootm 200000 400000
+
+  - DBug::
+
+     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
+        if you wish to ).
+     # make lite5200_defconfig
+     # cp your_initrd.gz arch/ppc/boot/images/ramdisk.image.gz
+     # make zImage.initrd
+     # make
+
+     then in DBug:
+     DBug> dn -i zImage.initrd.lite5200
+
+
+Some remarks:
+
+ - The port is named mpc52xxx, and config options are PPC_MPC52xx. The MGT5100
+   is not supported, and I'm not sure anyone is interesting in working on it
+   so. I didn't took 5xxx because there's apparently a lot of 5xxx that have
+   nothing to do with the MPC5200. I also included the 'MPC' for the same
+   reason.
+ - Of course, I inspired myself from the 2.4 port. If you think I forgot to
+   mention you/your company in the copyright of some code, I'll correct it
+   ASAP.
diff --git a/Documentation/powerpc/mpc52xx.txt b/Documentation/powerpc/mpc52xx.txt
deleted file mode 100644 (file)
index 0d540a3..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-Linux 2.6.x on MPC52xx family
------------------------------
-
-For the latest info, go to http://www.246tNt.com/mpc52xx/
-
-To compile/use :
-
-  - U-Boot:
-     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
-        if you wish to ).
-     # make lite5200_defconfig
-     # make uImage
-
-     then, on U-boot:
-     => tftpboot 200000 uImage
-     => tftpboot 400000 pRamdisk
-     => bootm 200000 400000
-
-  - DBug:
-     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
-        if you wish to ).
-     # make lite5200_defconfig
-     # cp your_initrd.gz arch/ppc/boot/images/ramdisk.image.gz
-     # make zImage.initrd
-     # make
-
-     then in DBug:
-     DBug> dn -i zImage.initrd.lite5200
-
-
-Some remarks :
- - The port is named mpc52xxx, and config options are PPC_MPC52xx. The MGT5100
-   is not supported, and I'm not sure anyone is interesting in working on it
-   so. I didn't took 5xxx because there's apparently a lot of 5xxx that have
-   nothing to do with the MPC5200. I also included the 'MPC' for the same
-   reason.
- - Of course, I inspired myself from the 2.4 port. If you think I forgot to
-   mention you/your company in the copyright of some code, I'll correct it
-   ASAP.
diff --git a/Documentation/powerpc/pci_iov_resource_on_powernv.rst b/Documentation/powerpc/pci_iov_resource_on_powernv.rst
new file mode 100644 (file)
index 0000000..f5a5793
--- /dev/null
@@ -0,0 +1,312 @@
+===================================================
+PCI Express I/O Virtualization Resource on Powerenv
+===================================================
+
+Wei Yang <weiyang@linux.vnet.ibm.com>
+
+Benjamin Herrenschmidt <benh@au1.ibm.com>
+
+Bjorn Helgaas <bhelgaas@google.com>
+
+26 Aug 2014
+
+This document describes the requirement from hardware for PCI MMIO resource
+sizing and assignment on PowerKVM and how generic PCI code handles this
+requirement. The first two sections describe the concepts of Partitionable
+Endpoints and the implementation on P8 (IODA2). The next two sections talks
+about considerations on enabling SRIOV on IODA2.
+
+1. Introduction to Partitionable Endpoints
+==========================================
+
+A Partitionable Endpoint (PE) is a way to group the various resources
+associated with a device or a set of devices to provide isolation between
+partitions (i.e., filtering of DMA, MSIs etc.) and to provide a mechanism
+to freeze a device that is causing errors in order to limit the possibility
+of propagation of bad data.
+
+There is thus, in HW, a table of PE states that contains a pair of "frozen"
+state bits (one for MMIO and one for DMA, they get set together but can be
+cleared independently) for each PE.
+
+When a PE is frozen, all stores in any direction are dropped and all loads
+return all 1's value. MSIs are also blocked. There's a bit more state that
+captures things like the details of the error that caused the freeze etc., but
+that's not critical.
+
+The interesting part is how the various PCIe transactions (MMIO, DMA, ...)
+are matched to their corresponding PEs.
+
+The following section provides a rough description of what we have on P8
+(IODA2).  Keep in mind that this is all per PHB (PCI host bridge).  Each PHB
+is a completely separate HW entity that replicates the entire logic, so has
+its own set of PEs, etc.
+
+2. Implementation of Partitionable Endpoints on P8 (IODA2)
+==========================================================
+
+P8 supports up to 256 Partitionable Endpoints per PHB.
+
+  * Inbound
+
+    For DMA, MSIs and inbound PCIe error messages, we have a table (in
+    memory but accessed in HW by the chip) that provides a direct
+    correspondence between a PCIe RID (bus/dev/fn) with a PE number.
+    We call this the RTT.
+
+    - For DMA we then provide an entire address space for each PE that can
+      contain two "windows", depending on the value of PCI address bit 59.
+      Each window can be configured to be remapped via a "TCE table" (IOMMU
+      translation table), which has various configurable characteristics
+      not described here.
+
+    - For MSIs, we have two windows in the address space (one at the top of
+      the 32-bit space and one much higher) which, via a combination of the
+      address and MSI value, will result in one of the 2048 interrupts per
+      bridge being triggered.  There's a PE# in the interrupt controller
+      descriptor table as well which is compared with the PE# obtained from
+      the RTT to "authorize" the device to emit that specific interrupt.
+
+    - Error messages just use the RTT.
+
+  * Outbound.  That's where the tricky part is.
+
+    Like other PCI host bridges, the Power8 IODA2 PHB supports "windows"
+    from the CPU address space to the PCI address space.  There is one M32
+    window and sixteen M64 windows.  They have different characteristics.
+    First what they have in common: they forward a configurable portion of
+    the CPU address space to the PCIe bus and must be naturally aligned
+    power of two in size.  The rest is different:
+
+    - The M32 window:
+
+      * Is limited to 4GB in size.
+
+      * Drops the top bits of the address (above the size) and replaces
+       them with a configurable value.  This is typically used to generate
+       32-bit PCIe accesses.  We configure that window at boot from FW and
+       don't touch it from Linux; it's usually set to forward a 2GB
+       portion of address space from the CPU to PCIe
+       0x8000_0000..0xffff_ffff.  (Note: The top 64KB are actually
+       reserved for MSIs but this is not a problem at this point; we just
+       need to ensure Linux doesn't assign anything there, the M32 logic
+       ignores that however and will forward in that space if we try).
+
+      * It is divided into 256 segments of equal size.  A table in the chip
+       maps each segment to a PE#.  That allows portions of the MMIO space
+       to be assigned to PEs on a segment granularity.  For a 2GB window,
+       the segment granularity is 2GB/256 = 8MB.
+
+    Now, this is the "main" window we use in Linux today (excluding
+    SR-IOV).  We basically use the trick of forcing the bridge MMIO windows
+    onto a segment alignment/granularity so that the space behind a bridge
+    can be assigned to a PE.
+
+    Ideally we would like to be able to have individual functions in PEs
+    but that would mean using a completely different address allocation
+    scheme where individual function BARs can be "grouped" to fit in one or
+    more segments.
+
+    - The M64 windows:
+
+      * Must be at least 256MB in size.
+
+      * Do not translate addresses (the address on PCIe is the same as the
+       address on the PowerBus).  There is a way to also set the top 14
+       bits which are not conveyed by PowerBus but we don't use this.
+
+      * Can be configured to be segmented.  When not segmented, we can
+       specify the PE# for the entire window.  When segmented, a window
+       has 256 segments; however, there is no table for mapping a segment
+       to a PE#.  The segment number *is* the PE#.
+
+      * Support overlaps.  If an address is covered by multiple windows,
+       there's a defined ordering for which window applies.
+
+    We have code (fairly new compared to the M32 stuff) that exploits that
+    for large BARs in 64-bit space:
+
+    We configure an M64 window to cover the entire region of address space
+    that has been assigned by FW for the PHB (about 64GB, ignore the space
+    for the M32, it comes out of a different "reserve").  We configure it
+    as segmented.
+
+    Then we do the same thing as with M32, using the bridge alignment
+    trick, to match to those giant segments.
+
+    Since we cannot remap, we have two additional constraints:
+
+    - We do the PE# allocation *after* the 64-bit space has been assigned
+      because the addresses we use directly determine the PE#.  We then
+      update the M32 PE# for the devices that use both 32-bit and 64-bit
+      spaces or assign the remaining PE# to 32-bit only devices.
+
+    - We cannot "group" segments in HW, so if a device ends up using more
+      than one segment, we end up with more than one PE#.  There is a HW
+      mechanism to make the freeze state cascade to "companion" PEs but
+      that only works for PCIe error messages (typically used so that if
+      you freeze a switch, it freezes all its children).  So we do it in
+      SW.  We lose a bit of effectiveness of EEH in that case, but that's
+      the best we found.  So when any of the PEs freezes, we freeze the
+      other ones for that "domain".  We thus introduce the concept of
+      "master PE" which is the one used for DMA, MSIs, etc., and "secondary
+      PEs" that are used for the remaining M64 segments.
+
+    We would like to investigate using additional M64 windows in "single
+    PE" mode to overlay over specific BARs to work around some of that, for
+    example for devices with very large BARs, e.g., GPUs.  It would make
+    sense, but we haven't done it yet.
+
+3. Considerations for SR-IOV on PowerKVM
+========================================
+
+  * SR-IOV Background
+
+    The PCIe SR-IOV feature allows a single Physical Function (PF) to
+    support several Virtual Functions (VFs).  Registers in the PF's SR-IOV
+    Capability control the number of VFs and whether they are enabled.
+
+    When VFs are enabled, they appear in Configuration Space like normal
+    PCI devices, but the BARs in VF config space headers are unusual.  For
+    a non-VF device, software uses BARs in the config space header to
+    discover the BAR sizes and assign addresses for them.  For VF devices,
+    software uses VF BAR registers in the *PF* SR-IOV Capability to
+    discover sizes and assign addresses.  The BARs in the VF's config space
+    header are read-only zeros.
+
+    When a VF BAR in the PF SR-IOV Capability is programmed, it sets the
+    base address for all the corresponding VF(n) BARs.  For example, if the
+    PF SR-IOV Capability is programmed to enable eight VFs, and it has a
+    1MB VF BAR0, the address in that VF BAR sets the base of an 8MB region.
+    This region is divided into eight contiguous 1MB regions, each of which
+    is a BAR0 for one of the VFs.  Note that even though the VF BAR
+    describes an 8MB region, the alignment requirement is for a single VF,
+    i.e., 1MB in this example.
+
+  There are several strategies for isolating VFs in PEs:
+
+  - M32 window: There's one M32 window, and it is split into 256
+    equally-sized segments.  The finest granularity possible is a 256MB
+    window with 1MB segments.  VF BARs that are 1MB or larger could be
+    mapped to separate PEs in this window.  Each segment can be
+    individually mapped to a PE via the lookup table, so this is quite
+    flexible, but it works best when all the VF BARs are the same size.  If
+    they are different sizes, the entire window has to be small enough that
+    the segment size matches the smallest VF BAR, which means larger VF
+    BARs span several segments.
+
+  - Non-segmented M64 window: A non-segmented M64 window is mapped entirely
+    to a single PE, so it could only isolate one VF.
+
+  - Single segmented M64 windows: A segmented M64 window could be used just
+    like the M32 window, but the segments can't be individually mapped to
+    PEs (the segment number is the PE#), so there isn't as much
+    flexibility.  A VF with multiple BARs would have to be in a "domain" of
+    multiple PEs, which is not as well isolated as a single PE.
+
+  - Multiple segmented M64 windows: As usual, each window is split into 256
+    equally-sized segments, and the segment number is the PE#.  But if we
+    use several M64 windows, they can be set to different base addresses
+    and different segment sizes.  If we have VFs that each have a 1MB BAR
+    and a 32MB BAR, we could use one M64 window to assign 1MB segments and
+    another M64 window to assign 32MB segments.
+
+  Finally, the plan to use M64 windows for SR-IOV, which will be described
+  more in the next two sections.  For a given VF BAR, we need to
+  effectively reserve the entire 256 segments (256 * VF BAR size) and
+  position the VF BAR to start at the beginning of a free range of
+  segments/PEs inside that M64 window.
+
+  The goal is of course to be able to give a separate PE for each VF.
+
+  The IODA2 platform has 16 M64 windows, which are used to map MMIO
+  range to PE#.  Each M64 window defines one MMIO range and this range is
+  divided into 256 segments, with each segment corresponding to one PE.
+
+  We decide to leverage this M64 window to map VFs to individual PEs, since
+  SR-IOV VF BARs are all the same size.
+
+  But doing so introduces another problem: total_VFs is usually smaller
+  than the number of M64 window segments, so if we map one VF BAR directly
+  to one M64 window, some part of the M64 window will map to another
+  device's MMIO range.
+
+  IODA supports 256 PEs, so segmented windows contain 256 segments, so if
+  total_VFs is less than 256, we have the situation in Figure 1.0, where
+  segments [total_VFs, 255] of the M64 window may map to some MMIO range on
+  other devices::
+
+     0      1                     total_VFs - 1
+     +------+------+-     -+------+------+
+     |      |      |  ...  |      |      |
+     +------+------+-     -+------+------+
+
+                           VF(n) BAR space
+
+     0      1                     total_VFs - 1                255
+     +------+------+-     -+------+------+-      -+------+------+
+     |      |      |  ...  |      |      |   ...  |      |      |
+     +------+------+-     -+------+------+-      -+------+------+
+
+                           M64 window
+
+               Figure 1.0 Direct map VF(n) BAR space
+
+  Our current solution is to allocate 256 segments even if the VF(n) BAR
+  space doesn't need that much, as shown in Figure 1.1::
+
+     0      1                     total_VFs - 1                255
+     +------+------+-     -+------+------+-      -+------+------+
+     |      |      |  ...  |      |      |   ...  |      |      |
+     +------+------+-     -+------+------+-      -+------+------+
+
+                           VF(n) BAR space + extra
+
+     0      1                     total_VFs - 1                255
+     +------+------+-     -+------+------+-      -+------+------+
+     |      |      |  ...  |      |      |   ...  |      |      |
+     +------+------+-     -+------+------+-      -+------+------+
+
+                          M64 window
+
+               Figure 1.1 Map VF(n) BAR space + extra
+
+  Allocating the extra space ensures that the entire M64 window will be
+  assigned to this one SR-IOV device and none of the space will be
+  available for other devices.  Note that this only expands the space
+  reserved in software; there are still only total_VFs VFs, and they only
+  respond to segments [0, total_VFs - 1].  There's nothing in hardware that
+  responds to segments [total_VFs, 255].
+
+4. Implications for the Generic PCI Code
+========================================
+
+The PCIe SR-IOV spec requires that the base of the VF(n) BAR space be
+aligned to the size of an individual VF BAR.
+
+In IODA2, the MMIO address determines the PE#.  If the address is in an M32
+window, we can set the PE# by updating the table that translates segments
+to PE#s.  Similarly, if the address is in an unsegmented M64 window, we can
+set the PE# for the window.  But if it's in a segmented M64 window, the
+segment number is the PE#.
+
+Therefore, the only way to control the PE# for a VF is to change the base
+of the VF(n) BAR space in the VF BAR.  If the PCI core allocates the exact
+amount of space required for the VF(n) BAR space, the VF BAR value is fixed
+and cannot be changed.
+
+On the other hand, if the PCI core allocates additional space, the VF BAR
+value can be changed as long as the entire VF(n) BAR space remains inside
+the space allocated by the core.
+
+Ideally the segment size will be the same as an individual VF BAR size.
+Then each VF will be in its own PE.  The VF BARs (and therefore the PE#s)
+are contiguous.  If VF0 is in PE(x), then VF(n) is in PE(x+n).  If we
+allocate 256 segments, there are (256 - numVFs) choices for the PE# of VF0.
+
+If the segment size is smaller than the VF BAR size, it will take several
+segments to cover a VF BAR, and a VF will be in several PEs.  This is
+possible, but the isolation isn't as good, and it reduces the number of PE#
+choices because instead of consuming only numVFs segments, the VF(n) BAR
+space will consume (numVFs * n) segments.  That means there aren't as many
+available segments for adjusting base of the VF(n) BAR space.
diff --git a/Documentation/powerpc/pci_iov_resource_on_powernv.txt b/Documentation/powerpc/pci_iov_resource_on_powernv.txt
deleted file mode 100644 (file)
index b55c5cd..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-Wei Yang <weiyang@linux.vnet.ibm.com>
-Benjamin Herrenschmidt <benh@au1.ibm.com>
-Bjorn Helgaas <bhelgaas@google.com>
-26 Aug 2014
-
-This document describes the requirement from hardware for PCI MMIO resource
-sizing and assignment on PowerKVM and how generic PCI code handles this
-requirement. The first two sections describe the concepts of Partitionable
-Endpoints and the implementation on P8 (IODA2). The next two sections talks
-about considerations on enabling SRIOV on IODA2.
-
-1. Introduction to Partitionable Endpoints
-
-A Partitionable Endpoint (PE) is a way to group the various resources
-associated with a device or a set of devices to provide isolation between
-partitions (i.e., filtering of DMA, MSIs etc.) and to provide a mechanism
-to freeze a device that is causing errors in order to limit the possibility
-of propagation of bad data.
-
-There is thus, in HW, a table of PE states that contains a pair of "frozen"
-state bits (one for MMIO and one for DMA, they get set together but can be
-cleared independently) for each PE.
-
-When a PE is frozen, all stores in any direction are dropped and all loads
-return all 1's value. MSIs are also blocked. There's a bit more state that
-captures things like the details of the error that caused the freeze etc., but
-that's not critical.
-
-The interesting part is how the various PCIe transactions (MMIO, DMA, ...)
-are matched to their corresponding PEs.
-
-The following section provides a rough description of what we have on P8
-(IODA2).  Keep in mind that this is all per PHB (PCI host bridge).  Each PHB
-is a completely separate HW entity that replicates the entire logic, so has
-its own set of PEs, etc.
-
-2. Implementation of Partitionable Endpoints on P8 (IODA2)
-
-P8 supports up to 256 Partitionable Endpoints per PHB.
-
-  * Inbound
-
-    For DMA, MSIs and inbound PCIe error messages, we have a table (in
-    memory but accessed in HW by the chip) that provides a direct
-    correspondence between a PCIe RID (bus/dev/fn) with a PE number.
-    We call this the RTT.
-
-    - For DMA we then provide an entire address space for each PE that can
-      contain two "windows", depending on the value of PCI address bit 59.
-      Each window can be configured to be remapped via a "TCE table" (IOMMU
-      translation table), which has various configurable characteristics
-      not described here.
-
-    - For MSIs, we have two windows in the address space (one at the top of
-      the 32-bit space and one much higher) which, via a combination of the
-      address and MSI value, will result in one of the 2048 interrupts per
-      bridge being triggered.  There's a PE# in the interrupt controller
-      descriptor table as well which is compared with the PE# obtained from
-      the RTT to "authorize" the device to emit that specific interrupt.
-
-    - Error messages just use the RTT.
-
-  * Outbound.  That's where the tricky part is.
-
-    Like other PCI host bridges, the Power8 IODA2 PHB supports "windows"
-    from the CPU address space to the PCI address space.  There is one M32
-    window and sixteen M64 windows.  They have different characteristics.
-    First what they have in common: they forward a configurable portion of
-    the CPU address space to the PCIe bus and must be naturally aligned
-    power of two in size.  The rest is different:
-
-    - The M32 window:
-
-      * Is limited to 4GB in size.
-
-      * Drops the top bits of the address (above the size) and replaces
-       them with a configurable value.  This is typically used to generate
-       32-bit PCIe accesses.  We configure that window at boot from FW and
-       don't touch it from Linux; it's usually set to forward a 2GB
-       portion of address space from the CPU to PCIe
-       0x8000_0000..0xffff_ffff.  (Note: The top 64KB are actually
-       reserved for MSIs but this is not a problem at this point; we just
-       need to ensure Linux doesn't assign anything there, the M32 logic
-       ignores that however and will forward in that space if we try).
-
-      * It is divided into 256 segments of equal size.  A table in the chip
-       maps each segment to a PE#.  That allows portions of the MMIO space
-       to be assigned to PEs on a segment granularity.  For a 2GB window,
-       the segment granularity is 2GB/256 = 8MB.
-
-    Now, this is the "main" window we use in Linux today (excluding
-    SR-IOV).  We basically use the trick of forcing the bridge MMIO windows
-    onto a segment alignment/granularity so that the space behind a bridge
-    can be assigned to a PE.
-
-    Ideally we would like to be able to have individual functions in PEs
-    but that would mean using a completely different address allocation
-    scheme where individual function BARs can be "grouped" to fit in one or
-    more segments.
-
-    - The M64 windows:
-
-      * Must be at least 256MB in size.
-
-      * Do not translate addresses (the address on PCIe is the same as the
-       address on the PowerBus).  There is a way to also set the top 14
-       bits which are not conveyed by PowerBus but we don't use this.
-
-      * Can be configured to be segmented.  When not segmented, we can
-       specify the PE# for the entire window.  When segmented, a window
-       has 256 segments; however, there is no table for mapping a segment
-       to a PE#.  The segment number *is* the PE#.
-
-      * Support overlaps.  If an address is covered by multiple windows,
-       there's a defined ordering for which window applies.
-
-    We have code (fairly new compared to the M32 stuff) that exploits that
-    for large BARs in 64-bit space:
-
-    We configure an M64 window to cover the entire region of address space
-    that has been assigned by FW for the PHB (about 64GB, ignore the space
-    for the M32, it comes out of a different "reserve").  We configure it
-    as segmented.
-
-    Then we do the same thing as with M32, using the bridge alignment
-    trick, to match to those giant segments.
-
-    Since we cannot remap, we have two additional constraints:
-
-    - We do the PE# allocation *after* the 64-bit space has been assigned
-      because the addresses we use directly determine the PE#.  We then
-      update the M32 PE# for the devices that use both 32-bit and 64-bit
-      spaces or assign the remaining PE# to 32-bit only devices.
-
-    - We cannot "group" segments in HW, so if a device ends up using more
-      than one segment, we end up with more than one PE#.  There is a HW
-      mechanism to make the freeze state cascade to "companion" PEs but
-      that only works for PCIe error messages (typically used so that if
-      you freeze a switch, it freezes all its children).  So we do it in
-      SW.  We lose a bit of effectiveness of EEH in that case, but that's
-      the best we found.  So when any of the PEs freezes, we freeze the
-      other ones for that "domain".  We thus introduce the concept of
-      "master PE" which is the one used for DMA, MSIs, etc., and "secondary
-      PEs" that are used for the remaining M64 segments.
-
-    We would like to investigate using additional M64 windows in "single
-    PE" mode to overlay over specific BARs to work around some of that, for
-    example for devices with very large BARs, e.g., GPUs.  It would make
-    sense, but we haven't done it yet.
-
-3. Considerations for SR-IOV on PowerKVM
-
-  * SR-IOV Background
-
-    The PCIe SR-IOV feature allows a single Physical Function (PF) to
-    support several Virtual Functions (VFs).  Registers in the PF's SR-IOV
-    Capability control the number of VFs and whether they are enabled.
-
-    When VFs are enabled, they appear in Configuration Space like normal
-    PCI devices, but the BARs in VF config space headers are unusual.  For
-    a non-VF device, software uses BARs in the config space header to
-    discover the BAR sizes and assign addresses for them.  For VF devices,
-    software uses VF BAR registers in the *PF* SR-IOV Capability to
-    discover sizes and assign addresses.  The BARs in the VF's config space
-    header are read-only zeros.
-
-    When a VF BAR in the PF SR-IOV Capability is programmed, it sets the
-    base address for all the corresponding VF(n) BARs.  For example, if the
-    PF SR-IOV Capability is programmed to enable eight VFs, and it has a
-    1MB VF BAR0, the address in that VF BAR sets the base of an 8MB region.
-    This region is divided into eight contiguous 1MB regions, each of which
-    is a BAR0 for one of the VFs.  Note that even though the VF BAR
-    describes an 8MB region, the alignment requirement is for a single VF,
-    i.e., 1MB in this example.
-
-  There are several strategies for isolating VFs in PEs:
-
-  - M32 window: There's one M32 window, and it is split into 256
-    equally-sized segments.  The finest granularity possible is a 256MB
-    window with 1MB segments.  VF BARs that are 1MB or larger could be
-    mapped to separate PEs in this window.  Each segment can be
-    individually mapped to a PE via the lookup table, so this is quite
-    flexible, but it works best when all the VF BARs are the same size.  If
-    they are different sizes, the entire window has to be small enough that
-    the segment size matches the smallest VF BAR, which means larger VF
-    BARs span several segments.
-
-  - Non-segmented M64 window: A non-segmented M64 window is mapped entirely
-    to a single PE, so it could only isolate one VF.
-
-  - Single segmented M64 windows: A segmented M64 window could be used just
-    like the M32 window, but the segments can't be individually mapped to
-    PEs (the segment number is the PE#), so there isn't as much
-    flexibility.  A VF with multiple BARs would have to be in a "domain" of
-    multiple PEs, which is not as well isolated as a single PE.
-
-  - Multiple segmented M64 windows: As usual, each window is split into 256
-    equally-sized segments, and the segment number is the PE#.  But if we
-    use several M64 windows, they can be set to different base addresses
-    and different segment sizes.  If we have VFs that each have a 1MB BAR
-    and a 32MB BAR, we could use one M64 window to assign 1MB segments and
-    another M64 window to assign 32MB segments.
-
-  Finally, the plan to use M64 windows for SR-IOV, which will be described
-  more in the next two sections.  For a given VF BAR, we need to
-  effectively reserve the entire 256 segments (256 * VF BAR size) and
-  position the VF BAR to start at the beginning of a free range of
-  segments/PEs inside that M64 window.
-
-  The goal is of course to be able to give a separate PE for each VF.
-
-  The IODA2 platform has 16 M64 windows, which are used to map MMIO
-  range to PE#.  Each M64 window defines one MMIO range and this range is
-  divided into 256 segments, with each segment corresponding to one PE.
-
-  We decide to leverage this M64 window to map VFs to individual PEs, since
-  SR-IOV VF BARs are all the same size.
-
-  But doing so introduces another problem: total_VFs is usually smaller
-  than the number of M64 window segments, so if we map one VF BAR directly
-  to one M64 window, some part of the M64 window will map to another
-  device's MMIO range.
-
-  IODA supports 256 PEs, so segmented windows contain 256 segments, so if
-  total_VFs is less than 256, we have the situation in Figure 1.0, where
-  segments [total_VFs, 255] of the M64 window may map to some MMIO range on
-  other devices:
-
-     0      1                     total_VFs - 1
-     +------+------+-     -+------+------+
-     |      |      |  ...  |      |      |
-     +------+------+-     -+------+------+
-
-                           VF(n) BAR space
-
-     0      1                     total_VFs - 1                255
-     +------+------+-     -+------+------+-      -+------+------+
-     |      |      |  ...  |      |      |   ...  |      |      |
-     +------+------+-     -+------+------+-      -+------+------+
-
-                           M64 window
-
-               Figure 1.0 Direct map VF(n) BAR space
-
-  Our current solution is to allocate 256 segments even if the VF(n) BAR
-  space doesn't need that much, as shown in Figure 1.1:
-
-     0      1                     total_VFs - 1                255
-     +------+------+-     -+------+------+-      -+------+------+
-     |      |      |  ...  |      |      |   ...  |      |      |
-     +------+------+-     -+------+------+-      -+------+------+
-
-                           VF(n) BAR space + extra
-
-     0      1                     total_VFs - 1                255
-     +------+------+-     -+------+------+-      -+------+------+
-     |      |      |  ...  |      |      |   ...  |      |      |
-     +------+------+-     -+------+------+-      -+------+------+
-
-                          M64 window
-
-               Figure 1.1 Map VF(n) BAR space + extra
-
-  Allocating the extra space ensures that the entire M64 window will be
-  assigned to this one SR-IOV device and none of the space will be
-  available for other devices.  Note that this only expands the space
-  reserved in software; there are still only total_VFs VFs, and they only
-  respond to segments [0, total_VFs - 1].  There's nothing in hardware that
-  responds to segments [total_VFs, 255].
-
-4. Implications for the Generic PCI Code
-
-The PCIe SR-IOV spec requires that the base of the VF(n) BAR space be
-aligned to the size of an individual VF BAR.
-
-In IODA2, the MMIO address determines the PE#.  If the address is in an M32
-window, we can set the PE# by updating the table that translates segments
-to PE#s.  Similarly, if the address is in an unsegmented M64 window, we can
-set the PE# for the window.  But if it's in a segmented M64 window, the
-segment number is the PE#.
-
-Therefore, the only way to control the PE# for a VF is to change the base
-of the VF(n) BAR space in the VF BAR.  If the PCI core allocates the exact
-amount of space required for the VF(n) BAR space, the VF BAR value is fixed
-and cannot be changed.
-
-On the other hand, if the PCI core allocates additional space, the VF BAR
-value can be changed as long as the entire VF(n) BAR space remains inside
-the space allocated by the core.
-
-Ideally the segment size will be the same as an individual VF BAR size.
-Then each VF will be in its own PE.  The VF BARs (and therefore the PE#s)
-are contiguous.  If VF0 is in PE(x), then VF(n) is in PE(x+n).  If we
-allocate 256 segments, there are (256 - numVFs) choices for the PE# of VF0.
-
-If the segment size is smaller than the VF BAR size, it will take several
-segments to cover a VF BAR, and a VF will be in several PEs.  This is
-possible, but the isolation isn't as good, and it reduces the number of PE#
-choices because instead of consuming only numVFs segments, the VF(n) BAR
-space will consume (numVFs * n) segments.  That means there aren't as many
-available segments for adjusting base of the VF(n) BAR space.
diff --git a/Documentation/powerpc/pmu-ebb.rst b/Documentation/powerpc/pmu-ebb.rst
new file mode 100644 (file)
index 0000000..4f47475
--- /dev/null
@@ -0,0 +1,138 @@
+========================
+PMU Event Based Branches
+========================
+
+Event Based Branches (EBBs) are a feature which allows the hardware to
+branch directly to a specified user space address when certain events occur.
+
+The full specification is available in Power ISA v2.07:
+
+  https://www.power.org/documentation/power-isa-version-2-07/
+
+One type of event for which EBBs can be configured is PMU exceptions. This
+document describes the API for configuring the Power PMU to generate EBBs,
+using the Linux perf_events API.
+
+
+Terminology
+-----------
+
+Throughout this document we will refer to an "EBB event" or "EBB events". This
+just refers to a struct perf_event which has set the "EBB" flag in its
+attr.config. All events which can be configured on the hardware PMU are
+possible "EBB events".
+
+
+Background
+----------
+
+When a PMU EBB occurs it is delivered to the currently running process. As such
+EBBs can only sensibly be used by programs for self-monitoring.
+
+It is a feature of the perf_events API that events can be created on other
+processes, subject to standard permission checks. This is also true of EBB
+events, however unless the target process enables EBBs (via mtspr(BESCR)) no
+EBBs will ever be delivered.
+
+This makes it possible for a process to enable EBBs for itself, but not
+actually configure any events. At a later time another process can come along
+and attach an EBB event to the process, which will then cause EBBs to be
+delivered to the first process. It's not clear if this is actually useful.
+
+
+When the PMU is configured for EBBs, all PMU interrupts are delivered to the
+user process. This means once an EBB event is scheduled on the PMU, no non-EBB
+events can be configured. This means that EBB events can not be run
+concurrently with regular 'perf' commands, or any other perf events.
+
+It is however safe to run 'perf' commands on a process which is using EBBs. The
+kernel will in general schedule the EBB event, and perf will be notified that
+its events could not run.
+
+The exclusion between EBB events and regular events is implemented using the
+existing "pinned" and "exclusive" attributes of perf_events. This means EBB
+events will be given priority over other events, unless they are also pinned.
+If an EBB event and a regular event are both pinned, then whichever is enabled
+first will be scheduled and the other will be put in error state. See the
+section below titled "Enabling an EBB event" for more information.
+
+
+Creating an EBB event
+---------------------
+
+To request that an event is counted using EBB, the event code should have bit
+63 set.
+
+EBB events must be created with a particular, and restrictive, set of
+attributes - this is so that they interoperate correctly with the rest of the
+perf_events subsystem.
+
+An EBB event must be created with the "pinned" and "exclusive" attributes set.
+Note that if you are creating a group of EBB events, only the leader can have
+these attributes set.
+
+An EBB event must NOT set any of the "inherit", "sample_period", "freq" or
+"enable_on_exec" attributes.
+
+An EBB event must be attached to a task. This is specified to perf_event_open()
+by passing a pid value, typically 0 indicating the current task.
+
+All events in a group must agree on whether they want EBB. That is all events
+must request EBB, or none may request EBB.
+
+EBB events must specify the PMC they are to be counted on. This ensures
+userspace is able to reliably determine which PMC the event is scheduled on.
+
+
+Enabling an EBB event
+---------------------
+
+Once an EBB event has been successfully opened, it must be enabled with the
+perf_events API. This can be achieved either via the ioctl() interface, or the
+prctl() interface.
+
+However, due to the design of the perf_events API, enabling an event does not
+guarantee that it has been scheduled on the PMU. To ensure that the EBB event
+has been scheduled on the PMU, you must perform a read() on the event. If the
+read() returns EOF, then the event has not been scheduled and EBBs are not
+enabled.
+
+This behaviour occurs because the EBB event is pinned and exclusive. When the
+EBB event is enabled it will force all other non-pinned events off the PMU. In
+this case the enable will be successful. However if there is already an event
+pinned on the PMU then the enable will not be successful.
+
+
+Reading an EBB event
+--------------------
+
+It is possible to read() from an EBB event. However the results are
+meaningless. Because interrupts are being delivered to the user process the
+kernel is not able to count the event, and so will return a junk value.
+
+
+Closing an EBB event
+--------------------
+
+When an EBB event is finished with, you can close it using close() as for any
+regular event. If this is the last EBB event the PMU will be deconfigured and
+no further PMU EBBs will be delivered.
+
+
+EBB Handler
+-----------
+
+The EBB handler is just regular userspace code, however it must be written in
+the style of an interrupt handler. When the handler is entered all registers
+are live (possibly) and so must be saved somehow before the handler can invoke
+other code.
+
+It's up to the program how to handle this. For C programs a relatively simple
+option is to create an interrupt frame on the stack and save registers there.
+
+Fork
+----
+
+EBB events are not inherited across fork. If the child process wishes to use
+EBBs it should open a new event for itself. Similarly the EBB state in
+BESCR/EBBHR/EBBRR is cleared across fork().
diff --git a/Documentation/powerpc/pmu-ebb.txt b/Documentation/powerpc/pmu-ebb.txt
deleted file mode 100644 (file)
index 73cd163..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-PMU Event Based Branches
-========================
-
-Event Based Branches (EBBs) are a feature which allows the hardware to
-branch directly to a specified user space address when certain events occur.
-
-The full specification is available in Power ISA v2.07:
-
-  https://www.power.org/documentation/power-isa-version-2-07/
-
-One type of event for which EBBs can be configured is PMU exceptions. This
-document describes the API for configuring the Power PMU to generate EBBs,
-using the Linux perf_events API.
-
-
-Terminology
------------
-
-Throughout this document we will refer to an "EBB event" or "EBB events". This
-just refers to a struct perf_event which has set the "EBB" flag in its
-attr.config. All events which can be configured on the hardware PMU are
-possible "EBB events".
-
-
-Background
-----------
-
-When a PMU EBB occurs it is delivered to the currently running process. As such
-EBBs can only sensibly be used by programs for self-monitoring.
-
-It is a feature of the perf_events API that events can be created on other
-processes, subject to standard permission checks. This is also true of EBB
-events, however unless the target process enables EBBs (via mtspr(BESCR)) no
-EBBs will ever be delivered.
-
-This makes it possible for a process to enable EBBs for itself, but not
-actually configure any events. At a later time another process can come along
-and attach an EBB event to the process, which will then cause EBBs to be
-delivered to the first process. It's not clear if this is actually useful.
-
-
-When the PMU is configured for EBBs, all PMU interrupts are delivered to the
-user process. This means once an EBB event is scheduled on the PMU, no non-EBB
-events can be configured. This means that EBB events can not be run
-concurrently with regular 'perf' commands, or any other perf events.
-
-It is however safe to run 'perf' commands on a process which is using EBBs. The
-kernel will in general schedule the EBB event, and perf will be notified that
-its events could not run.
-
-The exclusion between EBB events and regular events is implemented using the
-existing "pinned" and "exclusive" attributes of perf_events. This means EBB
-events will be given priority over other events, unless they are also pinned.
-If an EBB event and a regular event are both pinned, then whichever is enabled
-first will be scheduled and the other will be put in error state. See the
-section below titled "Enabling an EBB event" for more information.
-
-
-Creating an EBB event
----------------------
-
-To request that an event is counted using EBB, the event code should have bit
-63 set.
-
-EBB events must be created with a particular, and restrictive, set of
-attributes - this is so that they interoperate correctly with the rest of the
-perf_events subsystem.
-
-An EBB event must be created with the "pinned" and "exclusive" attributes set.
-Note that if you are creating a group of EBB events, only the leader can have
-these attributes set.
-
-An EBB event must NOT set any of the "inherit", "sample_period", "freq" or
-"enable_on_exec" attributes.
-
-An EBB event must be attached to a task. This is specified to perf_event_open()
-by passing a pid value, typically 0 indicating the current task.
-
-All events in a group must agree on whether they want EBB. That is all events
-must request EBB, or none may request EBB.
-
-EBB events must specify the PMC they are to be counted on. This ensures
-userspace is able to reliably determine which PMC the event is scheduled on.
-
-
-Enabling an EBB event
----------------------
-
-Once an EBB event has been successfully opened, it must be enabled with the
-perf_events API. This can be achieved either via the ioctl() interface, or the
-prctl() interface.
-
-However, due to the design of the perf_events API, enabling an event does not
-guarantee that it has been scheduled on the PMU. To ensure that the EBB event
-has been scheduled on the PMU, you must perform a read() on the event. If the
-read() returns EOF, then the event has not been scheduled and EBBs are not
-enabled.
-
-This behaviour occurs because the EBB event is pinned and exclusive. When the
-EBB event is enabled it will force all other non-pinned events off the PMU. In
-this case the enable will be successful. However if there is already an event
-pinned on the PMU then the enable will not be successful.
-
-
-Reading an EBB event
---------------------
-
-It is possible to read() from an EBB event. However the results are
-meaningless. Because interrupts are being delivered to the user process the
-kernel is not able to count the event, and so will return a junk value.
-
-
-Closing an EBB event
---------------------
-
-When an EBB event is finished with, you can close it using close() as for any
-regular event. If this is the last EBB event the PMU will be deconfigured and
-no further PMU EBBs will be delivered.
-
-
-EBB Handler
------------
-
-The EBB handler is just regular userspace code, however it must be written in
-the style of an interrupt handler. When the handler is entered all registers
-are live (possibly) and so must be saved somehow before the handler can invoke
-other code.
-
-It's up to the program how to handle this. For C programs a relatively simple
-option is to create an interrupt frame on the stack and save registers there.
-
-Fork
-----
-
-EBB events are not inherited across fork. If the child process wishes to use
-EBBs it should open a new event for itself. Similarly the EBB state in
-BESCR/EBBHR/EBBRR is cleared across fork().
diff --git a/Documentation/powerpc/ptrace.rst b/Documentation/powerpc/ptrace.rst
new file mode 100644 (file)
index 0000000..864d4b6
--- /dev/null
@@ -0,0 +1,156 @@
+======
+Ptrace
+======
+
+GDB intends to support the following hardware debug features of BookE
+processors:
+
+4 hardware breakpoints (IAC)
+2 hardware watchpoints (read, write and read-write) (DAC)
+2 value conditions for the hardware watchpoints (DVC)
+
+For that, we need to extend ptrace so that GDB can query and set these
+resources. Since we're extending, we're trying to create an interface
+that's extendable and that covers both BookE and server processors, so
+that GDB doesn't need to special-case each of them. We added the
+following 3 new ptrace requests.
+
+1. PTRACE_PPC_GETHWDEBUGINFO
+============================
+
+Query for GDB to discover the hardware debug features. The main info to
+be returned here is the minimum alignment for the hardware watchpoints.
+BookE processors don't have restrictions here, but server processors have
+an 8-byte alignment restriction for hardware watchpoints. We'd like to avoid
+adding special cases to GDB based on what it sees in AUXV.
+
+Since we're at it, we added other useful info that the kernel can return to
+GDB: this query will return the number of hardware breakpoints, hardware
+watchpoints and whether it supports a range of addresses and a condition.
+The query will fill the following structure provided by the requesting process::
+
+  struct ppc_debug_info {
+       unit32_t version;
+       unit32_t num_instruction_bps;
+       unit32_t num_data_bps;
+       unit32_t num_condition_regs;
+       unit32_t data_bp_alignment;
+       unit32_t sizeof_condition; /* size of the DVC register */
+       uint64_t features; /* bitmask of the individual flags */
+  };
+
+features will have bits indicating whether there is support for::
+
+  #define PPC_DEBUG_FEATURE_INSN_BP_RANGE              0x1
+  #define PPC_DEBUG_FEATURE_INSN_BP_MASK               0x2
+  #define PPC_DEBUG_FEATURE_DATA_BP_RANGE              0x4
+  #define PPC_DEBUG_FEATURE_DATA_BP_MASK               0x8
+  #define PPC_DEBUG_FEATURE_DATA_BP_DAWR               0x10
+
+2. PTRACE_SETHWDEBUG
+
+Sets a hardware breakpoint or watchpoint, according to the provided structure::
+
+  struct ppc_hw_breakpoint {
+        uint32_t version;
+  #define PPC_BREAKPOINT_TRIGGER_EXECUTE  0x1
+  #define PPC_BREAKPOINT_TRIGGER_READ     0x2
+ #define PPC_BREAKPOINT_TRIGGER_WRITE    0x4
+        uint32_t trigger_type;       /* only some combinations allowed */
+  #define PPC_BREAKPOINT_MODE_EXACT               0x0
+  #define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE     0x1
+  #define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE     0x2
+  #define PPC_BREAKPOINT_MODE_MASK                0x3
+        uint32_t addr_mode;          /* address match mode */
+
+  #define PPC_BREAKPOINT_CONDITION_MODE   0x3
+  #define PPC_BREAKPOINT_CONDITION_NONE   0x0
+  #define PPC_BREAKPOINT_CONDITION_AND    0x1
+  #define PPC_BREAKPOINT_CONDITION_EXACT  0x1  /* different name for the same thing as above */
+  #define PPC_BREAKPOINT_CONDITION_OR     0x2
+  #define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
+  #define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000   /* byte enable bits */
+  #define PPC_BREAKPOINT_CONDITION_BE(n)  (1<<((n)+16))
+        uint32_t condition_mode;     /* break/watchpoint condition flags */
+
+        uint64_t addr;
+        uint64_t addr2;
+        uint64_t condition_value;
+  };
+
+A request specifies one event, not necessarily just one register to be set.
+For instance, if the request is for a watchpoint with a condition, both the
+DAC and DVC registers will be set in the same request.
+
+With this GDB can ask for all kinds of hardware breakpoints and watchpoints
+that the BookE supports. COMEFROM breakpoints available in server processors
+are not contemplated, but that is out of the scope of this work.
+
+ptrace will return an integer (handle) uniquely identifying the breakpoint or
+watchpoint just created. This integer will be used in the PTRACE_DELHWDEBUG
+request to ask for its removal. Return -ENOSPC if the requested breakpoint
+can't be allocated on the registers.
+
+Some examples of using the structure to:
+
+- set a breakpoint in the first breakpoint register::
+
+    p.version         = PPC_DEBUG_CURRENT_VERSION;
+    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
+    p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
+    p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
+    p.addr            = (uint64_t) address;
+    p.addr2           = 0;
+    p.condition_value = 0;
+
+- set a watchpoint which triggers on reads in the second watchpoint register::
+
+    p.version         = PPC_DEBUG_CURRENT_VERSION;
+    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
+    p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
+    p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
+    p.addr            = (uint64_t) address;
+    p.addr2           = 0;
+    p.condition_value = 0;
+
+- set a watchpoint which triggers only with a specific value::
+
+    p.version         = PPC_DEBUG_CURRENT_VERSION;
+    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
+    p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
+    p.condition_mode  = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
+    p.addr            = (uint64_t) address;
+    p.addr2           = 0;
+    p.condition_value = (uint64_t) condition;
+
+- set a ranged hardware breakpoint::
+
+    p.version         = PPC_DEBUG_CURRENT_VERSION;
+    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
+    p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
+    p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
+    p.addr            = (uint64_t) begin_range;
+    p.addr2           = (uint64_t) end_range;
+    p.condition_value = 0;
+
+- set a watchpoint in server processors (BookS)::
+
+    p.version         = 1;
+    p.trigger_type    = PPC_BREAKPOINT_TRIGGER_RW;
+    p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
+    or
+    p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
+
+    p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
+    p.addr            = (uint64_t) begin_range;
+    /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
+     * addr2 - addr <= 8 Bytes.
+     */
+    p.addr2           = (uint64_t) end_range;
+    p.condition_value = 0;
+
+3. PTRACE_DELHWDEBUG
+
+Takes an integer which identifies an existing breakpoint or watchpoint
+(i.e., the value returned from PTRACE_SETHWDEBUG), and deletes the
+corresponding breakpoint or watchpoint..
diff --git a/Documentation/powerpc/ptrace.txt b/Documentation/powerpc/ptrace.txt
deleted file mode 100644 (file)
index 99c5ce8..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-GDB intends to support the following hardware debug features of BookE
-processors:
-
-4 hardware breakpoints (IAC)
-2 hardware watchpoints (read, write and read-write) (DAC)
-2 value conditions for the hardware watchpoints (DVC)
-
-For that, we need to extend ptrace so that GDB can query and set these
-resources. Since we're extending, we're trying to create an interface
-that's extendable and that covers both BookE and server processors, so
-that GDB doesn't need to special-case each of them. We added the
-following 3 new ptrace requests.
-
-1. PTRACE_PPC_GETHWDEBUGINFO
-
-Query for GDB to discover the hardware debug features. The main info to
-be returned here is the minimum alignment for the hardware watchpoints.
-BookE processors don't have restrictions here, but server processors have
-an 8-byte alignment restriction for hardware watchpoints. We'd like to avoid
-adding special cases to GDB based on what it sees in AUXV.
-
-Since we're at it, we added other useful info that the kernel can return to
-GDB: this query will return the number of hardware breakpoints, hardware
-watchpoints and whether it supports a range of addresses and a condition.
-The query will fill the following structure provided by the requesting process:
-
-struct ppc_debug_info {
-       unit32_t version;
-       unit32_t num_instruction_bps;
-       unit32_t num_data_bps;
-       unit32_t num_condition_regs;
-       unit32_t data_bp_alignment;
-       unit32_t sizeof_condition; /* size of the DVC register */
-       uint64_t features; /* bitmask of the individual flags */
-};
-
-features will have bits indicating whether there is support for:
-
-#define PPC_DEBUG_FEATURE_INSN_BP_RANGE                0x1
-#define PPC_DEBUG_FEATURE_INSN_BP_MASK         0x2
-#define PPC_DEBUG_FEATURE_DATA_BP_RANGE                0x4
-#define PPC_DEBUG_FEATURE_DATA_BP_MASK         0x8
-#define PPC_DEBUG_FEATURE_DATA_BP_DAWR         0x10
-
-2. PTRACE_SETHWDEBUG
-
-Sets a hardware breakpoint or watchpoint, according to the provided structure:
-
-struct ppc_hw_breakpoint {
-        uint32_t version;
-#define PPC_BREAKPOINT_TRIGGER_EXECUTE  0x1
-#define PPC_BREAKPOINT_TRIGGER_READ     0x2
-#define PPC_BREAKPOINT_TRIGGER_WRITE    0x4
-        uint32_t trigger_type;       /* only some combinations allowed */
-#define PPC_BREAKPOINT_MODE_EXACT               0x0
-#define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE     0x1
-#define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE     0x2
-#define PPC_BREAKPOINT_MODE_MASK                0x3
-        uint32_t addr_mode;          /* address match mode */
-
-#define PPC_BREAKPOINT_CONDITION_MODE   0x3
-#define PPC_BREAKPOINT_CONDITION_NONE   0x0
-#define PPC_BREAKPOINT_CONDITION_AND    0x1
-#define PPC_BREAKPOINT_CONDITION_EXACT  0x1    /* different name for the same thing as above */
-#define PPC_BREAKPOINT_CONDITION_OR     0x2
-#define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
-#define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000     /* byte enable bits */
-#define PPC_BREAKPOINT_CONDITION_BE(n)  (1<<((n)+16))
-        uint32_t condition_mode;     /* break/watchpoint condition flags */
-
-        uint64_t addr;
-        uint64_t addr2;
-        uint64_t condition_value;
-};
-
-A request specifies one event, not necessarily just one register to be set.
-For instance, if the request is for a watchpoint with a condition, both the
-DAC and DVC registers will be set in the same request.
-
-With this GDB can ask for all kinds of hardware breakpoints and watchpoints
-that the BookE supports. COMEFROM breakpoints available in server processors
-are not contemplated, but that is out of the scope of this work.
-
-ptrace will return an integer (handle) uniquely identifying the breakpoint or
-watchpoint just created. This integer will be used in the PTRACE_DELHWDEBUG
-request to ask for its removal. Return -ENOSPC if the requested breakpoint
-can't be allocated on the registers.
-
-Some examples of using the structure to:
-
-- set a breakpoint in the first breakpoint register
-
-  p.version         = PPC_DEBUG_CURRENT_VERSION;
-  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
-  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
-  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
-  p.addr            = (uint64_t) address;
-  p.addr2           = 0;
-  p.condition_value = 0;
-
-- set a watchpoint which triggers on reads in the second watchpoint register
-
-  p.version         = PPC_DEBUG_CURRENT_VERSION;
-  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
-  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
-  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
-  p.addr            = (uint64_t) address;
-  p.addr2           = 0;
-  p.condition_value = 0;
-
-- set a watchpoint which triggers only with a specific value
-
-  p.version         = PPC_DEBUG_CURRENT_VERSION;
-  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_READ;
-  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
-  p.condition_mode  = PPC_BREAKPOINT_CONDITION_AND | PPC_BREAKPOINT_CONDITION_BE_ALL;
-  p.addr            = (uint64_t) address;
-  p.addr2           = 0;
-  p.condition_value = (uint64_t) condition;
-
-- set a ranged hardware breakpoint
-
-  p.version         = PPC_DEBUG_CURRENT_VERSION;
-  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_EXECUTE;
-  p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
-  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
-  p.addr            = (uint64_t) begin_range;
-  p.addr2           = (uint64_t) end_range;
-  p.condition_value = 0;
-
-- set a watchpoint in server processors (BookS)
-
-  p.version         = 1;
-  p.trigger_type    = PPC_BREAKPOINT_TRIGGER_RW;
-  p.addr_mode       = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
-  or
-  p.addr_mode       = PPC_BREAKPOINT_MODE_EXACT;
-
-  p.condition_mode  = PPC_BREAKPOINT_CONDITION_NONE;
-  p.addr            = (uint64_t) begin_range;
-  /* For PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE addr2 needs to be specified, where
-   * addr2 - addr <= 8 Bytes.
-   */
-  p.addr2           = (uint64_t) end_range;
-  p.condition_value = 0;
-
-3. PTRACE_DELHWDEBUG
-
-Takes an integer which identifies an existing breakpoint or watchpoint
-(i.e., the value returned from PTRACE_SETHWDEBUG), and deletes the
-corresponding breakpoint or watchpoint..
diff --git a/Documentation/powerpc/qe_firmware.rst b/Documentation/powerpc/qe_firmware.rst
new file mode 100644 (file)
index 0000000..42f5103
--- /dev/null
@@ -0,0 +1,296 @@
+=========================================
+Freescale QUICC Engine Firmware Uploading
+=========================================
+
+(c) 2007 Timur Tabi <timur at freescale.com>,
+    Freescale Semiconductor
+
+.. Table of Contents
+
+   I - Software License for Firmware
+
+   II - Microcode Availability
+
+   III - Description and Terminology
+
+   IV - Microcode Programming Details
+
+   V - Firmware Structure Layout
+
+   VI - Sample Code for Creating Firmware Files
+
+Revision Information
+====================
+
+November 30, 2007: Rev 1.0 - Initial version
+
+I - Software License for Firmware
+=================================
+
+Each firmware file comes with its own software license.  For information on
+the particular license, please see the license text that is distributed with
+the firmware.
+
+II - Microcode Availability
+===========================
+
+Firmware files are distributed through various channels.  Some are available on
+http://opensource.freescale.com.  For other firmware files, please contact
+your Freescale representative or your operating system vendor.
+
+III - Description and Terminology
+=================================
+
+In this document, the term 'microcode' refers to the sequence of 32-bit
+integers that compose the actual QE microcode.
+
+The term 'firmware' refers to a binary blob that contains the microcode as
+well as other data that
+
+       1) describes the microcode's purpose
+       2) describes how and where to upload the microcode
+       3) specifies the values of various registers
+       4) includes additional data for use by specific device drivers
+
+Firmware files are binary files that contain only a firmware.
+
+IV - Microcode Programming Details
+===================================
+
+The QE architecture allows for only one microcode present in I-RAM for each
+RISC processor.  To replace any current microcode, a full QE reset (which
+disables the microcode) must be performed first.
+
+QE microcode is uploaded using the following procedure:
+
+1) The microcode is placed into I-RAM at a specific location, using the
+   IRAM.IADD and IRAM.IDATA registers.
+
+2) The CERCR.CIR bit is set to 0 or 1, depending on whether the firmware
+   needs split I-RAM.  Split I-RAM is only meaningful for SOCs that have
+   QEs with multiple RISC processors, such as the 8360.  Splitting the I-RAM
+   allows each processor to run a different microcode, effectively creating an
+   asymmetric multiprocessing (AMP) system.
+
+3) The TIBCR trap registers are loaded with the addresses of the trap handlers
+   in the microcode.
+
+4) The RSP.ECCR register is programmed with the value provided.
+
+5) If necessary, device drivers that need the virtual traps and extended mode
+   data will use them.
+
+Virtual Microcode Traps
+
+These virtual traps are conditional branches in the microcode.  These are
+"soft" provisional introduced in the ROMcode in order to enable higher
+flexibility and save h/w traps If new features are activated or an issue is
+being fixed in the RAM package utilizing they should be activated.  This data
+structure signals the microcode which of these virtual traps is active.
+
+This structure contains 6 words that the application should copy to some
+specific been defined.  This table describes the structure::
+
+       ---------------------------------------------------------------
+       | Offset in |                  | Destination Offset | Size of |
+       |   array   |     Protocol     |   within PRAM      | Operand |
+       --------------------------------------------------------------|
+       |     0     | Ethernet         |      0xF8          | 4 bytes |
+       |           | interworking     |                    |         |
+       ---------------------------------------------------------------
+       |     4     | ATM              |      0xF8          | 4 bytes |
+       |           | interworking     |                    |         |
+       ---------------------------------------------------------------
+       |     8     | PPP              |      0xF8          | 4 bytes |
+       |           | interworking     |                    |         |
+       ---------------------------------------------------------------
+       |     12    | Ethernet RX      |      0x22          | 1 byte  |
+       |           | Distributor Page |                    |         |
+       ---------------------------------------------------------------
+       |     16    | ATM Globtal      |      0x28          | 1 byte  |
+       |           | Params Table     |                    |         |
+       ---------------------------------------------------------------
+       |     20    | Insert Frame     |      0xF8          | 4 bytes |
+       ---------------------------------------------------------------
+
+
+Extended Modes
+
+This is a double word bit array (64 bits) that defines special functionality
+which has an impact on the software drivers.  Each bit has its own impact
+and has special instructions for the s/w associated with it.  This structure is
+described in this table::
+
+       -----------------------------------------------------------------------
+       | Bit #  |     Name     |   Description                               |
+       -----------------------------------------------------------------------
+       |   0    | General      | Indicates that prior to each host command   |
+       |        | push command | given by the application, the software must |
+       |        |              | assert a special host command (push command)|
+       |        |              | CECDR = 0x00800000.                         |
+       |        |              | CECR = 0x01c1000f.                          |
+       -----------------------------------------------------------------------
+       |   1    | UCC ATM      | Indicates that after issuing ATM RX INIT    |
+       |        | RX INIT      | command, the host must issue another special|
+       |        | push command | command (push command) and immediately      |
+       |        |              | following that re-issue the ATM RX INIT     |
+       |        |              | command. (This makes the sequence of        |
+       |        |              | initializing the ATM receiver a sequence of |
+       |        |              | three host commands)                        |
+       |        |              | CECDR = 0x00800000.                         |
+       |        |              | CECR = 0x01c1000f.                          |
+       -----------------------------------------------------------------------
+       |   2    | Add/remove   | Indicates that following the specific host  |
+       |        | command      | command: "Add/Remove entry in Hash Lookup   |
+       |        | validation   | Table" used in Interworking setup, the user |
+       |        |              | must issue another command.                 |
+       |        |              | CECDR = 0xce000003.                         |
+       |        |              | CECR = 0x01c10f58.                          |
+       -----------------------------------------------------------------------
+       |   3    | General push | Indicates that the s/w has to initialize    |
+       |        | command      | some pointers in the Ethernet thread pages  |
+       |        |              | which are used when Header Compression is   |
+       |        |              | activated.  The full details of these       |
+       |        |              | pointers is located in the software drivers.|
+       -----------------------------------------------------------------------
+       |   4    | General push | Indicates that after issuing Ethernet TX    |
+       |        | command      | INIT command, user must issue this command  |
+       |        |              | for each SNUM of Ethernet TX thread.        |
+       |        |              | CECDR = 0x00800003.                         |
+       |        |              | CECR = 0x7'b{0}, 8'b{Enet TX thread SNUM},  |
+       |        |              |        1'b{1}, 12'b{0}, 4'b{1}              |
+       -----------------------------------------------------------------------
+       | 5 - 31 |     N/A      | Reserved, set to zero.                      |
+       -----------------------------------------------------------------------
+
+V - Firmware Structure Layout
+==============================
+
+QE microcode from Freescale is typically provided as a header file.  This
+header file contains macros that define the microcode binary itself as well as
+some other data used in uploading that microcode.  The format of these files
+do not lend themselves to simple inclusion into other code.  Hence,
+the need for a more portable format.  This section defines that format.
+
+Instead of distributing a header file, the microcode and related data are
+embedded into a binary blob.  This blob is passed to the qe_upload_firmware()
+function, which parses the blob and performs everything necessary to upload
+the microcode.
+
+All integers are big-endian.  See the comments for function
+qe_upload_firmware() for up-to-date implementation information.
+
+This structure supports versioning, where the version of the structure is
+embedded into the structure itself.  To ensure forward and backwards
+compatibility, all versions of the structure must use the same 'qe_header'
+structure at the beginning.
+
+'header' (type: struct qe_header):
+       The 'length' field is the size, in bytes, of the entire structure,
+       including all the microcode embedded in it, as well as the CRC (if
+       present).
+
+       The 'magic' field is an array of three bytes that contains the letters
+       'Q', 'E', and 'F'.  This is an identifier that indicates that this
+       structure is a QE Firmware structure.
+
+       The 'version' field is a single byte that indicates the version of this
+       structure.  If the layout of the structure should ever need to be
+       changed to add support for additional types of microcode, then the
+       version number should also be changed.
+
+The 'id' field is a null-terminated string(suitable for printing) that
+identifies the firmware.
+
+The 'count' field indicates the number of 'microcode' structures.  There
+must be one and only one 'microcode' structure for each RISC processor.
+Therefore, this field also represents the number of RISC processors for this
+SOC.
+
+The 'soc' structure contains the SOC numbers and revisions used to match
+the microcode to the SOC itself.  Normally, the microcode loader should
+check the data in this structure with the SOC number and revisions, and
+only upload the microcode if there's a match.  However, this check is not
+made on all platforms.
+
+Although it is not recommended, you can specify '0' in the soc.model
+field to skip matching SOCs altogether.
+
+The 'model' field is a 16-bit number that matches the actual SOC. The
+'major' and 'minor' fields are the major and minor revision numbers,
+respectively, of the SOC.
+
+For example, to match the 8323, revision 1.0::
+
+     soc.model = 8323
+     soc.major = 1
+     soc.minor = 0
+
+'padding' is necessary for structure alignment.  This field ensures that the
+'extended_modes' field is aligned on a 64-bit boundary.
+
+'extended_modes' is a bitfield that defines special functionality which has an
+impact on the device drivers.  Each bit has its own impact and has special
+instructions for the driver associated with it.  This field is stored in
+the QE library and available to any driver that calles qe_get_firmware_info().
+
+'vtraps' is an array of 8 words that contain virtual trap values for each
+virtual traps.  As with 'extended_modes', this field is stored in the QE
+library and available to any driver that calles qe_get_firmware_info().
+
+'microcode' (type: struct qe_microcode):
+       For each RISC processor there is one 'microcode' structure.  The first
+       'microcode' structure is for the first RISC, and so on.
+
+       The 'id' field is a null-terminated string suitable for printing that
+       identifies this particular microcode.
+
+       'traps' is an array of 16 words that contain hardware trap values
+       for each of the 16 traps.  If trap[i] is 0, then this particular
+       trap is to be ignored (i.e. not written to TIBCR[i]).  The entire value
+       is written as-is to the TIBCR[i] register, so be sure to set the EN
+       and T_IBP bits if necessary.
+
+       'eccr' is the value to program into the ECCR register.
+
+       'iram_offset' is the offset into IRAM to start writing the
+       microcode.
+
+       'count' is the number of 32-bit words in the microcode.
+
+       'code_offset' is the offset, in bytes, from the beginning of this
+       structure where the microcode itself can be found.  The first
+       microcode binary should be located immediately after the 'microcode'
+       array.
+
+       'major', 'minor', and 'revision' are the major, minor, and revision
+       version numbers, respectively, of the microcode.  If all values are 0,
+       then these fields are ignored.
+
+       'reserved' is necessary for structure alignment.  Since 'microcode'
+       is an array, the 64-bit 'extended_modes' field needs to be aligned
+       on a 64-bit boundary, and this can only happen if the size of
+       'microcode' is a multiple of 8 bytes.  To ensure that, we add
+       'reserved'.
+
+After the last microcode is a 32-bit CRC.  It can be calculated using
+this algorithm::
+
+  u32 crc32(const u8 *p, unsigned int len)
+  {
+       unsigned int i;
+       u32 crc = 0;
+
+       while (len--) {
+          crc ^= *p++;
+          for (i = 0; i < 8; i++)
+                  crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
+       }
+       return crc;
+  }
+
+VI - Sample Code for Creating Firmware Files
+============================================
+
+A Python program that creates firmware binaries from the header files normally
+distributed by Freescale can be found on http://opensource.freescale.com.
diff --git a/Documentation/powerpc/qe_firmware.txt b/Documentation/powerpc/qe_firmware.txt
deleted file mode 100644 (file)
index e7ac24a..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-          Freescale QUICC Engine Firmware Uploading
-          -----------------------------------------
-
-(c) 2007 Timur Tabi <timur at freescale.com>,
-    Freescale Semiconductor
-
-Table of Contents
-=================
-
-  I - Software License for Firmware
-
-  II - Microcode Availability
-
-  III - Description and Terminology
-
-  IV - Microcode Programming Details
-
-  V - Firmware Structure Layout
-
-  VI - Sample Code for Creating Firmware Files
-
-Revision Information
-====================
-
-November 30, 2007: Rev 1.0 - Initial version
-
-I - Software License for Firmware
-=================================
-
-Each firmware file comes with its own software license.  For information on
-the particular license, please see the license text that is distributed with
-the firmware.
-
-II - Microcode Availability
-===========================
-
-Firmware files are distributed through various channels.  Some are available on
-http://opensource.freescale.com.  For other firmware files, please contact
-your Freescale representative or your operating system vendor.
-
-III - Description and Terminology
-================================
-
-In this document, the term 'microcode' refers to the sequence of 32-bit
-integers that compose the actual QE microcode.
-
-The term 'firmware' refers to a binary blob that contains the microcode as
-well as other data that
-
-       1) describes the microcode's purpose
-       2) describes how and where to upload the microcode
-       3) specifies the values of various registers
-       4) includes additional data for use by specific device drivers
-
-Firmware files are binary files that contain only a firmware.
-
-IV - Microcode Programming Details
-===================================
-
-The QE architecture allows for only one microcode present in I-RAM for each
-RISC processor.  To replace any current microcode, a full QE reset (which
-disables the microcode) must be performed first.
-
-QE microcode is uploaded using the following procedure:
-
-1) The microcode is placed into I-RAM at a specific location, using the
-   IRAM.IADD and IRAM.IDATA registers.
-
-2) The CERCR.CIR bit is set to 0 or 1, depending on whether the firmware
-   needs split I-RAM.  Split I-RAM is only meaningful for SOCs that have
-   QEs with multiple RISC processors, such as the 8360.  Splitting the I-RAM
-   allows each processor to run a different microcode, effectively creating an
-   asymmetric multiprocessing (AMP) system.
-
-3) The TIBCR trap registers are loaded with the addresses of the trap handlers
-   in the microcode.
-
-4) The RSP.ECCR register is programmed with the value provided.
-
-5) If necessary, device drivers that need the virtual traps and extended mode
-   data will use them.
-
-Virtual Microcode Traps
-
-These virtual traps are conditional branches in the microcode.  These are
-"soft" provisional introduced in the ROMcode in order to enable higher
-flexibility and save h/w traps If new features are activated or an issue is
-being fixed in the RAM package utilizing they should be activated.  This data
-structure signals the microcode which of these virtual traps is active.
-
-This structure contains 6 words that the application should copy to some
-specific been defined.  This table describes the structure.
-
-       ---------------------------------------------------------------
-       | Offset in |                  | Destination Offset | Size of |
-       |   array   |     Protocol     |   within PRAM      | Operand |
-       --------------------------------------------------------------|
-       |     0     | Ethernet         |      0xF8          | 4 bytes |
-       |           | interworking     |                    |         |
-       ---------------------------------------------------------------
-       |     4     | ATM              |      0xF8          | 4 bytes |
-       |           | interworking     |                    |         |
-       ---------------------------------------------------------------
-       |     8     | PPP              |      0xF8          | 4 bytes |
-       |           | interworking     |                    |         |
-       ---------------------------------------------------------------
-       |     12    | Ethernet RX      |      0x22          | 1 byte  |
-       |           | Distributor Page |                    |         |
-       ---------------------------------------------------------------
-       |     16    | ATM Globtal      |      0x28          | 1 byte  |
-       |           | Params Table     |                    |         |
-       ---------------------------------------------------------------
-       |     20    | Insert Frame     |      0xF8          | 4 bytes |
-       ---------------------------------------------------------------
-
-
-Extended Modes
-
-This is a double word bit array (64 bits) that defines special functionality
-which has an impact on the software drivers.  Each bit has its own impact
-and has special instructions for the s/w associated with it.  This structure is
-described in this table:
-
-       -----------------------------------------------------------------------
-       | Bit #  |     Name     |   Description                               |
-       -----------------------------------------------------------------------
-       |   0    | General      | Indicates that prior to each host command   |
-       |        | push command | given by the application, the software must |
-       |        |              | assert a special host command (push command)|
-       |        |              | CECDR = 0x00800000.                         |
-       |        |              | CECR = 0x01c1000f.                          |
-       -----------------------------------------------------------------------
-       |   1    | UCC ATM      | Indicates that after issuing ATM RX INIT    |
-       |        | RX INIT      | command, the host must issue another special|
-       |        | push command | command (push command) and immediately      |
-       |        |              | following that re-issue the ATM RX INIT     |
-       |        |              | command. (This makes the sequence of        |
-       |        |              | initializing the ATM receiver a sequence of |
-       |        |              | three host commands)                        |
-       |        |              | CECDR = 0x00800000.                         |
-       |        |              | CECR = 0x01c1000f.                          |
-       -----------------------------------------------------------------------
-       |   2    | Add/remove   | Indicates that following the specific host  |
-       |        | command      | command: "Add/Remove entry in Hash Lookup   |
-       |        | validation   | Table" used in Interworking setup, the user |
-       |        |              | must issue another command.                 |
-       |        |              | CECDR = 0xce000003.                         |
-       |        |              | CECR = 0x01c10f58.                          |
-       -----------------------------------------------------------------------
-       |   3    | General push | Indicates that the s/w has to initialize    |
-       |        | command      | some pointers in the Ethernet thread pages  |
-       |        |              | which are used when Header Compression is   |
-       |        |              | activated.  The full details of these       |
-       |        |              | pointers is located in the software drivers.|
-       -----------------------------------------------------------------------
-       |   4    | General push | Indicates that after issuing Ethernet TX    |
-       |        | command      | INIT command, user must issue this command  |
-       |        |              | for each SNUM of Ethernet TX thread.        |
-       |        |              | CECDR = 0x00800003.                         |
-       |        |              | CECR = 0x7'b{0}, 8'b{Enet TX thread SNUM},  |
-       |        |              |        1'b{1}, 12'b{0}, 4'b{1}              |
-       -----------------------------------------------------------------------
-       | 5 - 31 |     N/A      | Reserved, set to zero.                      |
-       -----------------------------------------------------------------------
-
-V - Firmware Structure Layout
-==============================
-
-QE microcode from Freescale is typically provided as a header file.  This
-header file contains macros that define the microcode binary itself as well as
-some other data used in uploading that microcode.  The format of these files
-do not lend themselves to simple inclusion into other code.  Hence,
-the need for a more portable format.  This section defines that format.
-
-Instead of distributing a header file, the microcode and related data are
-embedded into a binary blob.  This blob is passed to the qe_upload_firmware()
-function, which parses the blob and performs everything necessary to upload
-the microcode.
-
-All integers are big-endian.  See the comments for function
-qe_upload_firmware() for up-to-date implementation information.
-
-This structure supports versioning, where the version of the structure is
-embedded into the structure itself.  To ensure forward and backwards
-compatibility, all versions of the structure must use the same 'qe_header'
-structure at the beginning.
-
-'header' (type: struct qe_header):
-       The 'length' field is the size, in bytes, of the entire structure,
-       including all the microcode embedded in it, as well as the CRC (if
-       present).
-
-       The 'magic' field is an array of three bytes that contains the letters
-       'Q', 'E', and 'F'.  This is an identifier that indicates that this
-       structure is a QE Firmware structure.
-
-       The 'version' field is a single byte that indicates the version of this
-       structure.  If the layout of the structure should ever need to be
-       changed to add support for additional types of microcode, then the
-       version number should also be changed.
-
-The 'id' field is a null-terminated string(suitable for printing) that
-identifies the firmware.
-
-The 'count' field indicates the number of 'microcode' structures.  There
-must be one and only one 'microcode' structure for each RISC processor.
-Therefore, this field also represents the number of RISC processors for this
-SOC.
-
-The 'soc' structure contains the SOC numbers and revisions used to match
-the microcode to the SOC itself.  Normally, the microcode loader should
-check the data in this structure with the SOC number and revisions, and
-only upload the microcode if there's a match.  However, this check is not
-made on all platforms.
-
-Although it is not recommended, you can specify '0' in the soc.model
-field to skip matching SOCs altogether.
-
-The 'model' field is a 16-bit number that matches the actual SOC. The
-'major' and 'minor' fields are the major and minor revision numbers,
-respectively, of the SOC.
-
-For example, to match the 8323, revision 1.0:
-     soc.model = 8323
-     soc.major = 1
-     soc.minor = 0
-
-'padding' is necessary for structure alignment.  This field ensures that the
-'extended_modes' field is aligned on a 64-bit boundary.
-
-'extended_modes' is a bitfield that defines special functionality which has an
-impact on the device drivers.  Each bit has its own impact and has special
-instructions for the driver associated with it.  This field is stored in
-the QE library and available to any driver that calles qe_get_firmware_info().
-
-'vtraps' is an array of 8 words that contain virtual trap values for each
-virtual traps.  As with 'extended_modes', this field is stored in the QE
-library and available to any driver that calles qe_get_firmware_info().
-
-'microcode' (type: struct qe_microcode):
-       For each RISC processor there is one 'microcode' structure.  The first
-       'microcode' structure is for the first RISC, and so on.
-
-       The 'id' field is a null-terminated string suitable for printing that
-       identifies this particular microcode.
-
-       'traps' is an array of 16 words that contain hardware trap values
-       for each of the 16 traps.  If trap[i] is 0, then this particular
-       trap is to be ignored (i.e. not written to TIBCR[i]).  The entire value
-       is written as-is to the TIBCR[i] register, so be sure to set the EN
-       and T_IBP bits if necessary.
-
-       'eccr' is the value to program into the ECCR register.
-
-       'iram_offset' is the offset into IRAM to start writing the
-       microcode.
-
-       'count' is the number of 32-bit words in the microcode.
-
-       'code_offset' is the offset, in bytes, from the beginning of this
-       structure where the microcode itself can be found.  The first
-       microcode binary should be located immediately after the 'microcode'
-       array.
-
-       'major', 'minor', and 'revision' are the major, minor, and revision
-       version numbers, respectively, of the microcode.  If all values are 0,
-       then these fields are ignored.
-
-       'reserved' is necessary for structure alignment.  Since 'microcode'
-       is an array, the 64-bit 'extended_modes' field needs to be aligned
-       on a 64-bit boundary, and this can only happen if the size of
-       'microcode' is a multiple of 8 bytes.  To ensure that, we add
-       'reserved'.
-
-After the last microcode is a 32-bit CRC.  It can be calculated using
-this algorithm:
-
-u32 crc32(const u8 *p, unsigned int len)
-{
-       unsigned int i;
-       u32 crc = 0;
-
-       while (len--) {
-          crc ^= *p++;
-          for (i = 0; i < 8; i++)
-                  crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
-       }
-       return crc;
-}
-
-VI - Sample Code for Creating Firmware Files
-============================================
-
-A Python program that creates firmware binaries from the header files normally
-distributed by Freescale can be found on http://opensource.freescale.com.
diff --git a/Documentation/powerpc/syscall64-abi.rst b/Documentation/powerpc/syscall64-abi.rst
new file mode 100644 (file)
index 0000000..e49f69f
--- /dev/null
@@ -0,0 +1,110 @@
+===============================================
+Power Architecture 64-bit Linux system call ABI
+===============================================
+
+syscall
+=======
+
+syscall calling sequence\ [1]_ matches the Power Architecture 64-bit ELF ABI
+specification C function calling sequence, including register preservation
+rules, with the following differences.
+
+.. [1] Some syscalls (typically low-level management functions) may have
+       different calling sequences (e.g., rt_sigreturn).
+
+Parameters and return value
+---------------------------
+The system call number is specified in r0.
+
+There is a maximum of 6 integer parameters to a syscall, passed in r3-r8.
+
+Both a return value and a return error code are returned. cr0.SO is the return
+error code, and r3 is the return value or error code. When cr0.SO is clear,
+the syscall succeeded and r3 is the return value. When cr0.SO is set, the
+syscall failed and r3 is the error code that generally corresponds to errno.
+
+Stack
+-----
+System calls do not modify the caller's stack frame. For example, the caller's
+stack frame LR and CR save fields are not used.
+
+Register preservation rules
+---------------------------
+Register preservation rules match the ELF ABI calling sequence with the
+following differences:
+
+=========== ============= ========================================
+r0          Volatile      (System call number.)
+r3          Volatile      (Parameter 1, and return value.)
+r4-r8       Volatile      (Parameters 2-6.)
+cr0         Volatile      (cr0.SO is the return error condition)
+cr1, cr5-7  Nonvolatile
+lr          Nonvolatile
+=========== ============= ========================================
+
+All floating point and vector data registers as well as control and status
+registers are nonvolatile.
+
+Invocation
+----------
+The syscall is performed with the sc instruction, and returns with execution
+continuing at the instruction following the sc instruction.
+
+Transactional Memory
+--------------------
+Syscall behavior can change if the processor is in transactional or suspended
+transaction state, and the syscall can affect the behavior of the transaction.
+
+If the processor is in suspended state when a syscall is made, the syscall
+will be performed as normal, and will return as normal. The syscall will be
+performed in suspended state, so its side effects will be persistent according
+to the usual transactional memory semantics. A syscall may or may not result
+in the transaction being doomed by hardware.
+
+If the processor is in transactional state when a syscall is made, then the
+behavior depends on the presence of PPC_FEATURE2_HTM_NOSC in the AT_HWCAP2 ELF
+auxiliary vector.
+
+- If present, which is the case for newer kernels, then the syscall will not
+  be performed and the transaction will be doomed by the kernel with the
+  failure code TM_CAUSE_SYSCALL | TM_CAUSE_PERSISTENT in the TEXASR SPR.
+
+- If not present (older kernels), then the kernel will suspend the
+  transactional state and the syscall will proceed as in the case of a
+  suspended state syscall, and will resume the transactional state before
+  returning to the caller. This case is not well defined or supported, so this
+  behavior should not be relied upon.
+
+
+vsyscall
+========
+
+vsyscall calling sequence matches the syscall calling sequence, with the
+following differences. Some vsyscalls may have different calling sequences.
+
+Parameters and return value
+---------------------------
+r0 is not used as an input. The vsyscall is selected by its address.
+
+Stack
+-----
+The vsyscall may or may not use the caller's stack frame save areas.
+
+Register preservation rules
+---------------------------
+
+=========== ========
+r0          Volatile
+cr1, cr5-7  Volatile
+lr          Volatile
+=========== ========
+
+Invocation
+----------
+The vsyscall is performed with a branch-with-link instruction to the vsyscall
+function address.
+
+Transactional Memory
+--------------------
+vsyscalls will run in the same transactional state as the caller. A vsyscall
+may or may not result in the transaction being doomed by hardware.
diff --git a/Documentation/powerpc/syscall64-abi.txt b/Documentation/powerpc/syscall64-abi.txt
deleted file mode 100644 (file)
index fa716a0..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-===============================================
-Power Architecture 64-bit Linux system call ABI
-===============================================
-
-syscall
-=======
-
-syscall calling sequence[*] matches the Power Architecture 64-bit ELF ABI
-specification C function calling sequence, including register preservation
-rules, with the following differences.
-
-[*] Some syscalls (typically low-level management functions) may have
-    different calling sequences (e.g., rt_sigreturn).
-
-Parameters and return value
----------------------------
-The system call number is specified in r0.
-
-There is a maximum of 6 integer parameters to a syscall, passed in r3-r8.
-
-Both a return value and a return error code are returned. cr0.SO is the return
-error code, and r3 is the return value or error code. When cr0.SO is clear,
-the syscall succeeded and r3 is the return value. When cr0.SO is set, the
-syscall failed and r3 is the error code that generally corresponds to errno.
-
-Stack
------
-System calls do not modify the caller's stack frame. For example, the caller's
-stack frame LR and CR save fields are not used.
-
-Register preservation rules
----------------------------
-Register preservation rules match the ELF ABI calling sequence with the
-following differences:
-
-r0:         Volatile.   (System call number.)
-r3:         Volatile.   (Parameter 1, and return value.)
-r4-r8:      Volatile.   (Parameters 2-6.)
-cr0:        Volatile    (cr0.SO is the return error condition)
-cr1, cr5-7: Nonvolatile.
-lr:         Nonvolatile.
-
-All floating point and vector data registers as well as control and status
-registers are nonvolatile.
-
-Invocation
-----------
-The syscall is performed with the sc instruction, and returns with execution
-continuing at the instruction following the sc instruction.
-
-Transactional Memory
---------------------
-Syscall behavior can change if the processor is in transactional or suspended
-transaction state, and the syscall can affect the behavior of the transaction.
-
-If the processor is in suspended state when a syscall is made, the syscall
-will be performed as normal, and will return as normal. The syscall will be
-performed in suspended state, so its side effects will be persistent according
-to the usual transactional memory semantics. A syscall may or may not result
-in the transaction being doomed by hardware.
-
-If the processor is in transactional state when a syscall is made, then the
-behavior depends on the presence of PPC_FEATURE2_HTM_NOSC in the AT_HWCAP2 ELF
-auxiliary vector.
-
-- If present, which is the case for newer kernels, then the syscall will not
-  be performed and the transaction will be doomed by the kernel with the
-  failure code TM_CAUSE_SYSCALL | TM_CAUSE_PERSISTENT in the TEXASR SPR.
-
-- If not present (older kernels), then the kernel will suspend the
-  transactional state and the syscall will proceed as in the case of a
-  suspended state syscall, and will resume the transactional state before
-  returning to the caller. This case is not well defined or supported, so this
-  behavior should not be relied upon.
-
-
-vsyscall
-========
-
-vsyscall calling sequence matches the syscall calling sequence, with the
-following differences. Some vsyscalls may have different calling sequences.
-
-Parameters and return value
----------------------------
-r0 is not used as an input. The vsyscall is selected by its address.
-
-Stack
------
-The vsyscall may or may not use the caller's stack frame save areas.
-
-Register preservation rules
----------------------------
-r0: Volatile.
-cr1, cr5-7: Volatile.
-lr: Volatile.
-
-Invocation
-----------
-The vsyscall is performed with a branch-with-link instruction to the vsyscall
-function address.
-
-Transactional Memory
---------------------
-vsyscalls will run in the same transactional state as the caller. A vsyscall
-may or may not result in the transaction being doomed by hardware.
diff --git a/Documentation/powerpc/transactional_memory.rst b/Documentation/powerpc/transactional_memory.rst
new file mode 100644 (file)
index 0000000..0995510
--- /dev/null
@@ -0,0 +1,247 @@
+============================
+Transactional Memory support
+============================
+
+POWER kernel support for this feature is currently limited to supporting
+its use by user programs.  It is not currently used by the kernel itself.
+
+This file aims to sum up how it is supported by Linux and what behaviour you
+can expect from your user programs.
+
+
+Basic overview
+==============
+
+Hardware Transactional Memory is supported on POWER8 processors, and is a
+feature that enables a different form of atomic memory access.  Several new
+instructions are presented to delimit transactions; transactions are
+guaranteed to either complete atomically or roll back and undo any partial
+changes.
+
+A simple transaction looks like this::
+
+  begin_move_money:
+    tbegin
+    beq   abort_handler
+
+    ld    r4, SAVINGS_ACCT(r3)
+    ld    r5, CURRENT_ACCT(r3)
+    subi  r5, r5, 1
+    addi  r4, r4, 1
+    std   r4, SAVINGS_ACCT(r3)
+    std   r5, CURRENT_ACCT(r3)
+
+    tend
+
+    b     continue
+
+  abort_handler:
+    ... test for odd failures ...
+
+    /* Retry the transaction if it failed because it conflicted with
+     * someone else: */
+    b     begin_move_money
+
+
+The 'tbegin' instruction denotes the start point, and 'tend' the end point.
+Between these points the processor is in 'Transactional' state; any memory
+references will complete in one go if there are no conflicts with other
+transactional or non-transactional accesses within the system.  In this
+example, the transaction completes as though it were normal straight-line code
+IF no other processor has touched SAVINGS_ACCT(r3) or CURRENT_ACCT(r3); an
+atomic move of money from the current account to the savings account has been
+performed.  Even though the normal ld/std instructions are used (note no
+lwarx/stwcx), either *both* SAVINGS_ACCT(r3) and CURRENT_ACCT(r3) will be
+updated, or neither will be updated.
+
+If, in the meantime, there is a conflict with the locations accessed by the
+transaction, the transaction will be aborted by the CPU.  Register and memory
+state will roll back to that at the 'tbegin', and control will continue from
+'tbegin+4'.  The branch to abort_handler will be taken this second time; the
+abort handler can check the cause of the failure, and retry.
+
+Checkpointed registers include all GPRs, FPRs, VRs/VSRs, LR, CCR/CR, CTR, FPCSR
+and a few other status/flag regs; see the ISA for details.
+
+Causes of transaction aborts
+============================
+
+- Conflicts with cache lines used by other processors
+- Signals
+- Context switches
+- See the ISA for full documentation of everything that will abort transactions.
+
+
+Syscalls
+========
+
+Syscalls made from within an active transaction will not be performed and the
+transaction will be doomed by the kernel with the failure code TM_CAUSE_SYSCALL
+| TM_CAUSE_PERSISTENT.
+
+Syscalls made from within a suspended transaction are performed as normal and
+the transaction is not explicitly doomed by the kernel.  However, what the
+kernel does to perform the syscall may result in the transaction being doomed
+by the hardware.  The syscall is performed in suspended mode so any side
+effects will be persistent, independent of transaction success or failure.  No
+guarantees are provided by the kernel about which syscalls will affect
+transaction success.
+
+Care must be taken when relying on syscalls to abort during active transactions
+if the calls are made via a library.  Libraries may cache values (which may
+give the appearance of success) or perform operations that cause transaction
+failure before entering the kernel (which may produce different failure codes).
+Examples are glibc's getpid() and lazy symbol resolution.
+
+
+Signals
+=======
+
+Delivery of signals (both sync and async) during transactions provides a second
+thread state (ucontext/mcontext) to represent the second transactional register
+state.  Signal delivery 'treclaim's to capture both register states, so signals
+abort transactions.  The usual ucontext_t passed to the signal handler
+represents the checkpointed/original register state; the signal appears to have
+arisen at 'tbegin+4'.
+
+If the sighandler ucontext has uc_link set, a second ucontext has been
+delivered.  For future compatibility the MSR.TS field should be checked to
+determine the transactional state -- if so, the second ucontext in uc->uc_link
+represents the active transactional registers at the point of the signal.
+
+For 64-bit processes, uc->uc_mcontext.regs->msr is a full 64-bit MSR and its TS
+field shows the transactional mode.
+
+For 32-bit processes, the mcontext's MSR register is only 32 bits; the top 32
+bits are stored in the MSR of the second ucontext, i.e. in
+uc->uc_link->uc_mcontext.regs->msr.  The top word contains the transactional
+state TS.
+
+However, basic signal handlers don't need to be aware of transactions
+and simply returning from the handler will deal with things correctly:
+
+Transaction-aware signal handlers can read the transactional register state
+from the second ucontext.  This will be necessary for crash handlers to
+determine, for example, the address of the instruction causing the SIGSEGV.
+
+Example signal handler::
+
+    void crash_handler(int sig, siginfo_t *si, void *uc)
+    {
+      ucontext_t *ucp = uc;
+      ucontext_t *transactional_ucp = ucp->uc_link;
+
+      if (ucp_link) {
+        u64 msr = ucp->uc_mcontext.regs->msr;
+        /* May have transactional ucontext! */
+  #ifndef __powerpc64__
+        msr |= ((u64)transactional_ucp->uc_mcontext.regs->msr) << 32;
+  #endif
+        if (MSR_TM_ACTIVE(msr)) {
+           /* Yes, we crashed during a transaction.  Oops. */
+   fprintf(stderr, "Transaction to be restarted at 0x%llx, but "
+                           "crashy instruction was at 0x%llx\n",
+                           ucp->uc_mcontext.regs->nip,
+                           transactional_ucp->uc_mcontext.regs->nip);
+        }
+      }
+
+      fix_the_problem(ucp->dar);
+    }
+
+When in an active transaction that takes a signal, we need to be careful with
+the stack.  It's possible that the stack has moved back up after the tbegin.
+The obvious case here is when the tbegin is called inside a function that
+returns before a tend.  In this case, the stack is part of the checkpointed
+transactional memory state.  If we write over this non transactionally or in
+suspend, we are in trouble because if we get a tm abort, the program counter and
+stack pointer will be back at the tbegin but our in memory stack won't be valid
+anymore.
+
+To avoid this, when taking a signal in an active transaction, we need to use
+the stack pointer from the checkpointed state, rather than the speculated
+state.  This ensures that the signal context (written tm suspended) will be
+written below the stack required for the rollback.  The transaction is aborted
+because of the treclaim, so any memory written between the tbegin and the
+signal will be rolled back anyway.
+
+For signals taken in non-TM or suspended mode, we use the
+normal/non-checkpointed stack pointer.
+
+Any transaction initiated inside a sighandler and suspended on return
+from the sighandler to the kernel will get reclaimed and discarded.
+
+Failure cause codes used by kernel
+==================================
+
+These are defined in <asm/reg.h>, and distinguish different reasons why the
+kernel aborted a transaction:
+
+ ====================== ================================
+ TM_CAUSE_RESCHED       Thread was rescheduled.
+ TM_CAUSE_TLBI          Software TLB invalid.
+ TM_CAUSE_FAC_UNAV      FP/VEC/VSX unavailable trap.
+ TM_CAUSE_SYSCALL       Syscall from active transaction.
+ TM_CAUSE_SIGNAL        Signal delivered.
+ TM_CAUSE_MISC          Currently unused.
+ TM_CAUSE_ALIGNMENT     Alignment fault.
+ TM_CAUSE_EMULATE       Emulation that touched memory.
+ ====================== ================================
+
+These can be checked by the user program's abort handler as TEXASR[0:7].  If
+bit 7 is set, it indicates that the error is consider persistent.  For example
+a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not.
+
+GDB
+===
+
+GDB and ptrace are not currently TM-aware.  If one stops during a transaction,
+it looks like the transaction has just started (the checkpointed state is
+presented).  The transaction cannot then be continued and will take the failure
+handler route.  Furthermore, the transactional 2nd register state will be
+inaccessible.  GDB can currently be used on programs using TM, but not sensibly
+in parts within transactions.
+
+POWER9
+======
+
+TM on POWER9 has issues with storing the complete register state. This
+is described in this commit::
+
+    commit 4bb3c7a0208fc13ca70598efd109901a7cd45ae7
+    Author: Paul Mackerras <paulus@ozlabs.org>
+    Date:   Wed Mar 21 21:32:01 2018 +1100
+    KVM: PPC: Book3S HV: Work around transactional memory bugs in POWER9
+
+To account for this different POWER9 chips have TM enabled in
+different ways.
+
+On POWER9N DD2.01 and below, TM is disabled. ie
+HWCAP2[PPC_FEATURE2_HTM] is not set.
+
+On POWER9N DD2.1 TM is configured by firmware to always abort a
+transaction when tm suspend occurs. So tsuspend will cause a
+transaction to be aborted and rolled back. Kernel exceptions will also
+cause the transaction to be aborted and rolled back and the exception
+will not occur. If userspace constructs a sigcontext that enables TM
+suspend, the sigcontext will be rejected by the kernel. This mode is
+advertised to users with HWCAP2[PPC_FEATURE2_HTM_NO_SUSPEND] set.
+HWCAP2[PPC_FEATURE2_HTM] is not set in this mode.
+
+On POWER9N DD2.2 and above, KVM and POWERVM emulate TM for guests (as
+described in commit 4bb3c7a0208f), hence TM is enabled for guests
+ie. HWCAP2[PPC_FEATURE2_HTM] is set for guest userspace. Guests that
+makes heavy use of TM suspend (tsuspend or kernel suspend) will result
+in traps into the hypervisor and hence will suffer a performance
+degradation. Host userspace has TM disabled
+ie. HWCAP2[PPC_FEATURE2_HTM] is not set. (although we make enable it
+at some point in the future if we bring the emulation into host
+userspace context switching).
+
+POWER9C DD1.2 and above are only available with POWERVM and hence
+Linux only runs as a guest. On these systems TM is emulated like on
+POWER9N DD2.2.
+
+Guest migration from POWER8 to POWER9 will work with POWER9N DD2.2 and
+POWER9C DD1.2. Since earlier POWER9 processors don't support TM
+emulation, migration from POWER8 to POWER9 is not supported there.
diff --git a/Documentation/powerpc/transactional_memory.txt b/Documentation/powerpc/transactional_memory.txt
deleted file mode 100644 (file)
index 52c023e..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-Transactional Memory support
-============================
-
-POWER kernel support for this feature is currently limited to supporting
-its use by user programs.  It is not currently used by the kernel itself.
-
-This file aims to sum up how it is supported by Linux and what behaviour you
-can expect from your user programs.
-
-
-Basic overview
-==============
-
-Hardware Transactional Memory is supported on POWER8 processors, and is a
-feature that enables a different form of atomic memory access.  Several new
-instructions are presented to delimit transactions; transactions are
-guaranteed to either complete atomically or roll back and undo any partial
-changes.
-
-A simple transaction looks like this:
-
-begin_move_money:
-  tbegin
-  beq   abort_handler
-
-  ld    r4, SAVINGS_ACCT(r3)
-  ld    r5, CURRENT_ACCT(r3)
-  subi  r5, r5, 1
-  addi  r4, r4, 1
-  std   r4, SAVINGS_ACCT(r3)
-  std   r5, CURRENT_ACCT(r3)
-
-  tend
-
-  b     continue
-
-abort_handler:
-  ... test for odd failures ...
-
-  /* Retry the transaction if it failed because it conflicted with
-   * someone else: */
-  b     begin_move_money
-
-
-The 'tbegin' instruction denotes the start point, and 'tend' the end point.
-Between these points the processor is in 'Transactional' state; any memory
-references will complete in one go if there are no conflicts with other
-transactional or non-transactional accesses within the system.  In this
-example, the transaction completes as though it were normal straight-line code
-IF no other processor has touched SAVINGS_ACCT(r3) or CURRENT_ACCT(r3); an
-atomic move of money from the current account to the savings account has been
-performed.  Even though the normal ld/std instructions are used (note no
-lwarx/stwcx), either *both* SAVINGS_ACCT(r3) and CURRENT_ACCT(r3) will be
-updated, or neither will be updated.
-
-If, in the meantime, there is a conflict with the locations accessed by the
-transaction, the transaction will be aborted by the CPU.  Register and memory
-state will roll back to that at the 'tbegin', and control will continue from
-'tbegin+4'.  The branch to abort_handler will be taken this second time; the
-abort handler can check the cause of the failure, and retry.
-
-Checkpointed registers include all GPRs, FPRs, VRs/VSRs, LR, CCR/CR, CTR, FPCSR
-and a few other status/flag regs; see the ISA for details.
-
-Causes of transaction aborts
-============================
-
-- Conflicts with cache lines used by other processors
-- Signals
-- Context switches
-- See the ISA for full documentation of everything that will abort transactions.
-
-
-Syscalls
-========
-
-Syscalls made from within an active transaction will not be performed and the
-transaction will be doomed by the kernel with the failure code TM_CAUSE_SYSCALL
-| TM_CAUSE_PERSISTENT.
-
-Syscalls made from within a suspended transaction are performed as normal and
-the transaction is not explicitly doomed by the kernel.  However, what the
-kernel does to perform the syscall may result in the transaction being doomed
-by the hardware.  The syscall is performed in suspended mode so any side
-effects will be persistent, independent of transaction success or failure.  No
-guarantees are provided by the kernel about which syscalls will affect
-transaction success.
-
-Care must be taken when relying on syscalls to abort during active transactions
-if the calls are made via a library.  Libraries may cache values (which may
-give the appearance of success) or perform operations that cause transaction
-failure before entering the kernel (which may produce different failure codes).
-Examples are glibc's getpid() and lazy symbol resolution.
-
-
-Signals
-=======
-
-Delivery of signals (both sync and async) during transactions provides a second
-thread state (ucontext/mcontext) to represent the second transactional register
-state.  Signal delivery 'treclaim's to capture both register states, so signals
-abort transactions.  The usual ucontext_t passed to the signal handler
-represents the checkpointed/original register state; the signal appears to have
-arisen at 'tbegin+4'.
-
-If the sighandler ucontext has uc_link set, a second ucontext has been
-delivered.  For future compatibility the MSR.TS field should be checked to
-determine the transactional state -- if so, the second ucontext in uc->uc_link
-represents the active transactional registers at the point of the signal.
-
-For 64-bit processes, uc->uc_mcontext.regs->msr is a full 64-bit MSR and its TS
-field shows the transactional mode.
-
-For 32-bit processes, the mcontext's MSR register is only 32 bits; the top 32
-bits are stored in the MSR of the second ucontext, i.e. in
-uc->uc_link->uc_mcontext.regs->msr.  The top word contains the transactional
-state TS.
-
-However, basic signal handlers don't need to be aware of transactions
-and simply returning from the handler will deal with things correctly:
-
-Transaction-aware signal handlers can read the transactional register state
-from the second ucontext.  This will be necessary for crash handlers to
-determine, for example, the address of the instruction causing the SIGSEGV.
-
-Example signal handler:
-
-    void crash_handler(int sig, siginfo_t *si, void *uc)
-    {
-      ucontext_t *ucp = uc;
-      ucontext_t *transactional_ucp = ucp->uc_link;
-
-      if (ucp_link) {
-        u64 msr = ucp->uc_mcontext.regs->msr;
-        /* May have transactional ucontext! */
-#ifndef __powerpc64__
-        msr |= ((u64)transactional_ucp->uc_mcontext.regs->msr) << 32;
-#endif
-        if (MSR_TM_ACTIVE(msr)) {
-           /* Yes, we crashed during a transaction.  Oops. */
-   fprintf(stderr, "Transaction to be restarted at 0x%llx, but "
-                           "crashy instruction was at 0x%llx\n",
-                           ucp->uc_mcontext.regs->nip,
-                           transactional_ucp->uc_mcontext.regs->nip);
-        }
-      }
-
-      fix_the_problem(ucp->dar);
-    }
-
-When in an active transaction that takes a signal, we need to be careful with
-the stack.  It's possible that the stack has moved back up after the tbegin.
-The obvious case here is when the tbegin is called inside a function that
-returns before a tend.  In this case, the stack is part of the checkpointed
-transactional memory state.  If we write over this non transactionally or in
-suspend, we are in trouble because if we get a tm abort, the program counter and
-stack pointer will be back at the tbegin but our in memory stack won't be valid
-anymore.
-
-To avoid this, when taking a signal in an active transaction, we need to use
-the stack pointer from the checkpointed state, rather than the speculated
-state.  This ensures that the signal context (written tm suspended) will be
-written below the stack required for the rollback.  The transaction is aborted
-because of the treclaim, so any memory written between the tbegin and the
-signal will be rolled back anyway.
-
-For signals taken in non-TM or suspended mode, we use the
-normal/non-checkpointed stack pointer.
-
-Any transaction initiated inside a sighandler and suspended on return
-from the sighandler to the kernel will get reclaimed and discarded.
-
-Failure cause codes used by kernel
-==================================
-
-These are defined in <asm/reg.h>, and distinguish different reasons why the
-kernel aborted a transaction:
-
- TM_CAUSE_RESCHED       Thread was rescheduled.
- TM_CAUSE_TLBI          Software TLB invalid.
- TM_CAUSE_FAC_UNAV      FP/VEC/VSX unavailable trap.
- TM_CAUSE_SYSCALL       Syscall from active transaction.
- TM_CAUSE_SIGNAL        Signal delivered.
- TM_CAUSE_MISC          Currently unused.
- TM_CAUSE_ALIGNMENT     Alignment fault.
- TM_CAUSE_EMULATE       Emulation that touched memory.
-
-These can be checked by the user program's abort handler as TEXASR[0:7].  If
-bit 7 is set, it indicates that the error is consider persistent.  For example
-a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not.
-
-GDB
-===
-
-GDB and ptrace are not currently TM-aware.  If one stops during a transaction,
-it looks like the transaction has just started (the checkpointed state is
-presented).  The transaction cannot then be continued and will take the failure
-handler route.  Furthermore, the transactional 2nd register state will be
-inaccessible.  GDB can currently be used on programs using TM, but not sensibly
-in parts within transactions.
-
-POWER9
-======
-
-TM on POWER9 has issues with storing the complete register state. This
-is described in this commit:
-
-    commit 4bb3c7a0208fc13ca70598efd109901a7cd45ae7
-    Author: Paul Mackerras <paulus@ozlabs.org>
-    Date:   Wed Mar 21 21:32:01 2018 +1100
-    KVM: PPC: Book3S HV: Work around transactional memory bugs in POWER9
-
-To account for this different POWER9 chips have TM enabled in
-different ways.
-
-On POWER9N DD2.01 and below, TM is disabled. ie
-HWCAP2[PPC_FEATURE2_HTM] is not set.
-
-On POWER9N DD2.1 TM is configured by firmware to always abort a
-transaction when tm suspend occurs. So tsuspend will cause a
-transaction to be aborted and rolled back. Kernel exceptions will also
-cause the transaction to be aborted and rolled back and the exception
-will not occur. If userspace constructs a sigcontext that enables TM
-suspend, the sigcontext will be rejected by the kernel. This mode is
-advertised to users with HWCAP2[PPC_FEATURE2_HTM_NO_SUSPEND] set.
-HWCAP2[PPC_FEATURE2_HTM] is not set in this mode.
-
-On POWER9N DD2.2 and above, KVM and POWERVM emulate TM for guests (as
-described in commit 4bb3c7a0208f), hence TM is enabled for guests
-ie. HWCAP2[PPC_FEATURE2_HTM] is set for guest userspace. Guests that
-makes heavy use of TM suspend (tsuspend or kernel suspend) will result
-in traps into the hypervisor and hence will suffer a performance
-degradation. Host userspace has TM disabled
-ie. HWCAP2[PPC_FEATURE2_HTM] is not set. (although we make enable it
-at some point in the future if we bring the emulation into host
-userspace context switching).
-
-POWER9C DD1.2 and above are only available with POWERVM and hence
-Linux only runs as a guest. On these systems TM is emulated like on
-POWER9N DD2.2.
-
-Guest migration from POWER8 to POWER9 will work with POWER9N DD2.2 and
-POWER9C DD1.2. Since earlier POWER9 processors don't support TM
-emulation, migration from POWER8 to POWER9 is not supported there.
diff --git a/Documentation/process/conf.py b/Documentation/process/conf.py
deleted file mode 100644 (file)
index 1b01a80..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Development Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'process.tex', 'Linux Kernel Development Documentation',
-     'The kernel development community', 'manual'),
-]
index 49e0f64a3427deeec7eebf456e2549085ab378ff..053b24a6dd38cce19fc6d5ae1ed800dcb55cab00 100644 (file)
@@ -119,3 +119,17 @@ array may exceed the remaining memory in the stack segment. This could
 lead to a crash, possible overwriting sensitive contents at the end of the
 stack (when built without `CONFIG_THREAD_INFO_IN_TASK=y`), or overwriting
 memory adjacent to the stack (when built without `CONFIG_VMAP_STACK=y`)
+
+Implicit switch case fall-through
+---------------------------------
+The C language allows switch cases to "fall through" when
+a "break" statement is missing at the end of a case. This,
+however, introduces ambiguity in the code, as it's not always
+clear if the missing break is intentional or a bug. As there
+have been a long list of flaws `due to missing "break" statements
+<https://cwe.mitre.org/data/definitions/484.html>`_, we no longer allow
+"implicit fall-through". In order to identify an intentional fall-through
+case, we have adopted the marking used by static analyzers: a comment
+saying `/* Fall through */`. Once the C++17 `__attribute__((fallthrough))`
+is more widely handled by C compilers, static analyzers, and IDEs, we can
+switch to using that instead.
diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst
new file mode 100644 (file)
index 0000000..4026363
--- /dev/null
@@ -0,0 +1,279 @@
+Embargoed hardware issues
+=========================
+
+Scope
+-----
+
+Hardware issues which result in security problems are a different category
+of security bugs than pure software bugs which only affect the Linux
+kernel.
+
+Hardware issues like Meltdown, Spectre, L1TF etc. must be treated
+differently because they usually affect all Operating Systems ("OS") and
+therefore need coordination across different OS vendors, distributions,
+hardware vendors and other parties. For some of the issues, software
+mitigations can depend on microcode or firmware updates, which need further
+coordination.
+
+.. _Contact:
+
+Contact
+-------
+
+The Linux kernel hardware security team is separate from the regular Linux
+kernel security team.
+
+The team only handles the coordination of embargoed hardware security
+issues.  Reports of pure software security bugs in the Linux kernel are not
+handled by this team and the reporter will be guided to contact the regular
+Linux kernel security team (:ref:`Documentation/admin-guide/
+<securitybugs>`) instead.
+
+The team can be contacted by email at <hardware-security@kernel.org>. This
+is a private list of security officers who will help you to coordinate an
+issue according to our documented process.
+
+The list is encrypted and email to the list can be sent by either PGP or
+S/MIME encrypted and must be signed with the reporter's PGP key or S/MIME
+certificate. The list's PGP key and S/MIME certificate are available from
+https://www.kernel.org/....
+
+While hardware security issues are often handled by the affected hardware
+vendor, we welcome contact from researchers or individuals who have
+identified a potential hardware flaw.
+
+Hardware security officers
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The current team of hardware security officers:
+
+  - Linus Torvalds (Linux Foundation Fellow)
+  - Greg Kroah-Hartman (Linux Foundation Fellow)
+  - Thomas Gleixner (Linux Foundation Fellow)
+
+Operation of mailing-lists
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The encrypted mailing-lists which are used in our process are hosted on
+Linux Foundation's IT infrastructure. By providing this service Linux
+Foundation's director of IT Infrastructure security technically has the
+ability to access the embargoed information, but is obliged to
+confidentiality by his employment contract. Linux Foundation's director of
+IT Infrastructure security is also responsible for the kernel.org
+infrastructure.
+
+The Linux Foundation's current director of IT Infrastructure security is
+Konstantin Ryabitsev.
+
+
+Non-disclosure agreements
+-------------------------
+
+The Linux kernel hardware security team is not a formal body and therefore
+unable to enter into any non-disclosure agreements.  The kernel community
+is aware of the sensitive nature of such issues and offers a Memorandum of
+Understanding instead.
+
+
+Memorandum of Understanding
+---------------------------
+
+The Linux kernel community has a deep understanding of the requirement to
+keep hardware security issues under embargo for coordination between
+different OS vendors, distributors, hardware vendors and other parties.
+
+The Linux kernel community has successfully handled hardware security
+issues in the past and has the necessary mechanisms in place to allow
+community compliant development under embargo restrictions.
+
+The Linux kernel community has a dedicated hardware security team for
+initial contact, which oversees the process of handling such issues under
+embargo rules.
+
+The hardware security team identifies the developers (domain experts) who
+will form the initial response team for a particular issue. The initial
+response team can bring in further developers (domain experts) to address
+the issue in the best technical way.
+
+All involved developers pledge to adhere to the embargo rules and to keep
+the received information confidential. Violation of the pledge will lead to
+immediate exclusion from the current issue and removal from all related
+mailing-lists. In addition, the hardware security team will also exclude
+the offender from future issues. The impact of this consequence is a highly
+effective deterrent in our community. In case a violation happens the
+hardware security team will inform the involved parties immediately. If you
+or anyone becomes aware of a potential violation, please report it
+immediately to the Hardware security officers.
+
+
+Process
+^^^^^^^
+
+Due to the globally distributed nature of Linux kernel development,
+face-to-face meetings are almost impossible to address hardware security
+issues.  Phone conferences are hard to coordinate due to time zones and
+other factors and should be only used when absolutely necessary. Encrypted
+email has been proven to be the most effective and secure communication
+method for these types of issues.
+
+Start of Disclosure
+"""""""""""""""""""
+
+Disclosure starts by contacting the Linux kernel hardware security team by
+email. This initial contact should contain a description of the problem and
+a list of any known affected hardware. If your organization builds or
+distributes the affected hardware, we encourage you to also consider what
+other hardware could be affected.
+
+The hardware security team will provide an incident-specific encrypted
+mailing-list which will be used for initial discussion with the reporter,
+further disclosure and coordination.
+
+The hardware security team will provide the disclosing party a list of
+developers (domain experts) who should be informed initially about the
+issue after confirming with the developers  that they will adhere to this
+Memorandum of Understanding and the documented process. These developers
+form the initial response team and will be responsible for handling the
+issue after initial contact. The hardware security team is supporting the
+response team, but is not necessarily involved in the mitigation
+development process.
+
+While individual developers might be covered by a non-disclosure agreement
+via their employer, they cannot enter individual non-disclosure agreements
+in their role as Linux kernel developers. They will, however, agree to
+adhere to this documented process and the Memorandum of Understanding.
+
+
+Disclosure
+""""""""""
+
+The disclosing party provides detailed information to the initial response
+team via the specific encrypted mailing-list.
+
+From our experience the technical documentation of these issues is usually
+a sufficient starting point and further technical clarification is best
+done via email.
+
+Mitigation development
+""""""""""""""""""""""
+
+The initial response team sets up an encrypted mailing-list or repurposes
+an existing one if appropriate. The disclosing party should provide a list
+of contacts for all other parties who have already been, or should be,
+informed about the issue. The response team contacts these parties so they
+can name experts who should be subscribed to the mailing-list.
+
+Using a mailing-list is close to the normal Linux development process and
+has been successfully used in developing mitigations for various hardware
+security issues in the past.
+
+The mailing-list operates in the same way as normal Linux development.
+Patches are posted, discussed and reviewed and if agreed on applied to a
+non-public git repository which is only accessible to the participating
+developers via a secure connection. The repository contains the main
+development branch against the mainline kernel and backport branches for
+stable kernel versions as necessary.
+
+The initial response team will identify further experts from the Linux
+kernel developer community as needed and inform the disclosing party about
+their participation. Bringing in experts can happen at any time of the
+development process and often needs to be handled in a timely manner.
+
+Coordinated release
+"""""""""""""""""""
+
+The involved parties will negotiate the date and time where the embargo
+ends. At that point the prepared mitigations are integrated into the
+relevant kernel trees and published.
+
+While we understand that hardware security issues need coordinated embargo
+time, the embargo time should be constrained to the minimum time which is
+required for all involved parties to develop, test and prepare the
+mitigations. Extending embargo time artificially to meet conference talk
+dates or other non-technical reasons is creating more work and burden for
+the involved developers and response teams as the patches need to be kept
+up to date in order to follow the ongoing upstream kernel development,
+which might create conflicting changes.
+
+CVE assignment
+""""""""""""""
+
+Neither the hardware security team nor the initial response team assign
+CVEs, nor are CVEs required for the development process. If CVEs are
+provided by the disclosing party they can be used for documentation
+purposes.
+
+Process ambassadors
+-------------------
+
+For assistance with this process we have established ambassadors in various
+organizations, who can answer questions about or provide guidance on the
+reporting process and further handling. Ambassadors are not involved in the
+disclosure of a particular issue, unless requested by a response team or by
+an involved disclosed party. The current ambassadors list:
+
+  ============= ========================================================
+  ARM
+  AMD
+  IBM
+  Intel
+  Qualcomm     Trilok Soni <tsoni@codeaurora.org>
+
+  Microsoft    Sasha Levin <sashal@kernel.org>
+  VMware
+  Xen          Andrew Cooper <andrew.cooper3@citrix.com>
+
+  Canonical    Tyler Hicks <tyhicks@canonical.com>
+  Debian       Ben Hutchings <ben@decadent.org.uk>
+  Oracle       Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+  Red Hat      Josh Poimboeuf <jpoimboe@redhat.com>
+  SUSE         Jiri Kosina <jkosina@suse.cz>
+
+  Amazon
+  Google       Kees Cook <keescook@chromium.org>
+  ============= ========================================================
+
+If you want your organization to be added to the ambassadors list, please
+contact the hardware security team. The nominated ambassador has to
+understand and support our process fully and is ideally well connected in
+the Linux kernel community.
+
+Encrypted mailing-lists
+-----------------------
+
+We use encrypted mailing-lists for communication. The operating principle
+of these lists is that email sent to the list is encrypted either with the
+list's PGP key or with the list's S/MIME certificate. The mailing-list
+software decrypts the email and re-encrypts it individually for each
+subscriber with the subscriber's PGP key or S/MIME certificate. Details
+about the mailing-list software and the setup which is used to ensure the
+security of the lists and protection of the data can be found here:
+https://www.kernel.org/....
+
+List keys
+^^^^^^^^^
+
+For initial contact see :ref:`Contact`. For incident specific mailing-lists
+the key and S/MIME certificate are conveyed to the subscribers by email
+sent from the specific list.
+
+Subscription to incident specific lists
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Subscription is handled by the response teams. Disclosed parties who want
+to participate in the communication send a list of potential subscribers to
+the response team so the response team can validate subscription requests.
+
+Each subscriber needs to send a subscription request to the response team
+by email. The email must be signed with the subscriber's PGP key or S/MIME
+certificate. If a PGP key is used, it must be available from a public key
+server and is ideally connected to the Linux kernel's PGP web of trust. See
+also: https://www.kernel.org/signature.html.
+
+The response team verifies that the subscriber request is valid and adds
+the subscriber to the list. After subscription the subscriber will receive
+email from the mailing-list which is signed either with the list's PGP key
+or the list's S/MIME certificate. The subscriber's email client can extract
+the PGP key or the S/MIME certificate from the signature so the subscriber
+can send encrypted email to the list.
+
index 878ebfda7eeff378a2fee48e3b361aa6b3587896..e2c9ffc682c520c0a91036372bcdc8d707c2a78a 100644 (file)
@@ -45,6 +45,7 @@ Other guides to the community that are of interest to most developers are:
    submit-checklist
    kernel-docs
    deprecated
+   embargoed-hardware-issues
 
 These are some overall technical guides that have been put here for now for
 lack of a better place.
index 1b73fea23b39f11fee9be7207fb8b359c0e7e73f..14b1492f689bbe71c983a1baba1756d4e79e4204 100644 (file)
@@ -18,7 +18,7 @@ The following 64-byte header is present in decompressed Linux kernel image.
        u32 res1  = 0;            /* Reserved */
        u64 res2  = 0;            /* Reserved */
        u64 magic = 0x5643534952; /* Magic number, little endian, "RISCV" */
-       u32 res3;                 /* Reserved for additional RISC-V specific header */
+       u32 magic2 = 0x56534905;  /* Magic number 2, little endian, "RSC\x05" */
        u32 res4;                 /* Reserved for PE COFF offset */
 
 This header format is compliant with PE/COFF header and largely inspired from
@@ -37,13 +37,14 @@ Notes:
        Bits 16:31 - Major version
 
   This preserves compatibility across newer and older version of the header.
-  The current version is defined as 0.1.
+  The current version is defined as 0.2.
 
-- res3 is reserved for offset to any other additional fields. This makes the
-  header extendible in future. One example would be to accommodate ISA
-  extension for RISC-V in future. For current version, it is set to be zero.
+- The "magic" field is deprecated as of version 0.2.  In a future
+  release, it may be removed.  This originally should have matched up
+  with the ARM64 header "magic" field, but unfortunately does not.
+  The "magic2" field replaces it, matching up with the ARM64 header.
 
-- In current header, the flag field has only one field.
+- In current header, the flags field has only one field.
        Bit 0: Kernel endianness. 1 if BE, 0 if LE.
 
 - Image size is mandatory for boot loader to load kernel image. Booting will
index 1e210c6afa8898e4f2588644caa7fcc163f246fc..fca9c4f5bd9c0162778dff70b2514d4631768564 100644 (file)
@@ -180,6 +180,13 @@ The process of how these work together.
    add it to an iommu_group and a vfio_group. Then we could pass through
    the mdev to a guest.
 
+
+VFIO-CCW Regions
+----------------
+
+The vfio-ccw driver exposes MMIO regions to accept requests from and return
+results to userspace.
+
 vfio-ccw I/O region
 -------------------
 
@@ -205,6 +212,25 @@ irb_area stores the I/O result.
 
 ret_code stores a return code for each access of the region.
 
+This region is always available.
+
+vfio-ccw cmd region
+-------------------
+
+The vfio-ccw cmd region is used to accept asynchronous instructions
+from userspace::
+
+  #define VFIO_CCW_ASYNC_CMD_HSCH (1 << 0)
+  #define VFIO_CCW_ASYNC_CMD_CSCH (1 << 1)
+  struct ccw_cmd_region {
+         __u32 command;
+         __u32 ret_code;
+  } __packed;
+
+This region is exposed via region type VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD.
+
+Currently, CLEAR SUBCHANNEL and HALT SUBCHANNEL use this region.
+
 vfio-ccw operation details
 --------------------------
 
@@ -306,9 +332,8 @@ Together with the corresponding work in QEMU, we can bring the passed
 through DASD/ECKD device online in a guest now and use it as a block
 device.
 
-While the current code allows the guest to start channel programs via
-START SUBCHANNEL, support for HALT SUBCHANNEL or CLEAR SUBCHANNEL is
-not yet implemented.
+The current code allows the guest to start channel programs via
+START SUBCHANNEL, and to issue HALT SUBCHANNEL and CLEAR SUBCHANNEL.
 
 vfio-ccw supports classic (command mode) channel I/O only. Transport
 mode (HPF) is not supported.
diff --git a/Documentation/sh/conf.py b/Documentation/sh/conf.py
deleted file mode 100644 (file)
index 1eb684a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "SuperH architecture implementation manual"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'sh.tex', project,
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/sound/conf.py b/Documentation/sound/conf.py
deleted file mode 100644 (file)
index 3f1fc5e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux Sound Subsystem Documentation"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'sound.tex', project,
-     'The kernel development community', 'manual'),
-]
index 301a21aa4f631d8477445c4951da9e329189bad2..eeb394b39e2cc8dc8d8f866a379cf492f5d8b73b 100644 (file)
@@ -21,6 +21,29 @@ def loadConfig(namespace):
         and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ):
         config_file = os.path.abspath(config_file)
 
+        # Let's avoid one conf.py file just due to latex_documents
+        start = config_file.find('Documentation/')
+        if start >= 0:
+            start = config_file.find('/', start + 1)
+
+        end = config_file.rfind('/')
+        if start >= 0 and end > 0:
+            dir = config_file[start + 1:end]
+
+            print("source directory: %s" % dir)
+            new_latex_docs = []
+            latex_documents = namespace['latex_documents']
+
+            for l in latex_documents:
+                if l[0].find(dir + '/') == 0:
+                    has = True
+                    fn = l[0][len(dir) + 1:]
+                    new_latex_docs.append((fn, l[1], l[2], l[3], l[4]))
+                    break
+
+            namespace['latex_documents'] = new_latex_docs
+
+        # If there is an extra conf.py file, load it
         if os.path.isfile(config_file):
             sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
             config = namespace.copy()
@@ -29,4 +52,6 @@ def loadConfig(namespace):
             del config['__file__']
             namespace.update(config)
         else:
-            sys.stderr.write("WARNING: additional sphinx-config not found: %s\n" % config_file)
+            config = namespace.copy()
+            config['tags'].add("subproject")
+            namespace.update(config)
index 1739cba8863e53b008854e6cf77bdf4d8f9087e2..f1ad4504b734de217b8e051aed3b496fce68d835 100644 (file)
@@ -242,8 +242,9 @@ del kernel:
 * Per inserire blocchi di testo con caratteri a dimensione fissa (codici di
   esempio, casi d'uso, eccetera): utilizzate ``::`` quando non è necessario
   evidenziare la sintassi, specialmente per piccoli frammenti; invece,
-  utilizzate ``.. code-block:: <language>`` per blocchi di più lunghi che
-  potranno beneficiare dell'avere la sintassi evidenziata.
+  utilizzate ``.. code-block:: <language>`` per blocchi più lunghi che
+  beneficeranno della sintassi evidenziata. Per un breve pezzo di codice da
+  inserire nel testo, usate \`\`.
 
 
 Il dominio C
@@ -267,12 +268,14 @@ molto comune come ``open`` o ``ioctl``:
 
 Il nome della funzione (per esempio ioctl) rimane nel testo ma il nome del suo
 riferimento cambia da ``ioctl`` a ``VIDIOC_LOG_STATUS``. Anche la voce
-nell'indice cambia in ``VIDIOC_LOG_STATUS`` e si potrà quindi fare riferimento
-a questa funzione scrivendo:
-
-.. code-block:: rst
-
-     :c:func:`VIDIOC_LOG_STATUS`
+nell'indice cambia in ``VIDIOC_LOG_STATUS``.
+
+Notate che per una funzione non c'è bisogno di usare ``c:func:`` per generarne
+i riferimenti nella documentazione. Grazie a qualche magica estensione a
+Sphinx, il sistema di generazione della documentazione trasformerà
+automaticamente un riferimento ad una ``funzione()`` in un riferimento
+incrociato quando questa ha una voce nell'indice.  Se trovate degli usi di
+``c:func:`` nella documentazione del kernel, sentitevi liberi di rimuoverli.
 
 
 Tabelle a liste
index 2eda85d5cd1e53bb4792ee8f453db2bfd31cd90f..012de0f3154abcafe045c970080b7fc4d4088e9d 100644 (file)
@@ -27,6 +27,7 @@ Di seguito le guide che ogni sviluppatore dovrebbe leggere.
    code-of-conduct
    development-process
    submitting-patches
+   programming-language
    coding-style
    maintainer-pgp-guide
    email-clients
index 7bd70d66173764969f65d0c38c5f360c617aa6a6..38e0a955121a49de368ca378d3b1abad62106249 100644 (file)
@@ -1,6 +1,7 @@
 .. include:: ../disclaimer-ita.rst
 
 :Original: :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
 
 
 .. _it_kernel_docs:
@@ -8,6 +9,10 @@
 Indice di documenti per le persone interessate a capire e/o scrivere per il kernel Linux
 ========================================================================================
 
-.. warning::
-
-    TODO ancora da tradurre
+.. note::
+   Questo documento contiene riferimenti a documenti in lingua inglese; inoltre
+   utilizza dai campi *ReStructuredText* di supporto alla ricerca e che per
+   questo motivo è meglio non tradurre al fine di garantirne un corretto
+   utilizzo.
+   Per questi motivi il documento non verrà tradotto. Per favore fate
+   riferimento al documento originale in lingua inglese.
index 276db0e37f439420d2b3dda1e0710095216136da..118fb4153e8fdd0ecb24129095f2199fc7c9926b 100644 (file)
@@ -248,7 +248,10 @@ possano ricevere la vostra nuova sottochiave::
     kernel.
 
     Se per qualche ragione preferite rimanere con sottochiavi RSA, nel comando
-    precedente, sostituite "ed25519" con "rsa2048".
+    precedente, sostituite "ed25519" con "rsa2048". In aggiunta, se avete
+    intenzione di usare un dispositivo hardware che non supporta le chiavi
+    ED25519 ECC, come la Nitrokey Pro o la Yubikey, allora dovreste usare
+    "nistp256" al posto di "ed25519".
 
 Copia di riserva della chiave primaria per gestire il recupero da disastro
 --------------------------------------------------------------------------
@@ -449,23 +452,27 @@ implementi le funzionalità delle smartcard.  Sul mercato ci sono diverse
 soluzioni disponibili:
 
 - `Nitrokey Start`_: è Open hardware e Free Software, è basata sul progetto
-  `GnuK`_ della FSIJ. Ha il supporto per chiavi ECC, ma meno funzionalità di
-  sicurezza (come la resistenza alla manomissione o alcuni attacchi ad un
-  canale laterale).
+  `GnuK`_ della FSIJ. Questo è uno dei pochi dispositivi a supportare le chiavi
+  ECC ED25519, ma offre meno funzionalità di sicurezza (come la resistenza
+  alla manomissione o alcuni attacchi ad un canale laterale).
 - `Nitrokey Pro`_: è simile alla Nitrokey Start, ma è più resistente alla
-  manomissione e offre più funzionalità di sicurezza, ma l'ECC.
-- `Yubikey 4`_: l'hardware e il software sono proprietari, ma è più economica
+  manomissione e offre più funzionalità di sicurezza. La Pro 2 supporta la
+  crittografia ECC (NISTP).
+- `Yubikey 5`_: l'hardware e il software sono proprietari, ma è più economica
   della  Nitrokey Pro ed è venduta anche con porta USB-C il che è utile con i
   computer portatili più recenti. In aggiunta, offre altre funzionalità di
-  sicurezza come FIDO, U2F, ma non l'ECC
+  sicurezza come FIDO, U2F, e ora supporta anche le chiavi ECC (NISTP)
 
 `Su LWN c'è una buona recensione`_ dei modelli elencati qui sopra e altri.
+La scelta dipenderà dal costo, dalla disponibilità nella vostra area
+geografica e vostre considerazioni sull'hardware aperto/proprietario.
+
 Se volete usare chiavi ECC, la vostra migliore scelta sul mercato è la
 Nitrokey Start.
 
 .. _`Nitrokey Start`: https://shop.nitrokey.com/shop/product/nitrokey-start-6
-.. _`Nitrokey Pro`: https://shop.nitrokey.com/shop/product/nitrokey-pro-3
-.. _`Yubikey 4`: https://www.yubico.com/product/yubikey-4-series/
+.. _`Nitrokey Pro 2`: https://shop.nitrokey.com/shop/product/nitrokey-pro-2-3
+.. _`Yubikey 5`: https://www.yubico.com/product/yubikey-5-overview/
 .. _Gnuk: http://www.fsij.org/doc-gnuk/
 .. _`Su LWN c'è una buona recensione`: https://lwn.net/Articles/736231/
 
diff --git a/Documentation/translations/it_IT/process/programming-language.rst b/Documentation/translations/it_IT/process/programming-language.rst
new file mode 100644 (file)
index 0000000..f4b0063
--- /dev/null
@@ -0,0 +1,51 @@
+.. include:: ../disclaimer-ita.rst
+
+:Original: :ref:`Documentation/process/programming-language.rst <programming_language>`
+:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
+
+.. _it_programming_language:
+
+Linguaggio di programmazione
+============================
+
+Il kernel è scritto nel linguaggio di programmazione C [c-language]_.
+Più precisamente, il kernel viene compilato con ``gcc`` [gcc]_ usando
+l'opzione ``-std=gnu89`` [gcc-c-dialect-options]_: il dialetto GNU
+dello standard ISO C90 (con l'aggiunta di alcune funzionalità da C99)
+
+Questo dialetto contiene diverse estensioni al linguaggio [gnu-extensions]_,
+e molte di queste vengono usate sistematicamente dal kernel.
+
+Il kernel offre un certo livello di supporto per la compilazione con ``clang``
+[clang]_ e ``icc`` [icc]_ su diverse architetture, tuttavia in questo momento
+il supporto non è completo e richiede delle patch aggiuntive.
+
+Attributi
+---------
+
+Una delle estensioni più comuni e usate nel kernel sono gli attributi
+[gcc-attribute-syntax]_. Gli attributi permettono di aggiungere una semantica,
+definita dell'implementazione, alle entità del linguaggio (come le variabili,
+le funzioni o i tipi) senza dover fare importanti modifiche sintattiche al
+linguaggio stesso (come l'aggiunta di nuove parole chiave) [n2049]_.
+
+In alcuni casi, gli attributi sono opzionali (ovvero un compilatore che non
+dovesse supportarli dovrebbe produrre comunque codice corretto, anche se
+più lento o che non esegue controlli aggiuntivi durante la compilazione).
+
+Il kernel definisce alcune pseudo parole chiave (per esempio ``__pure``)
+in alternativa alla sintassi GNU per gli attributi (per esempio
+``__attribute__((__pure__))``) allo scopo di mostrare quali funzionalità si
+possono usare e/o per accorciare il codice.
+
+Per maggiori informazioni consultate il file d'intestazione
+``include/linux/compiler_attributes.h``.
+
+.. [c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards
+.. [gcc] https://gcc.gnu.org
+.. [clang] https://clang.llvm.org
+.. [icc] https://software.intel.com/en-us/c-compilers
+.. [gcc-c-dialect-options] https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+.. [gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+.. [gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+.. [n2049] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
index a33c2a5365420822d3e4050483acb639728a822c..2774624ee8439af4de2de5e3c6501b3e43d0ff09 100644 (file)
@@ -569,7 +569,7 @@ ACQUIRE 는 해당 오퍼레이션의 로드 부분에만 적용되고 RELEASE 
 
        [*] 버스 마스터링 DMA 와 일관성에 대해서는 다음을 참고하시기 바랍니다:
 
-           Documentation/PCI/pci.rst
+           Documentation/driver-api/pci/pci.rst
            Documentation/DMA-API-HOWTO.txt
            Documentation/DMA-API.txt
 
diff --git a/Documentation/userspace-api/conf.py b/Documentation/userspace-api/conf.py
deleted file mode 100644 (file)
index 2eaf59f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "The Linux kernel user-space API guide"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'userspace-api.tex', project,
-     'The kernel development community', 'manual'),
-]
diff --git a/Documentation/virt/index.rst b/Documentation/virt/index.rst
new file mode 100644 (file)
index 0000000..062ffb5
--- /dev/null
@@ -0,0 +1,18 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================
+Linux Virtualization Support
+============================
+
+.. toctree::
+   :maxdepth: 2
+
+   kvm/index
+   paravirt_ops
+
+.. only:: html and subproject
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/virt/kvm/amd-memory-encryption.rst b/Documentation/virt/kvm/amd-memory-encryption.rst
new file mode 100644 (file)
index 0000000..d18c97b
--- /dev/null
@@ -0,0 +1,250 @@
+======================================
+Secure Encrypted Virtualization (SEV)
+======================================
+
+Overview
+========
+
+Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
+
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When enabled,
+the memory contents of a VM will be transparently encrypted with a key
+unique to that VM.
+
+The hypervisor can determine the SEV support through the CPUID
+instruction. The CPUID function 0x8000001f reports information related
+to SEV::
+
+       0x8000001f[eax]:
+                       Bit[1]  indicates support for SEV
+           ...
+                 [ecx]:
+                       Bits[31:0]  Number of encrypted guests supported simultaneously
+
+If support for SEV is present, MSR 0xc001_0010 (MSR_K8_SYSCFG) and MSR 0xc001_0015
+(MSR_K7_HWCR) can be used to determine if it can be enabled::
+
+       0xc001_0010:
+               Bit[23]    1 = memory encryption can be enabled
+                          0 = memory encryption can not be enabled
+
+       0xc001_0015:
+               Bit[0]     1 = memory encryption can be enabled
+                          0 = memory encryption can not be enabled
+
+When SEV support is available, it can be enabled in a specific VM by
+setting the SEV bit before executing VMRUN.::
+
+       VMCB[0x90]:
+               Bit[1]      1 = SEV is enabled
+                           0 = SEV is disabled
+
+SEV hardware uses ASIDs to associate a memory encryption key with a VM.
+Hence, the ASID for the SEV-enabled guests must be from 1 to a maximum value
+defined in the CPUID 0x8000001f[ecx] field.
+
+SEV Key Management
+==================
+
+The SEV guest key management is handled by a separate processor called the AMD
+Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a secure
+key management interface to perform common hypervisor activities such as
+encrypting bootstrap code, snapshot, migrating and debugging the guest. For more
+information, see the SEV Key Management spec [api-spec]_
+
+KVM implements the following commands to support common lifecycle events of SEV
+guests, such as launching, running, snapshotting, migrating and decommissioning.
+
+1. KVM_SEV_INIT
+---------------
+
+The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform
+context. In a typical workflow, this command should be the first command issued.
+
+Returns: 0 on success, -negative on error
+
+2. KVM_SEV_LAUNCH_START
+-----------------------
+
+The KVM_SEV_LAUNCH_START command is used for creating the memory encryption
+context. To create the encryption context, user must provide a guest policy,
+the owner's public Diffie-Hellman (PDH) key and session information.
+
+Parameters: struct  kvm_sev_launch_start (in/out)
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_launch_start {
+                __u32 handle;           /* if zero then firmware creates a new handle */
+                __u32 policy;           /* guest's policy */
+
+                __u64 dh_uaddr;         /* userspace address pointing to the guest owner's PDH key */
+                __u32 dh_len;
+
+                __u64 session_addr;     /* userspace address which points to the guest session information */
+                __u32 session_len;
+        };
+
+On success, the 'handle' field contains a new handle and on error, a negative value.
+
+For more details, see SEV spec Section 6.2.
+
+3. KVM_SEV_LAUNCH_UPDATE_DATA
+-----------------------------
+
+The KVM_SEV_LAUNCH_UPDATE_DATA is used for encrypting a memory region. It also
+calculates a measurement of the memory contents. The measurement is a signature
+of the memory contents that can be sent to the guest owner as an attestation
+that the memory was encrypted correctly by the firmware.
+
+Parameters (in): struct  kvm_sev_launch_update_data
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_launch_update {
+                __u64 uaddr;    /* userspace address to be encrypted (must be 16-byte aligned) */
+                __u32 len;      /* length of the data to be encrypted (must be 16-byte aligned) */
+        };
+
+For more details, see SEV spec Section 6.3.
+
+4. KVM_SEV_LAUNCH_MEASURE
+-------------------------
+
+The KVM_SEV_LAUNCH_MEASURE command is used to retrieve the measurement of the
+data encrypted by the KVM_SEV_LAUNCH_UPDATE_DATA command. The guest owner may
+wait to provide the guest with confidential information until it can verify the
+measurement. Since the guest owner knows the initial contents of the guest at
+boot, the measurement can be verified by comparing it to what the guest owner
+expects.
+
+Parameters (in): struct  kvm_sev_launch_measure
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_launch_measure {
+                __u64 uaddr;    /* where to copy the measurement */
+                __u32 len;      /* length of measurement blob */
+        };
+
+For more details on the measurement verification flow, see SEV spec Section 6.4.
+
+5. KVM_SEV_LAUNCH_FINISH
+------------------------
+
+After completion of the launch flow, the KVM_SEV_LAUNCH_FINISH command can be
+issued to make the guest ready for the execution.
+
+Returns: 0 on success, -negative on error
+
+6. KVM_SEV_GUEST_STATUS
+-----------------------
+
+The KVM_SEV_GUEST_STATUS command is used to retrieve status information about a
+SEV-enabled guest.
+
+Parameters (out): struct kvm_sev_guest_status
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_guest_status {
+                __u32 handle;   /* guest handle */
+                __u32 policy;   /* guest policy */
+                __u8 state;     /* guest state (see enum below) */
+        };
+
+SEV guest state:
+
+::
+
+        enum {
+        SEV_STATE_INVALID = 0;
+        SEV_STATE_LAUNCHING,    /* guest is currently being launched */
+        SEV_STATE_SECRET,       /* guest is being launched and ready to accept the ciphertext data */
+        SEV_STATE_RUNNING,      /* guest is fully launched and running */
+        SEV_STATE_RECEIVING,    /* guest is being migrated in from another SEV machine */
+        SEV_STATE_SENDING       /* guest is getting migrated out to another SEV machine */
+        };
+
+7. KVM_SEV_DBG_DECRYPT
+----------------------
+
+The KVM_SEV_DEBUG_DECRYPT command can be used by the hypervisor to request the
+firmware to decrypt the data at the given memory region.
+
+Parameters (in): struct kvm_sev_dbg
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_dbg {
+                __u64 src_uaddr;        /* userspace address of data to decrypt */
+                __u64 dst_uaddr;        /* userspace address of destination */
+                __u32 len;              /* length of memory region to decrypt */
+        };
+
+The command returns an error if the guest policy does not allow debugging.
+
+8. KVM_SEV_DBG_ENCRYPT
+----------------------
+
+The KVM_SEV_DEBUG_ENCRYPT command can be used by the hypervisor to request the
+firmware to encrypt the data at the given memory region.
+
+Parameters (in): struct kvm_sev_dbg
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_dbg {
+                __u64 src_uaddr;        /* userspace address of data to encrypt */
+                __u64 dst_uaddr;        /* userspace address of destination */
+                __u32 len;              /* length of memory region to encrypt */
+        };
+
+The command returns an error if the guest policy does not allow debugging.
+
+9. KVM_SEV_LAUNCH_SECRET
+------------------------
+
+The KVM_SEV_LAUNCH_SECRET command can be used by the hypervisor to inject secret
+data after the measurement has been validated by the guest owner.
+
+Parameters (in): struct kvm_sev_launch_secret
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_launch_secret {
+                __u64 hdr_uaddr;        /* userspace address containing the packet header */
+                __u32 hdr_len;
+
+                __u64 guest_uaddr;      /* the guest memory region where the secret should be injected */
+                __u32 guest_len;
+
+                __u64 trans_uaddr;      /* the hypervisor memory region which contains the secret */
+                __u32 trans_len;
+        };
+
+References
+==========
+
+
+See [white-paper]_, [api-spec]_, [amd-apm]_ and [kvm-forum]_ for more info.
+
+.. [white-paper] http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
+.. [api-spec] http://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
+.. [amd-apm] http://support.amd.com/TechDocs/24593.pdf (section 15.34)
+.. [kvm-forum]  http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
diff --git a/Documentation/virt/kvm/api.txt b/Documentation/virt/kvm/api.txt
new file mode 100644 (file)
index 0000000..2d06776
--- /dev/null
@@ -0,0 +1,5296 @@
+The Definitive KVM (Kernel-based Virtual Machine) API Documentation
+===================================================================
+
+1. General description
+----------------------
+
+The kvm API is a set of ioctls that are issued to control various aspects
+of a virtual machine.  The ioctls belong to three classes:
+
+ - System ioctls: These query and set global attributes which affect the
+   whole kvm subsystem.  In addition a system ioctl is used to create
+   virtual machines.
+
+ - VM ioctls: These query and set attributes that affect an entire virtual
+   machine, for example memory layout.  In addition a VM ioctl is used to
+   create virtual cpus (vcpus) and devices.
+
+   VM ioctls must be issued from the same process (address space) that was
+   used to create the VM.
+
+ - vcpu ioctls: These query and set attributes that control the operation
+   of a single virtual cpu.
+
+   vcpu ioctls should be issued from the same thread that was used to create
+   the vcpu, except for asynchronous vcpu ioctl that are marked as such in
+   the documentation.  Otherwise, the first ioctl after switching threads
+   could see a performance impact.
+
+ - device ioctls: These query and set attributes that control the operation
+   of a single device.
+
+   device ioctls must be issued from the same process (address space) that
+   was used to create the VM.
+
+2. File descriptors
+-------------------
+
+The kvm API is centered around file descriptors.  An initial
+open("/dev/kvm") obtains a handle to the kvm subsystem; this handle
+can be used to issue system ioctls.  A KVM_CREATE_VM ioctl on this
+handle will create a VM file descriptor which can be used to issue VM
+ioctls.  A KVM_CREATE_VCPU or KVM_CREATE_DEVICE ioctl on a VM fd will
+create a virtual cpu or device and return a file descriptor pointing to
+the new resource.  Finally, ioctls on a vcpu or device fd can be used
+to control the vcpu or device.  For vcpus, this includes the important
+task of actually running guest code.
+
+In general file descriptors can be migrated among processes by means
+of fork() and the SCM_RIGHTS facility of unix domain socket.  These
+kinds of tricks are explicitly not supported by kvm.  While they will
+not cause harm to the host, their actual behavior is not guaranteed by
+the API.  See "General description" for details on the ioctl usage
+model that is supported by KVM.
+
+It is important to note that althought VM ioctls may only be issued from
+the process that created the VM, a VM's lifecycle is associated with its
+file descriptor, not its creator (process).  In other words, the VM and
+its resources, *including the associated address space*, are not freed
+until the last reference to the VM's file descriptor has been released.
+For example, if fork() is issued after ioctl(KVM_CREATE_VM), the VM will
+not be freed until both the parent (original) process and its child have
+put their references to the VM's file descriptor.
+
+Because a VM's resources are not freed until the last reference to its
+file descriptor is released, creating additional references to a VM via
+via fork(), dup(), etc... without careful consideration is strongly
+discouraged and may have unwanted side effects, e.g. memory allocated
+by and on behalf of the VM's process may not be freed/unaccounted when
+the VM is shut down.
+
+
+3. Extensions
+-------------
+
+As of Linux 2.6.22, the KVM ABI has been stabilized: no backward
+incompatible change are allowed.  However, there is an extension
+facility that allows backward-compatible extensions to the API to be
+queried and used.
+
+The extension mechanism is not based on the Linux version number.
+Instead, kvm defines extension identifiers and a facility to query
+whether a particular extension identifier is available.  If it is, a
+set of ioctls is available for application use.
+
+
+4. API description
+------------------
+
+This section describes ioctls that can be used to control kvm guests.
+For each ioctl, the following information is provided along with a
+description:
+
+  Capability: which KVM extension provides this ioctl.  Can be 'basic',
+      which means that is will be provided by any kernel that supports
+      API version 12 (see section 4.1), a KVM_CAP_xyz constant, which
+      means availability needs to be checked with KVM_CHECK_EXTENSION
+      (see section 4.4), or 'none' which means that while not all kernels
+      support this ioctl, there's no capability bit to check its
+      availability: for kernels that don't support the ioctl,
+      the ioctl returns -ENOTTY.
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Type: system, vm, or vcpu.
+
+  Parameters: what parameters are accepted by the ioctl.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+
+4.1 KVM_GET_API_VERSION
+
+Capability: basic
+Architectures: all
+Type: system ioctl
+Parameters: none
+Returns: the constant KVM_API_VERSION (=12)
+
+This identifies the API version as the stable kvm API. It is not
+expected that this number will change.  However, Linux 2.6.20 and
+2.6.21 report earlier versions; these are not documented and not
+supported.  Applications should refuse to run if KVM_GET_API_VERSION
+returns a value other than 12.  If this check passes, all ioctls
+described as 'basic' will be available.
+
+
+4.2 KVM_CREATE_VM
+
+Capability: basic
+Architectures: all
+Type: system ioctl
+Parameters: machine type identifier (KVM_VM_*)
+Returns: a VM fd that can be used to control the new virtual machine.
+
+The new VM has no virtual cpus and no memory.
+You probably want to use 0 as machine type.
+
+In order to create user controlled virtual machines on S390, check
+KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
+privileged user (CAP_SYS_ADMIN).
+
+To use hardware assisted virtualization on MIPS (VZ ASE) rather than
+the default trap & emulate implementation (which changes the virtual
+memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
+flag KVM_VM_MIPS_VZ.
+
+
+On arm64, the physical address size for a VM (IPA Size limit) is limited
+to 40bits by default. The limit can be configured if the host supports the
+extension KVM_CAP_ARM_VM_IPA_SIZE. When supported, use
+KVM_VM_TYPE_ARM_IPA_SIZE(IPA_Bits) to set the size in the machine type
+identifier, where IPA_Bits is the maximum width of any physical
+address used by the VM. The IPA_Bits is encoded in bits[7-0] of the
+machine type identifier.
+
+e.g, to configure a guest to use 48bit physical address size :
+
+    vm_fd = ioctl(dev_fd, KVM_CREATE_VM, KVM_VM_TYPE_ARM_IPA_SIZE(48));
+
+The requested size (IPA_Bits) must be :
+  0 - Implies default size, 40bits (for backward compatibility)
+
+  or
+
+  N - Implies N bits, where N is a positive integer such that,
+      32 <= N <= Host_IPA_Limit
+
+Host_IPA_Limit is the maximum possible value for IPA_Bits on the host and
+is dependent on the CPU capability and the kernel configuration. The limit can
+be retrieved using KVM_CAP_ARM_VM_IPA_SIZE of the KVM_CHECK_EXTENSION
+ioctl() at run-time.
+
+Please note that configuring the IPA size does not affect the capability
+exposed by the guest CPUs in ID_AA64MMFR0_EL1[PARange]. It only affects
+size of the address translated by the stage2 level (guest physical to
+host physical address translations).
+
+
+4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST
+
+Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST
+Architectures: x86
+Type: system ioctl
+Parameters: struct kvm_msr_list (in/out)
+Returns: 0 on success; -1 on error
+Errors:
+  EFAULT:    the msr index list cannot be read from or written to
+  E2BIG:     the msr index list is to be to fit in the array specified by
+             the user.
+
+struct kvm_msr_list {
+       __u32 nmsrs; /* number of msrs in entries */
+       __u32 indices[0];
+};
+
+The user fills in the size of the indices array in nmsrs, and in return
+kvm adjusts nmsrs to reflect the actual number of msrs and fills in the
+indices array with their numbers.
+
+KVM_GET_MSR_INDEX_LIST returns the guest msrs that are supported.  The list
+varies by kvm version and host processor, but does not change otherwise.
+
+Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are
+not returned in the MSR list, as different vcpus can have a different number
+of banks, as set via the KVM_X86_SETUP_MCE ioctl.
+
+KVM_GET_MSR_FEATURE_INDEX_LIST returns the list of MSRs that can be passed
+to the KVM_GET_MSRS system ioctl.  This lets userspace probe host capabilities
+and processor features that are exposed via MSRs (e.g., VMX capabilities).
+This list also varies by kvm version and host processor, but does not change
+otherwise.
+
+
+4.4 KVM_CHECK_EXTENSION
+
+Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl
+Architectures: all
+Type: system ioctl, vm ioctl
+Parameters: extension identifier (KVM_CAP_*)
+Returns: 0 if unsupported; 1 (or some other positive integer) if supported
+
+The API allows the application to query about extensions to the core
+kvm API.  Userspace passes an extension identifier (an integer) and
+receives an integer that describes the extension availability.
+Generally 0 means no and 1 means yes, but some extensions may report
+additional information in the integer return value.
+
+Based on their initialization different VMs may have different capabilities.
+It is thus encouraged to use the vm ioctl to query for capabilities (available
+with KVM_CAP_CHECK_EXTENSION_VM on the vm fd)
+
+4.5 KVM_GET_VCPU_MMAP_SIZE
+
+Capability: basic
+Architectures: all
+Type: system ioctl
+Parameters: none
+Returns: size of vcpu mmap area, in bytes
+
+The KVM_RUN ioctl (cf.) communicates with userspace via a shared
+memory region.  This ioctl returns the size of that region.  See the
+KVM_RUN documentation for details.
+
+
+4.6 KVM_SET_MEMORY_REGION
+
+Capability: basic
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_memory_region (in)
+Returns: 0 on success, -1 on error
+
+This ioctl is obsolete and has been removed.
+
+
+4.7 KVM_CREATE_VCPU
+
+Capability: basic
+Architectures: all
+Type: vm ioctl
+Parameters: vcpu id (apic id on x86)
+Returns: vcpu fd on success, -1 on error
+
+This API adds a vcpu to a virtual machine. No more than max_vcpus may be added.
+The vcpu id is an integer in the range [0, max_vcpu_id).
+
+The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of
+the KVM_CHECK_EXTENSION ioctl() at run-time.
+The maximum possible value for max_vcpus can be retrieved using the
+KVM_CAP_MAX_VCPUS of the KVM_CHECK_EXTENSION ioctl() at run-time.
+
+If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
+cpus max.
+If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is
+same as the value returned from KVM_CAP_NR_VCPUS.
+
+The maximum possible value for max_vcpu_id can be retrieved using the
+KVM_CAP_MAX_VCPU_ID of the KVM_CHECK_EXTENSION ioctl() at run-time.
+
+If the KVM_CAP_MAX_VCPU_ID does not exist, you should assume that max_vcpu_id
+is the same as the value returned from KVM_CAP_MAX_VCPUS.
+
+On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
+threads in one or more virtual CPU cores.  (This is because the
+hardware requires all the hardware threads in a CPU core to be in the
+same partition.)  The KVM_CAP_PPC_SMT capability indicates the number
+of vcpus per virtual core (vcore).  The vcore id is obtained by
+dividing the vcpu id by the number of vcpus per vcore.  The vcpus in a
+given vcore will always be in the same physical core as each other
+(though that might be a different physical core from time to time).
+Userspace can control the threading (SMT) mode of the guest by its
+allocation of vcpu ids.  For example, if userspace wants
+single-threaded guest vcpus, it should make all vcpu ids be a multiple
+of the number of vcpus per vcore.
+
+For virtual cpus that have been created with S390 user controlled virtual
+machines, the resulting vcpu fd can be memory mapped at page offset
+KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
+cpu's hardware control block.
+
+
+4.8 KVM_GET_DIRTY_LOG (vm ioctl)
+
+Capability: basic
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_dirty_log (in/out)
+Returns: 0 on success, -1 on error
+
+/* for KVM_GET_DIRTY_LOG */
+struct kvm_dirty_log {
+       __u32 slot;
+       __u32 padding;
+       union {
+               void __user *dirty_bitmap; /* one bit per page */
+               __u64 padding;
+       };
+};
+
+Given a memory slot, return a bitmap containing any pages dirtied
+since the last call to this ioctl.  Bit 0 is the first page in the
+memory slot.  Ensure the entire structure is cleared to avoid padding
+issues.
+
+If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 specifies
+the address space for which you want to return the dirty bitmap.
+They must be less than the value that KVM_CHECK_EXTENSION returns for
+the KVM_CAP_MULTI_ADDRESS_SPACE capability.
+
+The bits in the dirty bitmap are cleared before the ioctl returns, unless
+KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is enabled.  For more information,
+see the description of the capability.
+
+4.9 KVM_SET_MEMORY_ALIAS
+
+Capability: basic
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_memory_alias (in)
+Returns: 0 (success), -1 (error)
+
+This ioctl is obsolete and has been removed.
+
+
+4.10 KVM_RUN
+
+Capability: basic
+Architectures: all
+Type: vcpu ioctl
+Parameters: none
+Returns: 0 on success, -1 on error
+Errors:
+  EINTR:     an unmasked signal is pending
+
+This ioctl is used to run a guest virtual cpu.  While there are no
+explicit parameters, there is an implicit parameter block that can be
+obtained by mmap()ing the vcpu fd at offset 0, with the size given by
+KVM_GET_VCPU_MMAP_SIZE.  The parameter block is formatted as a 'struct
+kvm_run' (see below).
+
+
+4.11 KVM_GET_REGS
+
+Capability: basic
+Architectures: all except ARM, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_regs (out)
+Returns: 0 on success, -1 on error
+
+Reads the general purpose registers from the vcpu.
+
+/* x86 */
+struct kvm_regs {
+       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+       __u64 rax, rbx, rcx, rdx;
+       __u64 rsi, rdi, rsp, rbp;
+       __u64 r8,  r9,  r10, r11;
+       __u64 r12, r13, r14, r15;
+       __u64 rip, rflags;
+};
+
+/* mips */
+struct kvm_regs {
+       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+       __u64 gpr[32];
+       __u64 hi;
+       __u64 lo;
+       __u64 pc;
+};
+
+
+4.12 KVM_SET_REGS
+
+Capability: basic
+Architectures: all except ARM, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_regs (in)
+Returns: 0 on success, -1 on error
+
+Writes the general purpose registers into the vcpu.
+
+See KVM_GET_REGS for the data structure.
+
+
+4.13 KVM_GET_SREGS
+
+Capability: basic
+Architectures: x86, ppc
+Type: vcpu ioctl
+Parameters: struct kvm_sregs (out)
+Returns: 0 on success, -1 on error
+
+Reads special registers from the vcpu.
+
+/* x86 */
+struct kvm_sregs {
+       struct kvm_segment cs, ds, es, fs, gs, ss;
+       struct kvm_segment tr, ldt;
+       struct kvm_dtable gdt, idt;
+       __u64 cr0, cr2, cr3, cr4, cr8;
+       __u64 efer;
+       __u64 apic_base;
+       __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
+};
+
+/* ppc -- see arch/powerpc/include/uapi/asm/kvm.h */
+
+interrupt_bitmap is a bitmap of pending external interrupts.  At most
+one bit may be set.  This interrupt has been acknowledged by the APIC
+but not yet injected into the cpu core.
+
+
+4.14 KVM_SET_SREGS
+
+Capability: basic
+Architectures: x86, ppc
+Type: vcpu ioctl
+Parameters: struct kvm_sregs (in)
+Returns: 0 on success, -1 on error
+
+Writes special registers into the vcpu.  See KVM_GET_SREGS for the
+data structures.
+
+
+4.15 KVM_TRANSLATE
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_translation (in/out)
+Returns: 0 on success, -1 on error
+
+Translates a virtual address according to the vcpu's current address
+translation mode.
+
+struct kvm_translation {
+       /* in */
+       __u64 linear_address;
+
+       /* out */
+       __u64 physical_address;
+       __u8  valid;
+       __u8  writeable;
+       __u8  usermode;
+       __u8  pad[5];
+};
+
+
+4.16 KVM_INTERRUPT
+
+Capability: basic
+Architectures: x86, ppc, mips
+Type: vcpu ioctl
+Parameters: struct kvm_interrupt (in)
+Returns: 0 on success, negative on failure.
+
+Queues a hardware interrupt vector to be injected.
+
+/* for KVM_INTERRUPT */
+struct kvm_interrupt {
+       /* in */
+       __u32 irq;
+};
+
+X86:
+
+Returns: 0 on success,
+        -EEXIST if an interrupt is already enqueued
+        -EINVAL the the irq number is invalid
+        -ENXIO if the PIC is in the kernel
+        -EFAULT if the pointer is invalid
+
+Note 'irq' is an interrupt vector, not an interrupt pin or line. This
+ioctl is useful if the in-kernel PIC is not used.
+
+PPC:
+
+Queues an external interrupt to be injected. This ioctl is overleaded
+with 3 different irq values:
+
+a) KVM_INTERRUPT_SET
+
+  This injects an edge type external interrupt into the guest once it's ready
+  to receive interrupts. When injected, the interrupt is done.
+
+b) KVM_INTERRUPT_UNSET
+
+  This unsets any pending interrupt.
+
+  Only available with KVM_CAP_PPC_UNSET_IRQ.
+
+c) KVM_INTERRUPT_SET_LEVEL
+
+  This injects a level type external interrupt into the guest context. The
+  interrupt stays pending until a specific ioctl with KVM_INTERRUPT_UNSET
+  is triggered.
+
+  Only available with KVM_CAP_PPC_IRQ_LEVEL.
+
+Note that any value for 'irq' other than the ones stated above is invalid
+and incurs unexpected behavior.
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
+MIPS:
+
+Queues an external interrupt to be injected into the virtual CPU. A negative
+interrupt number dequeues the interrupt.
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
+
+4.17 KVM_DEBUG_GUEST
+
+Capability: basic
+Architectures: none
+Type: vcpu ioctl
+Parameters: none)
+Returns: -1 on error
+
+Support for this has been removed.  Use KVM_SET_GUEST_DEBUG instead.
+
+
+4.18 KVM_GET_MSRS
+
+Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system)
+Architectures: x86
+Type: system ioctl, vcpu ioctl
+Parameters: struct kvm_msrs (in/out)
+Returns: number of msrs successfully returned;
+        -1 on error
+
+When used as a system ioctl:
+Reads the values of MSR-based features that are available for the VM.  This
+is similar to KVM_GET_SUPPORTED_CPUID, but it returns MSR indices and values.
+The list of msr-based features can be obtained using KVM_GET_MSR_FEATURE_INDEX_LIST
+in a system ioctl.
+
+When used as a vcpu ioctl:
+Reads model-specific registers from the vcpu.  Supported msr indices can
+be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl.
+
+struct kvm_msrs {
+       __u32 nmsrs; /* number of msrs in entries */
+       __u32 pad;
+
+       struct kvm_msr_entry entries[0];
+};
+
+struct kvm_msr_entry {
+       __u32 index;
+       __u32 reserved;
+       __u64 data;
+};
+
+Application code should set the 'nmsrs' member (which indicates the
+size of the entries array) and the 'index' member of each array entry.
+kvm will fill in the 'data' member.
+
+
+4.19 KVM_SET_MSRS
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_msrs (in)
+Returns: 0 on success, -1 on error
+
+Writes model-specific registers to the vcpu.  See KVM_GET_MSRS for the
+data structures.
+
+Application code should set the 'nmsrs' member (which indicates the
+size of the entries array), and the 'index' and 'data' members of each
+array entry.
+
+
+4.20 KVM_SET_CPUID
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_cpuid (in)
+Returns: 0 on success, -1 on error
+
+Defines the vcpu responses to the cpuid instruction.  Applications
+should use the KVM_SET_CPUID2 ioctl if available.
+
+
+struct kvm_cpuid_entry {
+       __u32 function;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding;
+};
+
+/* for KVM_SET_CPUID */
+struct kvm_cpuid {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry entries[0];
+};
+
+
+4.21 KVM_SET_SIGNAL_MASK
+
+Capability: basic
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_signal_mask (in)
+Returns: 0 on success, -1 on error
+
+Defines which signals are blocked during execution of KVM_RUN.  This
+signal mask temporarily overrides the threads signal mask.  Any
+unblocked signal received (except SIGKILL and SIGSTOP, which retain
+their traditional behaviour) will cause KVM_RUN to return with -EINTR.
+
+Note the signal will only be delivered if not blocked by the original
+signal mask.
+
+/* for KVM_SET_SIGNAL_MASK */
+struct kvm_signal_mask {
+       __u32 len;
+       __u8  sigset[0];
+};
+
+
+4.22 KVM_GET_FPU
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_fpu (out)
+Returns: 0 on success, -1 on error
+
+Reads the floating point state from the vcpu.
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+       __u8  fpr[8][16];
+       __u16 fcw;
+       __u16 fsw;
+       __u8  ftwx;  /* in fxsave format */
+       __u8  pad1;
+       __u16 last_opcode;
+       __u64 last_ip;
+       __u64 last_dp;
+       __u8  xmm[16][16];
+       __u32 mxcsr;
+       __u32 pad2;
+};
+
+
+4.23 KVM_SET_FPU
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_fpu (in)
+Returns: 0 on success, -1 on error
+
+Writes the floating point state to the vcpu.
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+       __u8  fpr[8][16];
+       __u16 fcw;
+       __u16 fsw;
+       __u8  ftwx;  /* in fxsave format */
+       __u8  pad1;
+       __u16 last_opcode;
+       __u64 last_ip;
+       __u64 last_dp;
+       __u8  xmm[16][16];
+       __u32 mxcsr;
+       __u32 pad2;
+};
+
+
+4.24 KVM_CREATE_IRQCHIP
+
+Capability: KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390)
+Architectures: x86, ARM, arm64, s390
+Type: vm ioctl
+Parameters: none
+Returns: 0 on success, -1 on error
+
+Creates an interrupt controller model in the kernel.
+On x86, creates a virtual ioapic, a virtual PIC (two PICs, nested), and sets up
+future vcpus to have a local APIC.  IRQ routing for GSIs 0-15 is set to both
+PIC and IOAPIC; GSI 16-23 only go to the IOAPIC.
+On ARM/arm64, a GICv2 is created. Any other GIC versions require the usage of
+KVM_CREATE_DEVICE, which also supports creating a GICv2.  Using
+KVM_CREATE_DEVICE is preferred over KVM_CREATE_IRQCHIP for GICv2.
+On s390, a dummy irq routing table is created.
+
+Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled
+before KVM_CREATE_IRQCHIP can be used.
+
+
+4.25 KVM_IRQ_LINE
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86, arm, arm64
+Type: vm ioctl
+Parameters: struct kvm_irq_level
+Returns: 0 on success, -1 on error
+
+Sets the level of a GSI input to the interrupt controller model in the kernel.
+On some architectures it is required that an interrupt controller model has
+been previously created with KVM_CREATE_IRQCHIP.  Note that edge-triggered
+interrupts require the level to be set to 1 and then back to 0.
+
+On real hardware, interrupt pins can be active-low or active-high.  This
+does not matter for the level field of struct kvm_irq_level: 1 always
+means active (asserted), 0 means inactive (deasserted).
+
+x86 allows the operating system to program the interrupt polarity
+(active-low/active-high) for level-triggered interrupts, and KVM used
+to consider the polarity.  However, due to bitrot in the handling of
+active-low interrupts, the above convention is now valid on x86 too.
+This is signaled by KVM_CAP_X86_IOAPIC_POLARITY_IGNORED.  Userspace
+should not present interrupts to the guest as active-low unless this
+capability is present (or unless it is not using the in-kernel irqchip,
+of course).
+
+
+ARM/arm64 can signal an interrupt either at the CPU level, or at the
+in-kernel irqchip (GIC), and for in-kernel irqchip can tell the GIC to
+use PPIs designated for specific cpus.  The irq field is interpreted
+like this:
+
+  bits:  | 31 ... 24 | 23  ... 16 | 15    ...    0 |
+  field: | irq_type  | vcpu_index |     irq_id     |
+
+The irq_type field has the following values:
+- irq_type[0]: out-of-kernel GIC: irq_id 0 is IRQ, irq_id 1 is FIQ
+- irq_type[1]: in-kernel GIC: SPI, irq_id between 32 and 1019 (incl.)
+               (the vcpu_index field is ignored)
+- irq_type[2]: in-kernel GIC: PPI, irq_id between 16 and 31 (incl.)
+
+(The irq_id field thus corresponds nicely to the IRQ ID in the ARM GIC specs)
+
+In both cases, level is used to assert/deassert the line.
+
+struct kvm_irq_level {
+       union {
+               __u32 irq;     /* GSI */
+               __s32 status;  /* not used for KVM_IRQ_LEVEL */
+       };
+       __u32 level;           /* 0 or 1 */
+};
+
+
+4.26 KVM_GET_IRQCHIP
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_irqchip (in/out)
+Returns: 0 on success, -1 on error
+
+Reads the state of a kernel interrupt controller created with
+KVM_CREATE_IRQCHIP into a buffer provided by the caller.
+
+struct kvm_irqchip {
+       __u32 chip_id;  /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
+       __u32 pad;
+        union {
+               char dummy[512];  /* reserving space */
+               struct kvm_pic_state pic;
+               struct kvm_ioapic_state ioapic;
+       } chip;
+};
+
+
+4.27 KVM_SET_IRQCHIP
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_irqchip (in)
+Returns: 0 on success, -1 on error
+
+Sets the state of a kernel interrupt controller created with
+KVM_CREATE_IRQCHIP from a buffer provided by the caller.
+
+struct kvm_irqchip {
+       __u32 chip_id;  /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
+       __u32 pad;
+        union {
+               char dummy[512];  /* reserving space */
+               struct kvm_pic_state pic;
+               struct kvm_ioapic_state ioapic;
+       } chip;
+};
+
+
+4.28 KVM_XEN_HVM_CONFIG
+
+Capability: KVM_CAP_XEN_HVM
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_xen_hvm_config (in)
+Returns: 0 on success, -1 on error
+
+Sets the MSR that the Xen HVM guest uses to initialize its hypercall
+page, and provides the starting address and size of the hypercall
+blobs in userspace.  When the guest writes the MSR, kvm copies one
+page of a blob (32- or 64-bit, depending on the vcpu mode) to guest
+memory.
+
+struct kvm_xen_hvm_config {
+       __u32 flags;
+       __u32 msr;
+       __u64 blob_addr_32;
+       __u64 blob_addr_64;
+       __u8 blob_size_32;
+       __u8 blob_size_64;
+       __u8 pad2[30];
+};
+
+
+4.29 KVM_GET_CLOCK
+
+Capability: KVM_CAP_ADJUST_CLOCK
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_clock_data (out)
+Returns: 0 on success, -1 on error
+
+Gets the current timestamp of kvmclock as seen by the current guest. In
+conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios
+such as migration.
+
+When KVM_CAP_ADJUST_CLOCK is passed to KVM_CHECK_EXTENSION, it returns the
+set of bits that KVM can return in struct kvm_clock_data's flag member.
+
+The only flag defined now is KVM_CLOCK_TSC_STABLE.  If set, the returned
+value is the exact kvmclock value seen by all VCPUs at the instant
+when KVM_GET_CLOCK was called.  If clear, the returned value is simply
+CLOCK_MONOTONIC plus a constant offset; the offset can be modified
+with KVM_SET_CLOCK.  KVM will try to make all VCPUs follow this clock,
+but the exact value read by each VCPU could differ, because the host
+TSC is not stable.
+
+struct kvm_clock_data {
+       __u64 clock;  /* kvmclock current value */
+       __u32 flags;
+       __u32 pad[9];
+};
+
+
+4.30 KVM_SET_CLOCK
+
+Capability: KVM_CAP_ADJUST_CLOCK
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_clock_data (in)
+Returns: 0 on success, -1 on error
+
+Sets the current timestamp of kvmclock to the value specified in its parameter.
+In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios
+such as migration.
+
+struct kvm_clock_data {
+       __u64 clock;  /* kvmclock current value */
+       __u32 flags;
+       __u32 pad[9];
+};
+
+
+4.31 KVM_GET_VCPU_EVENTS
+
+Capability: KVM_CAP_VCPU_EVENTS
+Extended by: KVM_CAP_INTR_SHADOW
+Architectures: x86, arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_vcpu_event (out)
+Returns: 0 on success, -1 on error
+
+X86:
+
+Gets currently pending exceptions, interrupts, and NMIs as well as related
+states of the vcpu.
+
+struct kvm_vcpu_events {
+       struct {
+               __u8 injected;
+               __u8 nr;
+               __u8 has_error_code;
+               __u8 pending;
+               __u32 error_code;
+       } exception;
+       struct {
+               __u8 injected;
+               __u8 nr;
+               __u8 soft;
+               __u8 shadow;
+       } interrupt;
+       struct {
+               __u8 injected;
+               __u8 pending;
+               __u8 masked;
+               __u8 pad;
+       } nmi;
+       __u32 sipi_vector;
+       __u32 flags;
+       struct {
+               __u8 smm;
+               __u8 pending;
+               __u8 smm_inside_nmi;
+               __u8 latched_init;
+       } smi;
+       __u8 reserved[27];
+       __u8 exception_has_payload;
+       __u64 exception_payload;
+};
+
+The following bits are defined in the flags field:
+
+- KVM_VCPUEVENT_VALID_SHADOW may be set to signal that
+  interrupt.shadow contains a valid state.
+
+- KVM_VCPUEVENT_VALID_SMM may be set to signal that smi contains a
+  valid state.
+
+- KVM_VCPUEVENT_VALID_PAYLOAD may be set to signal that the
+  exception_has_payload, exception_payload, and exception.pending
+  fields contain a valid state. This bit will be set whenever
+  KVM_CAP_EXCEPTION_PAYLOAD is enabled.
+
+ARM/ARM64:
+
+If the guest accesses a device that is being emulated by the host kernel in
+such a way that a real device would generate a physical SError, KVM may make
+a virtual SError pending for that VCPU. This system error interrupt remains
+pending until the guest takes the exception by unmasking PSTATE.A.
+
+Running the VCPU may cause it to take a pending SError, or make an access that
+causes an SError to become pending. The event's description is only valid while
+the VPCU is not running.
+
+This API provides a way to read and write the pending 'event' state that is not
+visible to the guest. To save, restore or migrate a VCPU the struct representing
+the state can be read then written using this GET/SET API, along with the other
+guest-visible registers. It is not possible to 'cancel' an SError that has been
+made pending.
+
+A device being emulated in user-space may also wish to generate an SError. To do
+this the events structure can be populated by user-space. The current state
+should be read first, to ensure no existing SError is pending. If an existing
+SError is pending, the architecture's 'Multiple SError interrupts' rules should
+be followed. (2.5.3 of DDI0587.a "ARM Reliability, Availability, and
+Serviceability (RAS) Specification").
+
+SError exceptions always have an ESR value. Some CPUs have the ability to
+specify what the virtual SError's ESR value should be. These systems will
+advertise KVM_CAP_ARM_INJECT_SERROR_ESR. In this case exception.has_esr will
+always have a non-zero value when read, and the agent making an SError pending
+should specify the ISS field in the lower 24 bits of exception.serror_esr. If
+the system supports KVM_CAP_ARM_INJECT_SERROR_ESR, but user-space sets the events
+with exception.has_esr as zero, KVM will choose an ESR.
+
+Specifying exception.has_esr on a system that does not support it will return
+-EINVAL. Setting anything other than the lower 24bits of exception.serror_esr
+will return -EINVAL.
+
+struct kvm_vcpu_events {
+       struct {
+               __u8 serror_pending;
+               __u8 serror_has_esr;
+               /* Align it to 8 bytes */
+               __u8 pad[6];
+               __u64 serror_esr;
+       } exception;
+       __u32 reserved[12];
+};
+
+4.32 KVM_SET_VCPU_EVENTS
+
+Capability: KVM_CAP_VCPU_EVENTS
+Extended by: KVM_CAP_INTR_SHADOW
+Architectures: x86, arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_vcpu_event (in)
+Returns: 0 on success, -1 on error
+
+X86:
+
+Set pending exceptions, interrupts, and NMIs as well as related states of the
+vcpu.
+
+See KVM_GET_VCPU_EVENTS for the data structure.
+
+Fields that may be modified asynchronously by running VCPUs can be excluded
+from the update. These fields are nmi.pending, sipi_vector, smi.smm,
+smi.pending. Keep the corresponding bits in the flags field cleared to
+suppress overwriting the current in-kernel state. The bits are:
+
+KVM_VCPUEVENT_VALID_NMI_PENDING - transfer nmi.pending to the kernel
+KVM_VCPUEVENT_VALID_SIPI_VECTOR - transfer sipi_vector
+KVM_VCPUEVENT_VALID_SMM         - transfer the smi sub-struct.
+
+If KVM_CAP_INTR_SHADOW is available, KVM_VCPUEVENT_VALID_SHADOW can be set in
+the flags field to signal that interrupt.shadow contains a valid state and
+shall be written into the VCPU.
+
+KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available.
+
+If KVM_CAP_EXCEPTION_PAYLOAD is enabled, KVM_VCPUEVENT_VALID_PAYLOAD
+can be set in the flags field to signal that the
+exception_has_payload, exception_payload, and exception.pending fields
+contain a valid state and shall be written into the VCPU.
+
+ARM/ARM64:
+
+Set the pending SError exception state for this VCPU. It is not possible to
+'cancel' an Serror that has been made pending.
+
+See KVM_GET_VCPU_EVENTS for the data structure.
+
+
+4.33 KVM_GET_DEBUGREGS
+
+Capability: KVM_CAP_DEBUGREGS
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_debugregs (out)
+Returns: 0 on success, -1 on error
+
+Reads debug registers from the vcpu.
+
+struct kvm_debugregs {
+       __u64 db[4];
+       __u64 dr6;
+       __u64 dr7;
+       __u64 flags;
+       __u64 reserved[9];
+};
+
+
+4.34 KVM_SET_DEBUGREGS
+
+Capability: KVM_CAP_DEBUGREGS
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_debugregs (in)
+Returns: 0 on success, -1 on error
+
+Writes debug registers into the vcpu.
+
+See KVM_GET_DEBUGREGS for the data structure. The flags field is unused
+yet and must be cleared on entry.
+
+
+4.35 KVM_SET_USER_MEMORY_REGION
+
+Capability: KVM_CAP_USER_MEMORY
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_userspace_memory_region (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_userspace_memory_region {
+       __u32 slot;
+       __u32 flags;
+       __u64 guest_phys_addr;
+       __u64 memory_size; /* bytes */
+       __u64 userspace_addr; /* start of the userspace allocated memory */
+};
+
+/* for kvm_memory_region::flags */
+#define KVM_MEM_LOG_DIRTY_PAGES        (1UL << 0)
+#define KVM_MEM_READONLY       (1UL << 1)
+
+This ioctl allows the user to create, modify or delete a guest physical
+memory slot.  Bits 0-15 of "slot" specify the slot id and this value
+should be less than the maximum number of user memory slots supported per
+VM.  The maximum allowed slots can be queried using KVM_CAP_NR_MEMSLOTS.
+Slots may not overlap in guest physical address space.
+
+If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 of "slot"
+specifies the address space which is being modified.  They must be
+less than the value that KVM_CHECK_EXTENSION returns for the
+KVM_CAP_MULTI_ADDRESS_SPACE capability.  Slots in separate address spaces
+are unrelated; the restriction on overlapping slots only applies within
+each address space.
+
+Deleting a slot is done by passing zero for memory_size.  When changing
+an existing slot, it may be moved in the guest physical memory space,
+or its flags may be modified, but it may not be resized.
+
+Memory for the region is taken starting at the address denoted by the
+field userspace_addr, which must point at user addressable memory for
+the entire memory slot size.  Any object may back this memory, including
+anonymous memory, ordinary files, and hugetlbfs.
+
+It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
+be identical.  This allows large pages in the guest to be backed by large
+pages in the host.
+
+The flags field supports two flags: KVM_MEM_LOG_DIRTY_PAGES and
+KVM_MEM_READONLY.  The former can be set to instruct KVM to keep track of
+writes to memory within the slot.  See KVM_GET_DIRTY_LOG ioctl to know how to
+use it.  The latter can be set, if KVM_CAP_READONLY_MEM capability allows it,
+to make a new slot read-only.  In this case, writes to this memory will be
+posted to userspace as KVM_EXIT_MMIO exits.
+
+When the KVM_CAP_SYNC_MMU capability is available, changes in the backing of
+the memory region are automatically reflected into the guest.  For example, an
+mmap() that affects the region will be made visible immediately.  Another
+example is madvise(MADV_DROP).
+
+It is recommended to use this API instead of the KVM_SET_MEMORY_REGION ioctl.
+The KVM_SET_MEMORY_REGION does not allow fine grained control over memory
+allocation and is deprecated.
+
+
+4.36 KVM_SET_TSS_ADDR
+
+Capability: KVM_CAP_SET_TSS_ADDR
+Architectures: x86
+Type: vm ioctl
+Parameters: unsigned long tss_address (in)
+Returns: 0 on success, -1 on error
+
+This ioctl defines the physical address of a three-page region in the guest
+physical address space.  The region must be within the first 4GB of the
+guest physical address space and must not conflict with any memory slot
+or any mmio address.  The guest may malfunction if it accesses this memory
+region.
+
+This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
+because of a quirk in the virtualization implementation (see the internals
+documentation when it pops into existence).
+
+
+4.37 KVM_ENABLE_CAP
+
+Capability: KVM_CAP_ENABLE_CAP
+Architectures: mips, ppc, s390
+Type: vcpu ioctl
+Parameters: struct kvm_enable_cap (in)
+Returns: 0 on success; -1 on error
+
+Capability: KVM_CAP_ENABLE_CAP_VM
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_enable_cap (in)
+Returns: 0 on success; -1 on error
+
++Not all extensions are enabled by default. Using this ioctl the application
+can enable an extension, making it available to the guest.
+
+On systems that do not support this ioctl, it always fails. On systems that
+do support it, it only works for extensions that are supported for enablement.
+
+To check if a capability can be enabled, the KVM_CHECK_EXTENSION ioctl should
+be used.
+
+struct kvm_enable_cap {
+       /* in */
+       __u32 cap;
+
+The capability that is supposed to get enabled.
+
+       __u32 flags;
+
+A bitfield indicating future enhancements. Has to be 0 for now.
+
+       __u64 args[4];
+
+Arguments for enabling a feature. If a feature needs initial values to
+function properly, this is the place to put them.
+
+       __u8  pad[64];
+};
+
+The vcpu ioctl should be used for vcpu-specific capabilities, the vm ioctl
+for vm-wide capabilities.
+
+4.38 KVM_GET_MP_STATE
+
+Capability: KVM_CAP_MP_STATE
+Architectures: x86, s390, arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_mp_state (out)
+Returns: 0 on success; -1 on error
+
+struct kvm_mp_state {
+       __u32 mp_state;
+};
+
+Returns the vcpu's current "multiprocessing state" (though also valid on
+uniprocessor guests).
+
+Possible values are:
+
+ - KVM_MP_STATE_RUNNABLE:        the vcpu is currently running [x86,arm/arm64]
+ - KVM_MP_STATE_UNINITIALIZED:   the vcpu is an application processor (AP)
+                                 which has not yet received an INIT signal [x86]
+ - KVM_MP_STATE_INIT_RECEIVED:   the vcpu has received an INIT signal, and is
+                                 now ready for a SIPI [x86]
+ - KVM_MP_STATE_HALTED:          the vcpu has executed a HLT instruction and
+                                 is waiting for an interrupt [x86]
+ - KVM_MP_STATE_SIPI_RECEIVED:   the vcpu has just received a SIPI (vector
+                                 accessible via KVM_GET_VCPU_EVENTS) [x86]
+ - KVM_MP_STATE_STOPPED:         the vcpu is stopped [s390,arm/arm64]
+ - KVM_MP_STATE_CHECK_STOP:      the vcpu is in a special error state [s390]
+ - KVM_MP_STATE_OPERATING:       the vcpu is operating (running or halted)
+                                 [s390]
+ - KVM_MP_STATE_LOAD:            the vcpu is in a special load/startup state
+                                 [s390]
+
+On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
+these architectures.
+
+For arm/arm64:
+
+The only states that are valid are KVM_MP_STATE_STOPPED and
+KVM_MP_STATE_RUNNABLE which reflect if the vcpu is paused or not.
+
+4.39 KVM_SET_MP_STATE
+
+Capability: KVM_CAP_MP_STATE
+Architectures: x86, s390, arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_mp_state (in)
+Returns: 0 on success; -1 on error
+
+Sets the vcpu's current "multiprocessing state"; see KVM_GET_MP_STATE for
+arguments.
+
+On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
+these architectures.
+
+For arm/arm64:
+
+The only states that are valid are KVM_MP_STATE_STOPPED and
+KVM_MP_STATE_RUNNABLE which reflect if the vcpu should be paused or not.
+
+4.40 KVM_SET_IDENTITY_MAP_ADDR
+
+Capability: KVM_CAP_SET_IDENTITY_MAP_ADDR
+Architectures: x86
+Type: vm ioctl
+Parameters: unsigned long identity (in)
+Returns: 0 on success, -1 on error
+
+This ioctl defines the physical address of a one-page region in the guest
+physical address space.  The region must be within the first 4GB of the
+guest physical address space and must not conflict with any memory slot
+or any mmio address.  The guest may malfunction if it accesses this memory
+region.
+
+Setting the address to 0 will result in resetting the address to its default
+(0xfffbc000).
+
+This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
+because of a quirk in the virtualization implementation (see the internals
+documentation when it pops into existence).
+
+Fails if any VCPU has already been created.
+
+4.41 KVM_SET_BOOT_CPU_ID
+
+Capability: KVM_CAP_SET_BOOT_CPU_ID
+Architectures: x86
+Type: vm ioctl
+Parameters: unsigned long vcpu_id
+Returns: 0 on success, -1 on error
+
+Define which vcpu is the Bootstrap Processor (BSP).  Values are the same
+as the vcpu id in KVM_CREATE_VCPU.  If this ioctl is not called, the default
+is vcpu 0.
+
+
+4.42 KVM_GET_XSAVE
+
+Capability: KVM_CAP_XSAVE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_xsave (out)
+Returns: 0 on success, -1 on error
+
+struct kvm_xsave {
+       __u32 region[1024];
+};
+
+This ioctl would copy current vcpu's xsave struct to the userspace.
+
+
+4.43 KVM_SET_XSAVE
+
+Capability: KVM_CAP_XSAVE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_xsave (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_xsave {
+       __u32 region[1024];
+};
+
+This ioctl would copy userspace's xsave struct to the kernel.
+
+
+4.44 KVM_GET_XCRS
+
+Capability: KVM_CAP_XCRS
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_xcrs (out)
+Returns: 0 on success, -1 on error
+
+struct kvm_xcr {
+       __u32 xcr;
+       __u32 reserved;
+       __u64 value;
+};
+
+struct kvm_xcrs {
+       __u32 nr_xcrs;
+       __u32 flags;
+       struct kvm_xcr xcrs[KVM_MAX_XCRS];
+       __u64 padding[16];
+};
+
+This ioctl would copy current vcpu's xcrs to the userspace.
+
+
+4.45 KVM_SET_XCRS
+
+Capability: KVM_CAP_XCRS
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_xcrs (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_xcr {
+       __u32 xcr;
+       __u32 reserved;
+       __u64 value;
+};
+
+struct kvm_xcrs {
+       __u32 nr_xcrs;
+       __u32 flags;
+       struct kvm_xcr xcrs[KVM_MAX_XCRS];
+       __u64 padding[16];
+};
+
+This ioctl would set vcpu's xcr to the value userspace specified.
+
+
+4.46 KVM_GET_SUPPORTED_CPUID
+
+Capability: KVM_CAP_EXT_CPUID
+Architectures: x86
+Type: system ioctl
+Parameters: struct kvm_cpuid2 (in/out)
+Returns: 0 on success, -1 on error
+
+struct kvm_cpuid2 {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry2 entries[0];
+};
+
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX                BIT(0)
+#define KVM_CPUID_FLAG_STATEFUL_FUNC           BIT(1)
+#define KVM_CPUID_FLAG_STATE_READ_NEXT         BIT(2)
+
+struct kvm_cpuid_entry2 {
+       __u32 function;
+       __u32 index;
+       __u32 flags;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding[3];
+};
+
+This ioctl returns x86 cpuid features which are supported by both the
+hardware and kvm in its default configuration.  Userspace can use the
+information returned by this ioctl to construct cpuid information (for
+KVM_SET_CPUID2) that is consistent with hardware, kernel, and
+userspace capabilities, and with user requirements (for example, the
+user may wish to constrain cpuid to emulate older hardware, or for
+feature consistency across a cluster).
+
+Note that certain capabilities, such as KVM_CAP_X86_DISABLE_EXITS, may
+expose cpuid features (e.g. MONITOR) which are not supported by kvm in
+its default configuration. If userspace enables such capabilities, it
+is responsible for modifying the results of this ioctl appropriately.
+
+Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
+with the 'nent' field indicating the number of entries in the variable-size
+array 'entries'.  If the number of entries is too low to describe the cpu
+capabilities, an error (E2BIG) is returned.  If the number is too high,
+the 'nent' field is adjusted and an error (ENOMEM) is returned.  If the
+number is just right, the 'nent' field is adjusted to the number of valid
+entries in the 'entries' array, which is then filled.
+
+The entries returned are the host cpuid as returned by the cpuid instruction,
+with unknown or unsupported features masked out.  Some features (for example,
+x2apic), may not be present in the host cpu, but are exposed by kvm if it can
+emulate them efficiently. The fields in each entry are defined as follows:
+
+  function: the eax value used to obtain the entry
+  index: the ecx value used to obtain the entry (for entries that are
+         affected by ecx)
+  flags: an OR of zero or more of the following:
+        KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
+           if the index field is valid
+        KVM_CPUID_FLAG_STATEFUL_FUNC:
+           if cpuid for this function returns different values for successive
+           invocations; there will be several entries with the same function,
+           all with this flag set
+        KVM_CPUID_FLAG_STATE_READ_NEXT:
+           for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
+           the first entry to be read by a cpu
+   eax, ebx, ecx, edx: the values returned by the cpuid instruction for
+         this function/index combination
+
+The TSC deadline timer feature (CPUID leaf 1, ecx[24]) is always returned
+as false, since the feature depends on KVM_CREATE_IRQCHIP for local APIC
+support.  Instead it is reported via
+
+  ioctl(KVM_CHECK_EXTENSION, KVM_CAP_TSC_DEADLINE_TIMER)
+
+if that returns true and you use KVM_CREATE_IRQCHIP, or if you emulate the
+feature in userspace, then you can enable the feature for KVM_SET_CPUID2.
+
+
+4.47 KVM_PPC_GET_PVINFO
+
+Capability: KVM_CAP_PPC_GET_PVINFO
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_ppc_pvinfo (out)
+Returns: 0 on success, !0 on error
+
+struct kvm_ppc_pvinfo {
+       __u32 flags;
+       __u32 hcall[4];
+       __u8  pad[108];
+};
+
+This ioctl fetches PV specific information that need to be passed to the guest
+using the device tree or other means from vm context.
+
+The hcall array defines 4 instructions that make up a hypercall.
+
+If any additional field gets added to this structure later on, a bit for that
+additional piece of information will be set in the flags bitmap.
+
+The flags bitmap is defined as:
+
+   /* the host supports the ePAPR idle hcall
+   #define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
+4.52 KVM_SET_GSI_ROUTING
+
+Capability: KVM_CAP_IRQ_ROUTING
+Architectures: x86 s390 arm arm64
+Type: vm ioctl
+Parameters: struct kvm_irq_routing (in)
+Returns: 0 on success, -1 on error
+
+Sets the GSI routing table entries, overwriting any previously set entries.
+
+On arm/arm64, GSI routing has the following limitation:
+- GSI routing does not apply to KVM_IRQ_LINE but only to KVM_IRQFD.
+
+struct kvm_irq_routing {
+       __u32 nr;
+       __u32 flags;
+       struct kvm_irq_routing_entry entries[0];
+};
+
+No flags are specified so far, the corresponding field must be set to zero.
+
+struct kvm_irq_routing_entry {
+       __u32 gsi;
+       __u32 type;
+       __u32 flags;
+       __u32 pad;
+       union {
+               struct kvm_irq_routing_irqchip irqchip;
+               struct kvm_irq_routing_msi msi;
+               struct kvm_irq_routing_s390_adapter adapter;
+               struct kvm_irq_routing_hv_sint hv_sint;
+               __u32 pad[8];
+       } u;
+};
+
+/* gsi routing entry types */
+#define KVM_IRQ_ROUTING_IRQCHIP 1
+#define KVM_IRQ_ROUTING_MSI 2
+#define KVM_IRQ_ROUTING_S390_ADAPTER 3
+#define KVM_IRQ_ROUTING_HV_SINT 4
+
+flags:
+- KVM_MSI_VALID_DEVID: used along with KVM_IRQ_ROUTING_MSI routing entry
+  type, specifies that the devid field contains a valid value.  The per-VM
+  KVM_CAP_MSI_DEVID capability advertises the requirement to provide
+  the device ID.  If this capability is not available, userspace should
+  never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
+- zero otherwise
+
+struct kvm_irq_routing_irqchip {
+       __u32 irqchip;
+       __u32 pin;
+};
+
+struct kvm_irq_routing_msi {
+       __u32 address_lo;
+       __u32 address_hi;
+       __u32 data;
+       union {
+               __u32 pad;
+               __u32 devid;
+       };
+};
+
+If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
+for the device that wrote the MSI message.  For PCI, this is usually a
+BFD identifier in the lower 16 bits.
+
+On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
+feature of KVM_CAP_X2APIC_API capability is enabled.  If it is enabled,
+address_hi bits 31-8 provide bits 31-8 of the destination id.  Bits 7-0 of
+address_hi must be zero.
+
+struct kvm_irq_routing_s390_adapter {
+       __u64 ind_addr;
+       __u64 summary_addr;
+       __u64 ind_offset;
+       __u32 summary_offset;
+       __u32 adapter_id;
+};
+
+struct kvm_irq_routing_hv_sint {
+       __u32 vcpu;
+       __u32 sint;
+};
+
+
+4.55 KVM_SET_TSC_KHZ
+
+Capability: KVM_CAP_TSC_CONTROL
+Architectures: x86
+Type: vcpu ioctl
+Parameters: virtual tsc_khz
+Returns: 0 on success, -1 on error
+
+Specifies the tsc frequency for the virtual machine. The unit of the
+frequency is KHz.
+
+
+4.56 KVM_GET_TSC_KHZ
+
+Capability: KVM_CAP_GET_TSC_KHZ
+Architectures: x86
+Type: vcpu ioctl
+Parameters: none
+Returns: virtual tsc-khz on success, negative value on error
+
+Returns the tsc frequency of the guest. The unit of the return value is
+KHz. If the host has unstable tsc this ioctl returns -EIO instead as an
+error.
+
+
+4.57 KVM_GET_LAPIC
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_lapic_state (out)
+Returns: 0 on success, -1 on error
+
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+       char regs[KVM_APIC_REG_SIZE];
+};
+
+Reads the Local APIC registers and copies them into the input argument.  The
+data format and layout are the same as documented in the architecture manual.
+
+If KVM_X2APIC_API_USE_32BIT_IDS feature of KVM_CAP_X2APIC_API is
+enabled, then the format of APIC_ID register depends on the APIC mode
+(reported by MSR_IA32_APICBASE) of its VCPU.  x2APIC stores APIC ID in
+the APIC_ID register (bytes 32-35).  xAPIC only allows an 8-bit APIC ID
+which is stored in bits 31-24 of the APIC register, or equivalently in
+byte 35 of struct kvm_lapic_state's regs field.  KVM_GET_LAPIC must then
+be called after MSR_IA32_APICBASE has been set with KVM_SET_MSR.
+
+If KVM_X2APIC_API_USE_32BIT_IDS feature is disabled, struct kvm_lapic_state
+always uses xAPIC format.
+
+
+4.58 KVM_SET_LAPIC
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_lapic_state (in)
+Returns: 0 on success, -1 on error
+
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+       char regs[KVM_APIC_REG_SIZE];
+};
+
+Copies the input argument into the Local APIC registers.  The data format
+and layout are the same as documented in the architecture manual.
+
+The format of the APIC ID register (bytes 32-35 of struct kvm_lapic_state's
+regs field) depends on the state of the KVM_CAP_X2APIC_API capability.
+See the note in KVM_GET_LAPIC.
+
+
+4.59 KVM_IOEVENTFD
+
+Capability: KVM_CAP_IOEVENTFD
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_ioeventfd (in)
+Returns: 0 on success, !0 on error
+
+This ioctl attaches or detaches an ioeventfd to a legal pio/mmio address
+within the guest.  A guest write in the registered address will signal the
+provided event instead of triggering an exit.
+
+struct kvm_ioeventfd {
+       __u64 datamatch;
+       __u64 addr;        /* legal pio/mmio address */
+       __u32 len;         /* 0, 1, 2, 4, or 8 bytes    */
+       __s32 fd;
+       __u32 flags;
+       __u8  pad[36];
+};
+
+For the special case of virtio-ccw devices on s390, the ioevent is matched
+to a subchannel/virtqueue tuple instead.
+
+The following flags are defined:
+
+#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
+#define KVM_IOEVENTFD_FLAG_PIO       (1 << kvm_ioeventfd_flag_nr_pio)
+#define KVM_IOEVENTFD_FLAG_DEASSIGN  (1 << kvm_ioeventfd_flag_nr_deassign)
+#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
+       (1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
+
+If datamatch flag is set, the event will be signaled only if the written value
+to the registered address is equal to datamatch in struct kvm_ioeventfd.
+
+For virtio-ccw devices, addr contains the subchannel id and datamatch the
+virtqueue index.
+
+With KVM_CAP_IOEVENTFD_ANY_LENGTH, a zero length ioeventfd is allowed, and
+the kernel will ignore the length of guest write and may get a faster vmexit.
+The speedup may only apply to specific architectures, but the ioeventfd will
+work anyway.
+
+4.60 KVM_DIRTY_TLB
+
+Capability: KVM_CAP_SW_TLB
+Architectures: ppc
+Type: vcpu ioctl
+Parameters: struct kvm_dirty_tlb (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_dirty_tlb {
+       __u64 bitmap;
+       __u32 num_dirty;
+};
+
+This must be called whenever userspace has changed an entry in the shared
+TLB, prior to calling KVM_RUN on the associated vcpu.
+
+The "bitmap" field is the userspace address of an array.  This array
+consists of a number of bits, equal to the total number of TLB entries as
+determined by the last successful call to KVM_CONFIG_TLB, rounded up to the
+nearest multiple of 64.
+
+Each bit corresponds to one TLB entry, ordered the same as in the shared TLB
+array.
+
+The array is little-endian: the bit 0 is the least significant bit of the
+first byte, bit 8 is the least significant bit of the second byte, etc.
+This avoids any complications with differing word sizes.
+
+The "num_dirty" field is a performance hint for KVM to determine whether it
+should skip processing the bitmap and just invalidate everything.  It must
+be set to the number of set bits in the bitmap.
+
+
+4.62 KVM_CREATE_SPAPR_TCE
+
+Capability: KVM_CAP_SPAPR_TCE
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_create_spapr_tce (in)
+Returns: file descriptor for manipulating the created TCE table
+
+This creates a virtual TCE (translation control entry) table, which
+is an IOMMU for PAPR-style virtual I/O.  It is used to translate
+logical addresses used in virtual I/O into guest physical addresses,
+and provides a scatter/gather capability for PAPR virtual I/O.
+
+/* for KVM_CAP_SPAPR_TCE */
+struct kvm_create_spapr_tce {
+       __u64 liobn;
+       __u32 window_size;
+};
+
+The liobn field gives the logical IO bus number for which to create a
+TCE table.  The window_size field specifies the size of the DMA window
+which this TCE table will translate - the table will contain one 64
+bit TCE entry for every 4kiB of the DMA window.
+
+When the guest issues an H_PUT_TCE hcall on a liobn for which a TCE
+table has been created using this ioctl(), the kernel will handle it
+in real mode, updating the TCE table.  H_PUT_TCE calls for other
+liobns will cause a vm exit and must be handled by userspace.
+
+The return value is a file descriptor which can be passed to mmap(2)
+to map the created TCE table into userspace.  This lets userspace read
+the entries written by kernel-handled H_PUT_TCE calls, and also lets
+userspace update the TCE table directly which is useful in some
+circumstances.
+
+
+4.63 KVM_ALLOCATE_RMA
+
+Capability: KVM_CAP_PPC_RMA
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_allocate_rma (out)
+Returns: file descriptor for mapping the allocated RMA
+
+This allocates a Real Mode Area (RMA) from the pool allocated at boot
+time by the kernel.  An RMA is a physically-contiguous, aligned region
+of memory used on older POWER processors to provide the memory which
+will be accessed by real-mode (MMU off) accesses in a KVM guest.
+POWER processors support a set of sizes for the RMA that usually
+includes 64MB, 128MB, 256MB and some larger powers of two.
+
+/* for KVM_ALLOCATE_RMA */
+struct kvm_allocate_rma {
+       __u64 rma_size;
+};
+
+The return value is a file descriptor which can be passed to mmap(2)
+to map the allocated RMA into userspace.  The mapped area can then be
+passed to the KVM_SET_USER_MEMORY_REGION ioctl to establish it as the
+RMA for a virtual machine.  The size of the RMA in bytes (which is
+fixed at host kernel boot time) is returned in the rma_size field of
+the argument structure.
+
+The KVM_CAP_PPC_RMA capability is 1 or 2 if the KVM_ALLOCATE_RMA ioctl
+is supported; 2 if the processor requires all virtual machines to have
+an RMA, or 1 if the processor can use an RMA but doesn't require it,
+because it supports the Virtual RMA (VRMA) facility.
+
+
+4.64 KVM_NMI
+
+Capability: KVM_CAP_USER_NMI
+Architectures: x86
+Type: vcpu ioctl
+Parameters: none
+Returns: 0 on success, -1 on error
+
+Queues an NMI on the thread's vcpu.  Note this is well defined only
+when KVM_CREATE_IRQCHIP has not been called, since this is an interface
+between the virtual cpu core and virtual local APIC.  After KVM_CREATE_IRQCHIP
+has been called, this interface is completely emulated within the kernel.
+
+To use this to emulate the LINT1 input with KVM_CREATE_IRQCHIP, use the
+following algorithm:
+
+  - pause the vcpu
+  - read the local APIC's state (KVM_GET_LAPIC)
+  - check whether changing LINT1 will queue an NMI (see the LVT entry for LINT1)
+  - if so, issue KVM_NMI
+  - resume the vcpu
+
+Some guests configure the LINT1 NMI input to cause a panic, aiding in
+debugging.
+
+
+4.65 KVM_S390_UCAS_MAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl maps the memory at "user_addr" with the length "length" to
+the vcpu's address space starting at "vcpu_addr". All parameters need to
+be aligned by 1 megabyte.
+
+
+4.66 KVM_S390_UCAS_UNMAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl unmaps the memory in the vcpu's address space starting at
+"vcpu_addr" with the length "length". The field "user_addr" is ignored.
+All parameters need to be aligned by 1 megabyte.
+
+
+4.67 KVM_S390_VCPU_FAULT
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: vcpu absolute address (in)
+Returns: 0 in case of success
+
+This call creates a page table entry on the virtual cpu's address space
+(for user controlled virtual machines) or the virtual machine's address
+space (for regular virtual machines). This only works for minor faults,
+thus it's recommended to access subject memory page via the user page
+table upfront. This is useful to handle validity intercepts for user
+controlled virtual machines to fault in the virtual cpu's lowcore pages
+prior to calling the KVM_RUN ioctl.
+
+
+4.68 KVM_SET_ONE_REG
+
+Capability: KVM_CAP_ONE_REG
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_one_reg (in)
+Returns: 0 on success, negative value on failure
+Errors:
+  ENOENT:   no such register
+  EINVAL:   invalid register ID, or no such register
+  EPERM:    (arm64) register access not allowed before vcpu finalization
+(These error codes are indicative only: do not rely on a specific error
+code being returned in a specific situation.)
+
+struct kvm_one_reg {
+       __u64 id;
+       __u64 addr;
+};
+
+Using this ioctl, a single vcpu register can be set to a specific value
+defined by user space with the passed in struct kvm_one_reg, where id
+refers to the register identifier as described below and addr is a pointer
+to a variable with the respective size. There can be architecture agnostic
+and architecture specific registers. Each have their own range of operation
+and their own constants and width. To keep track of the implemented
+registers, find a list below:
+
+  Arch  |           Register            | Width (bits)
+        |                               |
+  PPC   | KVM_REG_PPC_HIOR              | 64
+  PPC   | KVM_REG_PPC_IAC1              | 64
+  PPC   | KVM_REG_PPC_IAC2              | 64
+  PPC   | KVM_REG_PPC_IAC3              | 64
+  PPC   | KVM_REG_PPC_IAC4              | 64
+  PPC   | KVM_REG_PPC_DAC1              | 64
+  PPC   | KVM_REG_PPC_DAC2              | 64
+  PPC   | KVM_REG_PPC_DABR              | 64
+  PPC   | KVM_REG_PPC_DSCR              | 64
+  PPC   | KVM_REG_PPC_PURR              | 64
+  PPC   | KVM_REG_PPC_SPURR             | 64
+  PPC   | KVM_REG_PPC_DAR               | 64
+  PPC   | KVM_REG_PPC_DSISR             | 32
+  PPC   | KVM_REG_PPC_AMR               | 64
+  PPC   | KVM_REG_PPC_UAMOR             | 64
+  PPC   | KVM_REG_PPC_MMCR0             | 64
+  PPC   | KVM_REG_PPC_MMCR1             | 64
+  PPC   | KVM_REG_PPC_MMCRA             | 64
+  PPC   | KVM_REG_PPC_MMCR2             | 64
+  PPC   | KVM_REG_PPC_MMCRS             | 64
+  PPC   | KVM_REG_PPC_SIAR              | 64
+  PPC   | KVM_REG_PPC_SDAR              | 64
+  PPC   | KVM_REG_PPC_SIER              | 64
+  PPC   | KVM_REG_PPC_PMC1              | 32
+  PPC   | KVM_REG_PPC_PMC2              | 32
+  PPC   | KVM_REG_PPC_PMC3              | 32
+  PPC   | KVM_REG_PPC_PMC4              | 32
+  PPC   | KVM_REG_PPC_PMC5              | 32
+  PPC   | KVM_REG_PPC_PMC6              | 32
+  PPC   | KVM_REG_PPC_PMC7              | 32
+  PPC   | KVM_REG_PPC_PMC8              | 32
+  PPC   | KVM_REG_PPC_FPR0              | 64
+          ...
+  PPC   | KVM_REG_PPC_FPR31             | 64
+  PPC   | KVM_REG_PPC_VR0               | 128
+          ...
+  PPC   | KVM_REG_PPC_VR31              | 128
+  PPC   | KVM_REG_PPC_VSR0              | 128
+          ...
+  PPC   | KVM_REG_PPC_VSR31             | 128
+  PPC   | KVM_REG_PPC_FPSCR             | 64
+  PPC   | KVM_REG_PPC_VSCR              | 32
+  PPC   | KVM_REG_PPC_VPA_ADDR          | 64
+  PPC   | KVM_REG_PPC_VPA_SLB           | 128
+  PPC   | KVM_REG_PPC_VPA_DTL           | 128
+  PPC   | KVM_REG_PPC_EPCR              | 32
+  PPC   | KVM_REG_PPC_EPR               | 32
+  PPC   | KVM_REG_PPC_TCR               | 32
+  PPC   | KVM_REG_PPC_TSR               | 32
+  PPC   | KVM_REG_PPC_OR_TSR            | 32
+  PPC   | KVM_REG_PPC_CLEAR_TSR         | 32
+  PPC   | KVM_REG_PPC_MAS0              | 32
+  PPC   | KVM_REG_PPC_MAS1              | 32
+  PPC   | KVM_REG_PPC_MAS2              | 64
+  PPC   | KVM_REG_PPC_MAS7_3            | 64
+  PPC   | KVM_REG_PPC_MAS4              | 32
+  PPC   | KVM_REG_PPC_MAS6              | 32
+  PPC   | KVM_REG_PPC_MMUCFG            | 32
+  PPC   | KVM_REG_PPC_TLB0CFG           | 32
+  PPC   | KVM_REG_PPC_TLB1CFG           | 32
+  PPC   | KVM_REG_PPC_TLB2CFG           | 32
+  PPC   | KVM_REG_PPC_TLB3CFG           | 32
+  PPC   | KVM_REG_PPC_TLB0PS            | 32
+  PPC   | KVM_REG_PPC_TLB1PS            | 32
+  PPC   | KVM_REG_PPC_TLB2PS            | 32
+  PPC   | KVM_REG_PPC_TLB3PS            | 32
+  PPC   | KVM_REG_PPC_EPTCFG            | 32
+  PPC   | KVM_REG_PPC_ICP_STATE         | 64
+  PPC   | KVM_REG_PPC_VP_STATE          | 128
+  PPC   | KVM_REG_PPC_TB_OFFSET         | 64
+  PPC   | KVM_REG_PPC_SPMC1             | 32
+  PPC   | KVM_REG_PPC_SPMC2             | 32
+  PPC   | KVM_REG_PPC_IAMR              | 64
+  PPC   | KVM_REG_PPC_TFHAR             | 64
+  PPC   | KVM_REG_PPC_TFIAR             | 64
+  PPC   | KVM_REG_PPC_TEXASR            | 64
+  PPC   | KVM_REG_PPC_FSCR              | 64
+  PPC   | KVM_REG_PPC_PSPB              | 32
+  PPC   | KVM_REG_PPC_EBBHR             | 64
+  PPC   | KVM_REG_PPC_EBBRR             | 64
+  PPC   | KVM_REG_PPC_BESCR             | 64
+  PPC   | KVM_REG_PPC_TAR               | 64
+  PPC   | KVM_REG_PPC_DPDES             | 64
+  PPC   | KVM_REG_PPC_DAWR              | 64
+  PPC   | KVM_REG_PPC_DAWRX             | 64
+  PPC   | KVM_REG_PPC_CIABR             | 64
+  PPC   | KVM_REG_PPC_IC                | 64
+  PPC   | KVM_REG_PPC_VTB               | 64
+  PPC   | KVM_REG_PPC_CSIGR             | 64
+  PPC   | KVM_REG_PPC_TACR              | 64
+  PPC   | KVM_REG_PPC_TCSCR             | 64
+  PPC   | KVM_REG_PPC_PID               | 64
+  PPC   | KVM_REG_PPC_ACOP              | 64
+  PPC   | KVM_REG_PPC_VRSAVE            | 32
+  PPC   | KVM_REG_PPC_LPCR              | 32
+  PPC   | KVM_REG_PPC_LPCR_64           | 64
+  PPC   | KVM_REG_PPC_PPR               | 64
+  PPC   | KVM_REG_PPC_ARCH_COMPAT       | 32
+  PPC   | KVM_REG_PPC_DABRX             | 32
+  PPC   | KVM_REG_PPC_WORT              | 64
+  PPC  | KVM_REG_PPC_SPRG9             | 64
+  PPC  | KVM_REG_PPC_DBSR              | 32
+  PPC   | KVM_REG_PPC_TIDR              | 64
+  PPC   | KVM_REG_PPC_PSSCR             | 64
+  PPC   | KVM_REG_PPC_DEC_EXPIRY        | 64
+  PPC   | KVM_REG_PPC_PTCR              | 64
+  PPC   | KVM_REG_PPC_TM_GPR0           | 64
+          ...
+  PPC   | KVM_REG_PPC_TM_GPR31          | 64
+  PPC   | KVM_REG_PPC_TM_VSR0           | 128
+          ...
+  PPC   | KVM_REG_PPC_TM_VSR63          | 128
+  PPC   | KVM_REG_PPC_TM_CR             | 64
+  PPC   | KVM_REG_PPC_TM_LR             | 64
+  PPC   | KVM_REG_PPC_TM_CTR            | 64
+  PPC   | KVM_REG_PPC_TM_FPSCR          | 64
+  PPC   | KVM_REG_PPC_TM_AMR            | 64
+  PPC   | KVM_REG_PPC_TM_PPR            | 64
+  PPC   | KVM_REG_PPC_TM_VRSAVE         | 64
+  PPC   | KVM_REG_PPC_TM_VSCR           | 32
+  PPC   | KVM_REG_PPC_TM_DSCR           | 64
+  PPC   | KVM_REG_PPC_TM_TAR            | 64
+  PPC   | KVM_REG_PPC_TM_XER            | 64
+        |                               |
+  MIPS  | KVM_REG_MIPS_R0               | 64
+          ...
+  MIPS  | KVM_REG_MIPS_R31              | 64
+  MIPS  | KVM_REG_MIPS_HI               | 64
+  MIPS  | KVM_REG_MIPS_LO               | 64
+  MIPS  | KVM_REG_MIPS_PC               | 64
+  MIPS  | KVM_REG_MIPS_CP0_INDEX        | 32
+  MIPS  | KVM_REG_MIPS_CP0_ENTRYLO0     | 64
+  MIPS  | KVM_REG_MIPS_CP0_ENTRYLO1     | 64
+  MIPS  | KVM_REG_MIPS_CP0_CONTEXT      | 64
+  MIPS  | KVM_REG_MIPS_CP0_CONTEXTCONFIG| 32
+  MIPS  | KVM_REG_MIPS_CP0_USERLOCAL    | 64
+  MIPS  | KVM_REG_MIPS_CP0_XCONTEXTCONFIG| 64
+  MIPS  | KVM_REG_MIPS_CP0_PAGEMASK     | 32
+  MIPS  | KVM_REG_MIPS_CP0_PAGEGRAIN    | 32
+  MIPS  | KVM_REG_MIPS_CP0_SEGCTL0      | 64
+  MIPS  | KVM_REG_MIPS_CP0_SEGCTL1      | 64
+  MIPS  | KVM_REG_MIPS_CP0_SEGCTL2      | 64
+  MIPS  | KVM_REG_MIPS_CP0_PWBASE       | 64
+  MIPS  | KVM_REG_MIPS_CP0_PWFIELD      | 64
+  MIPS  | KVM_REG_MIPS_CP0_PWSIZE       | 64
+  MIPS  | KVM_REG_MIPS_CP0_WIRED        | 32
+  MIPS  | KVM_REG_MIPS_CP0_PWCTL        | 32
+  MIPS  | KVM_REG_MIPS_CP0_HWRENA       | 32
+  MIPS  | KVM_REG_MIPS_CP0_BADVADDR     | 64
+  MIPS  | KVM_REG_MIPS_CP0_BADINSTR     | 32
+  MIPS  | KVM_REG_MIPS_CP0_BADINSTRP    | 32
+  MIPS  | KVM_REG_MIPS_CP0_COUNT        | 32
+  MIPS  | KVM_REG_MIPS_CP0_ENTRYHI      | 64
+  MIPS  | KVM_REG_MIPS_CP0_COMPARE      | 32
+  MIPS  | KVM_REG_MIPS_CP0_STATUS       | 32
+  MIPS  | KVM_REG_MIPS_CP0_INTCTL       | 32
+  MIPS  | KVM_REG_MIPS_CP0_CAUSE        | 32
+  MIPS  | KVM_REG_MIPS_CP0_EPC          | 64
+  MIPS  | KVM_REG_MIPS_CP0_PRID         | 32
+  MIPS  | KVM_REG_MIPS_CP0_EBASE        | 64
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG       | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG1      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG2      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG3      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG4      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG5      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG7      | 32
+  MIPS  | KVM_REG_MIPS_CP0_XCONTEXT     | 64
+  MIPS  | KVM_REG_MIPS_CP0_ERROREPC     | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH1    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH2    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH3    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH4    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH5    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH6    | 64
+  MIPS  | KVM_REG_MIPS_CP0_MAAR(0..63)  | 64
+  MIPS  | KVM_REG_MIPS_COUNT_CTL        | 64
+  MIPS  | KVM_REG_MIPS_COUNT_RESUME     | 64
+  MIPS  | KVM_REG_MIPS_COUNT_HZ         | 64
+  MIPS  | KVM_REG_MIPS_FPR_32(0..31)    | 32
+  MIPS  | KVM_REG_MIPS_FPR_64(0..31)    | 64
+  MIPS  | KVM_REG_MIPS_VEC_128(0..31)   | 128
+  MIPS  | KVM_REG_MIPS_FCR_IR           | 32
+  MIPS  | KVM_REG_MIPS_FCR_CSR          | 32
+  MIPS  | KVM_REG_MIPS_MSA_IR           | 32
+  MIPS  | KVM_REG_MIPS_MSA_CSR          | 32
+
+ARM registers are mapped using the lower 32 bits.  The upper 16 of that
+is the register group type, or coprocessor number:
+
+ARM core registers have the following id bit patterns:
+  0x4020 0000 0010 <index into the kvm_regs struct:16>
+
+ARM 32-bit CP15 registers have the following id bit patterns:
+  0x4020 0000 000F <zero:1> <crn:4> <crm:4> <opc1:4> <opc2:3>
+
+ARM 64-bit CP15 registers have the following id bit patterns:
+  0x4030 0000 000F <zero:1> <zero:4> <crm:4> <opc1:4> <zero:3>
+
+ARM CCSIDR registers are demultiplexed by CSSELR value:
+  0x4020 0000 0011 00 <csselr:8>
+
+ARM 32-bit VFP control registers have the following id bit patterns:
+  0x4020 0000 0012 1 <regno:12>
+
+ARM 64-bit FP registers have the following id bit patterns:
+  0x4030 0000 0012 0 <regno:12>
+
+ARM firmware pseudo-registers have the following bit pattern:
+  0x4030 0000 0014 <regno:16>
+
+
+arm64 registers are mapped using the lower 32 bits. The upper 16 of
+that is the register group type, or coprocessor number:
+
+arm64 core/FP-SIMD registers have the following id bit patterns. Note
+that the size of the access is variable, as the kvm_regs structure
+contains elements ranging from 32 to 128 bits. The index is a 32bit
+value in the kvm_regs structure seen as a 32bit array.
+  0x60x0 0000 0010 <index into the kvm_regs struct:16>
+
+Specifically:
+    Encoding            Register  Bits  kvm_regs member
+----------------------------------------------------------------
+  0x6030 0000 0010 0000 X0          64  regs.regs[0]
+  0x6030 0000 0010 0002 X1          64  regs.regs[1]
+    ...
+  0x6030 0000 0010 003c X30         64  regs.regs[30]
+  0x6030 0000 0010 003e SP          64  regs.sp
+  0x6030 0000 0010 0040 PC          64  regs.pc
+  0x6030 0000 0010 0042 PSTATE      64  regs.pstate
+  0x6030 0000 0010 0044 SP_EL1      64  sp_el1
+  0x6030 0000 0010 0046 ELR_EL1     64  elr_el1
+  0x6030 0000 0010 0048 SPSR_EL1    64  spsr[KVM_SPSR_EL1] (alias SPSR_SVC)
+  0x6030 0000 0010 004a SPSR_ABT    64  spsr[KVM_SPSR_ABT]
+  0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
+  0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
+  0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
+  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]    (*)
+  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]    (*)
+    ...
+  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]   (*)
+  0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
+  0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
+
+(*) These encodings are not accepted for SVE-enabled vcpus.  See
+    KVM_ARM_VCPU_INIT.
+
+    The equivalent register content can be accessed via bits [127:0] of
+    the corresponding SVE Zn registers instead for vcpus that have SVE
+    enabled (see below).
+
+arm64 CCSIDR registers are demultiplexed by CSSELR value:
+  0x6020 0000 0011 00 <csselr:8>
+
+arm64 system registers have the following id bit patterns:
+  0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3>
+
+arm64 firmware pseudo-registers have the following bit pattern:
+  0x6030 0000 0014 <regno:16>
+
+arm64 SVE registers have the following bit patterns:
+  0x6080 0000 0015 00 <n:5> <slice:5>   Zn bits[2048*slice + 2047 : 2048*slice]
+  0x6050 0000 0015 04 <n:4> <slice:5>   Pn bits[256*slice + 255 : 256*slice]
+  0x6050 0000 0015 060 <slice:5>        FFR bits[256*slice + 255 : 256*slice]
+  0x6060 0000 0015 ffff                 KVM_REG_ARM64_SVE_VLS pseudo-register
+
+Access to register IDs where 2048 * slice >= 128 * max_vq will fail with
+ENOENT.  max_vq is the vcpu's maximum supported vector length in 128-bit
+quadwords: see (**) below.
+
+These registers are only accessible on vcpus for which SVE is enabled.
+See KVM_ARM_VCPU_INIT for details.
+
+In addition, except for KVM_REG_ARM64_SVE_VLS, these registers are not
+accessible until the vcpu's SVE configuration has been finalized
+using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).  See KVM_ARM_VCPU_INIT
+and KVM_ARM_VCPU_FINALIZE for more information about this procedure.
+
+KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector
+lengths supported by the vcpu to be discovered and configured by
+userspace.  When transferred to or from user memory via KVM_GET_ONE_REG
+or KVM_SET_ONE_REG, the value of this register is of type
+__u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the set of vector lengths as
+follows:
+
+__u64 vector_lengths[KVM_ARM64_SVE_VLS_WORDS];
+
+if (vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX &&
+    ((vector_lengths[(vq - KVM_ARM64_SVE_VQ_MIN) / 64] >>
+               ((vq - KVM_ARM64_SVE_VQ_MIN) % 64)) & 1))
+       /* Vector length vq * 16 bytes supported */
+else
+       /* Vector length vq * 16 bytes not supported */
+
+(**) The maximum value vq for which the above condition is true is
+max_vq.  This is the maximum vector length available to the guest on
+this vcpu, and determines which register slices are visible through
+this ioctl interface.
+
+(See Documentation/arm64/sve.rst for an explanation of the "vq"
+nomenclature.)
+
+KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT.
+KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that
+the host supports.
+
+Userspace may subsequently modify it if desired until the vcpu's SVE
+configuration is finalized using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).
+
+Apart from simply removing all vector lengths from the host set that
+exceed some value, support for arbitrarily chosen sets of vector lengths
+is hardware-dependent and may not be available.  Attempting to configure
+an invalid set of vector lengths via KVM_SET_ONE_REG will fail with
+EINVAL.
+
+After the vcpu's SVE configuration is finalized, further attempts to
+write this register will fail with EPERM.
+
+
+MIPS registers are mapped using the lower 32 bits.  The upper 16 of that is
+the register group type:
+
+MIPS core registers (see above) have the following id bit patterns:
+  0x7030 0000 0000 <reg:16>
+
+MIPS CP0 registers (see KVM_REG_MIPS_CP0_* above) have the following id bit
+patterns depending on whether they're 32-bit or 64-bit registers:
+  0x7020 0000 0001 00 <reg:5> <sel:3>   (32-bit)
+  0x7030 0000 0001 00 <reg:5> <sel:3>   (64-bit)
+
+Note: KVM_REG_MIPS_CP0_ENTRYLO0 and KVM_REG_MIPS_CP0_ENTRYLO1 are the MIPS64
+versions of the EntryLo registers regardless of the word size of the host
+hardware, host kernel, guest, and whether XPA is present in the guest, i.e.
+with the RI and XI bits (if they exist) in bits 63 and 62 respectively, and
+the PFNX field starting at bit 30.
+
+MIPS MAARs (see KVM_REG_MIPS_CP0_MAAR(*) above) have the following id bit
+patterns:
+  0x7030 0000 0001 01 <reg:8>
+
+MIPS KVM control registers (see above) have the following id bit patterns:
+  0x7030 0000 0002 <reg:16>
+
+MIPS FPU registers (see KVM_REG_MIPS_FPR_{32,64}() above) have the following
+id bit patterns depending on the size of the register being accessed. They are
+always accessed according to the current guest FPU mode (Status.FR and
+Config5.FRE), i.e. as the guest would see them, and they become unpredictable
+if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector
+registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they
+overlap the FPU registers:
+  0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers)
+  0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers)
+  0x7040 0000 0003 00 <0:3> <reg:5> (128-bit MSA vector registers)
+
+MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the
+following id bit patterns:
+  0x7020 0000 0003 01 <0:3> <reg:5>
+
+MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the
+following id bit patterns:
+  0x7020 0000 0003 02 <0:3> <reg:5>
+
+
+4.69 KVM_GET_ONE_REG
+
+Capability: KVM_CAP_ONE_REG
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_one_reg (in and out)
+Returns: 0 on success, negative value on failure
+Errors include:
+  ENOENT:   no such register
+  EINVAL:   invalid register ID, or no such register
+  EPERM:    (arm64) register access not allowed before vcpu finalization
+(These error codes are indicative only: do not rely on a specific error
+code being returned in a specific situation.)
+
+This ioctl allows to receive the value of a single register implemented
+in a vcpu. The register to read is indicated by the "id" field of the
+kvm_one_reg struct passed in. On success, the register value can be found
+at the memory location pointed to by "addr".
+
+The list of registers accessible using this interface is identical to the
+list in 4.68.
+
+
+4.70 KVM_KVMCLOCK_CTRL
+
+Capability: KVM_CAP_KVMCLOCK_CTRL
+Architectures: Any that implement pvclocks (currently x86 only)
+Type: vcpu ioctl
+Parameters: None
+Returns: 0 on success, -1 on error
+
+This signals to the host kernel that the specified guest is being paused by
+userspace.  The host will set a flag in the pvclock structure that is checked
+from the soft lockup watchdog.  The flag is part of the pvclock structure that
+is shared between guest and host, specifically the second bit of the flags
+field of the pvclock_vcpu_time_info structure.  It will be set exclusively by
+the host and read/cleared exclusively by the guest.  The guest operation of
+checking and clearing the flag must an atomic operation so
+load-link/store-conditional, or equivalent must be used.  There are two cases
+where the guest will clear the flag: when the soft lockup watchdog timer resets
+itself or when a soft lockup is detected.  This ioctl can be called any time
+after pausing the vcpu, but before it is resumed.
+
+
+4.71 KVM_SIGNAL_MSI
+
+Capability: KVM_CAP_SIGNAL_MSI
+Architectures: x86 arm arm64
+Type: vm ioctl
+Parameters: struct kvm_msi (in)
+Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
+
+Directly inject a MSI message. Only valid with in-kernel irqchip that handles
+MSI messages.
+
+struct kvm_msi {
+       __u32 address_lo;
+       __u32 address_hi;
+       __u32 data;
+       __u32 flags;
+       __u32 devid;
+       __u8  pad[12];
+};
+
+flags: KVM_MSI_VALID_DEVID: devid contains a valid value.  The per-VM
+  KVM_CAP_MSI_DEVID capability advertises the requirement to provide
+  the device ID.  If this capability is not available, userspace
+  should never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
+
+If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
+for the device that wrote the MSI message.  For PCI, this is usually a
+BFD identifier in the lower 16 bits.
+
+On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
+feature of KVM_CAP_X2APIC_API capability is enabled.  If it is enabled,
+address_hi bits 31-8 provide bits 31-8 of the destination id.  Bits 7-0 of
+address_hi must be zero.
+
+
+4.71 KVM_CREATE_PIT2
+
+Capability: KVM_CAP_PIT2
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_pit_config (in)
+Returns: 0 on success, -1 on error
+
+Creates an in-kernel device model for the i8254 PIT. This call is only valid
+after enabling in-kernel irqchip support via KVM_CREATE_IRQCHIP. The following
+parameters have to be passed:
+
+struct kvm_pit_config {
+       __u32 flags;
+       __u32 pad[15];
+};
+
+Valid flags are:
+
+#define KVM_PIT_SPEAKER_DUMMY     1 /* emulate speaker port stub */
+
+PIT timer interrupts may use a per-VM kernel thread for injection. If it
+exists, this thread will have a name of the following pattern:
+
+kvm-pit/<owner-process-pid>
+
+When running a guest with elevated priorities, the scheduling parameters of
+this thread may have to be adjusted accordingly.
+
+This IOCTL replaces the obsolete KVM_CREATE_PIT.
+
+
+4.72 KVM_GET_PIT2
+
+Capability: KVM_CAP_PIT_STATE2
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_pit_state2 (out)
+Returns: 0 on success, -1 on error
+
+Retrieves the state of the in-kernel PIT model. Only valid after
+KVM_CREATE_PIT2. The state is returned in the following structure:
+
+struct kvm_pit_state2 {
+       struct kvm_pit_channel_state channels[3];
+       __u32 flags;
+       __u32 reserved[9];
+};
+
+Valid flags are:
+
+/* disable PIT in HPET legacy mode */
+#define KVM_PIT_FLAGS_HPET_LEGACY  0x00000001
+
+This IOCTL replaces the obsolete KVM_GET_PIT.
+
+
+4.73 KVM_SET_PIT2
+
+Capability: KVM_CAP_PIT_STATE2
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_pit_state2 (in)
+Returns: 0 on success, -1 on error
+
+Sets the state of the in-kernel PIT model. Only valid after KVM_CREATE_PIT2.
+See KVM_GET_PIT2 for details on struct kvm_pit_state2.
+
+This IOCTL replaces the obsolete KVM_SET_PIT.
+
+
+4.74 KVM_PPC_GET_SMMU_INFO
+
+Capability: KVM_CAP_PPC_GET_SMMU_INFO
+Architectures: powerpc
+Type: vm ioctl
+Parameters: None
+Returns: 0 on success, -1 on error
+
+This populates and returns a structure describing the features of
+the "Server" class MMU emulation supported by KVM.
+This can in turn be used by userspace to generate the appropriate
+device-tree properties for the guest operating system.
+
+The structure contains some global information, followed by an
+array of supported segment page sizes:
+
+      struct kvm_ppc_smmu_info {
+            __u64 flags;
+            __u32 slb_size;
+            __u32 pad;
+            struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
+      };
+
+The supported flags are:
+
+    - KVM_PPC_PAGE_SIZES_REAL:
+        When that flag is set, guest page sizes must "fit" the backing
+        store page sizes. When not set, any page size in the list can
+        be used regardless of how they are backed by userspace.
+
+    - KVM_PPC_1T_SEGMENTS
+        The emulated MMU supports 1T segments in addition to the
+        standard 256M ones.
+
+    - KVM_PPC_NO_HASH
+       This flag indicates that HPT guests are not supported by KVM,
+       thus all guests must use radix MMU mode.
+
+The "slb_size" field indicates how many SLB entries are supported
+
+The "sps" array contains 8 entries indicating the supported base
+page sizes for a segment in increasing order. Each entry is defined
+as follow:
+
+   struct kvm_ppc_one_seg_page_size {
+       __u32 page_shift;       /* Base page shift of segment (or 0) */
+       __u32 slb_enc;          /* SLB encoding for BookS */
+       struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
+   };
+
+An entry with a "page_shift" of 0 is unused. Because the array is
+organized in increasing order, a lookup can stop when encoutering
+such an entry.
+
+The "slb_enc" field provides the encoding to use in the SLB for the
+page size. The bits are in positions such as the value can directly
+be OR'ed into the "vsid" argument of the slbmte instruction.
+
+The "enc" array is a list which for each of those segment base page
+size provides the list of supported actual page sizes (which can be
+only larger or equal to the base page size), along with the
+corresponding encoding in the hash PTE. Similarly, the array is
+8 entries sorted by increasing sizes and an entry with a "0" shift
+is an empty entry and a terminator:
+
+   struct kvm_ppc_one_page_size {
+       __u32 page_shift;       /* Page shift (or 0) */
+       __u32 pte_enc;          /* Encoding in the HPTE (>>12) */
+   };
+
+The "pte_enc" field provides a value that can OR'ed into the hash
+PTE's RPN field (ie, it needs to be shifted left by 12 to OR it
+into the hash PTE second double word).
+
+4.75 KVM_IRQFD
+
+Capability: KVM_CAP_IRQFD
+Architectures: x86 s390 arm arm64
+Type: vm ioctl
+Parameters: struct kvm_irqfd (in)
+Returns: 0 on success, -1 on error
+
+Allows setting an eventfd to directly trigger a guest interrupt.
+kvm_irqfd.fd specifies the file descriptor to use as the eventfd and
+kvm_irqfd.gsi specifies the irqchip pin toggled by this event.  When
+an event is triggered on the eventfd, an interrupt is injected into
+the guest using the specified gsi pin.  The irqfd is removed using
+the KVM_IRQFD_FLAG_DEASSIGN flag, specifying both kvm_irqfd.fd
+and kvm_irqfd.gsi.
+
+With KVM_CAP_IRQFD_RESAMPLE, KVM_IRQFD supports a de-assert and notify
+mechanism allowing emulation of level-triggered, irqfd-based
+interrupts.  When KVM_IRQFD_FLAG_RESAMPLE is set the user must pass an
+additional eventfd in the kvm_irqfd.resamplefd field.  When operating
+in resample mode, posting of an interrupt through kvm_irq.fd asserts
+the specified gsi in the irqchip.  When the irqchip is resampled, such
+as from an EOI, the gsi is de-asserted and the user is notified via
+kvm_irqfd.resamplefd.  It is the user's responsibility to re-queue
+the interrupt if the device making use of it still requires service.
+Note that closing the resamplefd is not sufficient to disable the
+irqfd.  The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
+and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
+
+On arm/arm64, gsi routing being supported, the following can happen:
+- in case no routing entry is associated to this gsi, injection fails
+- in case the gsi is associated to an irqchip routing entry,
+  irqchip.pin + 32 corresponds to the injected SPI ID.
+- in case the gsi is associated to an MSI routing entry, the MSI
+  message and device ID are translated into an LPI (support restricted
+  to GICv3 ITS in-kernel emulation).
+
+4.76 KVM_PPC_ALLOCATE_HTAB
+
+Capability: KVM_CAP_PPC_ALLOC_HTAB
+Architectures: powerpc
+Type: vm ioctl
+Parameters: Pointer to u32 containing hash table order (in/out)
+Returns: 0 on success, -1 on error
+
+This requests the host kernel to allocate an MMU hash table for a
+guest using the PAPR paravirtualization interface.  This only does
+anything if the kernel is configured to use the Book 3S HV style of
+virtualization.  Otherwise the capability doesn't exist and the ioctl
+returns an ENOTTY error.  The rest of this description assumes Book 3S
+HV.
+
+There must be no vcpus running when this ioctl is called; if there
+are, it will do nothing and return an EBUSY error.
+
+The parameter is a pointer to a 32-bit unsigned integer variable
+containing the order (log base 2) of the desired size of the hash
+table, which must be between 18 and 46.  On successful return from the
+ioctl, the value will not be changed by the kernel.
+
+If no hash table has been allocated when any vcpu is asked to run
+(with the KVM_RUN ioctl), the host kernel will allocate a
+default-sized hash table (16 MB).
+
+If this ioctl is called when a hash table has already been allocated,
+with a different order from the existing hash table, the existing hash
+table will be freed and a new one allocated.  If this is ioctl is
+called when a hash table has already been allocated of the same order
+as specified, the kernel will clear out the existing hash table (zero
+all HPTEs).  In either case, if the guest is using the virtualized
+real-mode area (VRMA) facility, the kernel will re-create the VMRA
+HPTEs on the next KVM_RUN of any vcpu.
+
+4.77 KVM_S390_INTERRUPT
+
+Capability: basic
+Architectures: s390
+Type: vm ioctl, vcpu ioctl
+Parameters: struct kvm_s390_interrupt (in)
+Returns: 0 on success, -1 on error
+
+Allows to inject an interrupt to the guest. Interrupts can be floating
+(vm ioctl) or per cpu (vcpu ioctl), depending on the interrupt type.
+
+Interrupt parameters are passed via kvm_s390_interrupt:
+
+struct kvm_s390_interrupt {
+       __u32 type;
+       __u32 parm;
+       __u64 parm64;
+};
+
+type can be one of the following:
+
+KVM_S390_SIGP_STOP (vcpu) - sigp stop; optional flags in parm
+KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
+KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
+KVM_S390_RESTART (vcpu) - restart
+KVM_S390_INT_CLOCK_COMP (vcpu) - clock comparator interrupt
+KVM_S390_INT_CPU_TIMER (vcpu) - CPU timer interrupt
+KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
+                          parameters in parm and parm64
+KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
+KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
+KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
+KVM_S390_INT_IO(ai,cssid,ssid,schid) (vm) - compound value to indicate an
+    I/O interrupt (ai - adapter interrupt; cssid,ssid,schid - subchannel);
+    I/O interruption parameters in parm (subchannel) and parm64 (intparm,
+    interruption subclass)
+KVM_S390_MCHK (vm, vcpu) - machine check interrupt; cr 14 bits in parm,
+                           machine check interrupt code in parm64 (note that
+                           machine checks needing further payload are not
+                           supported by this ioctl)
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
+4.78 KVM_PPC_GET_HTAB_FD
+
+Capability: KVM_CAP_PPC_HTAB_FD
+Architectures: powerpc
+Type: vm ioctl
+Parameters: Pointer to struct kvm_get_htab_fd (in)
+Returns: file descriptor number (>= 0) on success, -1 on error
+
+This returns a file descriptor that can be used either to read out the
+entries in the guest's hashed page table (HPT), or to write entries to
+initialize the HPT.  The returned fd can only be written to if the
+KVM_GET_HTAB_WRITE bit is set in the flags field of the argument, and
+can only be read if that bit is clear.  The argument struct looks like
+this:
+
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+       __u64   flags;
+       __u64   start_index;
+       __u64   reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY       ((__u64)0x1)
+#define KVM_GET_HTAB_WRITE             ((__u64)0x2)
+
+The `start_index' field gives the index in the HPT of the entry at
+which to start reading.  It is ignored when writing.
+
+Reads on the fd will initially supply information about all
+"interesting" HPT entries.  Interesting entries are those with the
+bolted bit set, if the KVM_GET_HTAB_BOLTED_ONLY bit is set, otherwise
+all entries.  When the end of the HPT is reached, the read() will
+return.  If read() is called again on the fd, it will start again from
+the beginning of the HPT, but will only return HPT entries that have
+changed since they were last read.
+
+Data read or written is structured as a header (8 bytes) followed by a
+series of valid HPT entries (16 bytes) each.  The header indicates how
+many valid HPT entries there are and how many invalid entries follow
+the valid entries.  The invalid entries are not represented explicitly
+in the stream.  The header format is:
+
+struct kvm_get_htab_header {
+       __u32   index;
+       __u16   n_valid;
+       __u16   n_invalid;
+};
+
+Writes to the fd create HPT entries starting at the index given in the
+header; first `n_valid' valid entries with contents from the data
+written, then `n_invalid' invalid entries, invalidating any previously
+valid entries found.
+
+4.79 KVM_CREATE_DEVICE
+
+Capability: KVM_CAP_DEVICE_CTRL
+Type: vm ioctl
+Parameters: struct kvm_create_device (in/out)
+Returns: 0 on success, -1 on error
+Errors:
+  ENODEV: The device type is unknown or unsupported
+  EEXIST: Device already created, and this type of device may not
+          be instantiated multiple times
+
+  Other error conditions may be defined by individual device types or
+  have their standard meanings.
+
+Creates an emulated device in the kernel.  The file descriptor returned
+in fd can be used with KVM_SET/GET/HAS_DEVICE_ATTR.
+
+If the KVM_CREATE_DEVICE_TEST flag is set, only test whether the
+device type is supported (not necessarily whether it can be created
+in the current vm).
+
+Individual devices should not define flags.  Attributes should be used
+for specifying any behavior that is not implied by the device type
+number.
+
+struct kvm_create_device {
+       __u32   type;   /* in: KVM_DEV_TYPE_xxx */
+       __u32   fd;     /* out: device handle */
+       __u32   flags;  /* in: KVM_CREATE_DEVICE_xxx */
+};
+
+4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR
+
+Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
+  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
+Type: device ioctl, vm ioctl, vcpu ioctl
+Parameters: struct kvm_device_attr
+Returns: 0 on success, -1 on error
+Errors:
+  ENXIO:  The group or attribute is unknown/unsupported for this device
+          or hardware support is missing.
+  EPERM:  The attribute cannot (currently) be accessed this way
+          (e.g. read-only attribute, or attribute that only makes
+          sense when the device is in a different state)
+
+  Other error conditions may be defined by individual device types.
+
+Gets/sets a specified piece of device configuration and/or state.  The
+semantics are device-specific.  See individual device documentation in
+the "devices" directory.  As with ONE_REG, the size of the data
+transferred is defined by the particular attribute.
+
+struct kvm_device_attr {
+       __u32   flags;          /* no flags currently defined */
+       __u32   group;          /* device-defined */
+       __u64   attr;           /* group-defined */
+       __u64   addr;           /* userspace address of attr data */
+};
+
+4.81 KVM_HAS_DEVICE_ATTR
+
+Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
+  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
+Type: device ioctl, vm ioctl, vcpu ioctl
+Parameters: struct kvm_device_attr
+Returns: 0 on success, -1 on error
+Errors:
+  ENXIO:  The group or attribute is unknown/unsupported for this device
+          or hardware support is missing.
+
+Tests whether a device supports a particular attribute.  A successful
+return indicates the attribute is implemented.  It does not necessarily
+indicate that the attribute can be read or written in the device's
+current state.  "addr" is ignored.
+
+4.82 KVM_ARM_VCPU_INIT
+
+Capability: basic
+Architectures: arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_vcpu_init (in)
+Returns: 0 on success; -1 on error
+Errors:
+  EINVAL:    the target is unknown, or the combination of features is invalid.
+  ENOENT:    a features bit specified is unknown.
+
+This tells KVM what type of CPU to present to the guest, and what
+optional features it should have.  This will cause a reset of the cpu
+registers to their initial values.  If this is not called, KVM_RUN will
+return ENOEXEC for that vcpu.
+
+Note that because some registers reflect machine topology, all vcpus
+should be created before this ioctl is invoked.
+
+Userspace can call this function multiple times for a given vcpu, including
+after the vcpu has been run. This will reset the vcpu to its initial
+state. All calls to this function after the initial call must use the same
+target and same set of feature flags, otherwise EINVAL will be returned.
+
+Possible features:
+       - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state.
+         Depends on KVM_CAP_ARM_PSCI.  If not set, the CPU will be powered on
+         and execute guest code when KVM_RUN is called.
+       - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
+         Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
+       - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
+          backward compatible with v0.2) for the CPU.
+         Depends on KVM_CAP_ARM_PSCI_0_2.
+       - KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
+         Depends on KVM_CAP_ARM_PMU_V3.
+
+       - KVM_ARM_VCPU_PTRAUTH_ADDRESS: Enables Address Pointer authentication
+         for arm64 only.
+         Depends on KVM_CAP_ARM_PTRAUTH_ADDRESS.
+         If KVM_CAP_ARM_PTRAUTH_ADDRESS and KVM_CAP_ARM_PTRAUTH_GENERIC are
+         both present, then both KVM_ARM_VCPU_PTRAUTH_ADDRESS and
+         KVM_ARM_VCPU_PTRAUTH_GENERIC must be requested or neither must be
+         requested.
+
+       - KVM_ARM_VCPU_PTRAUTH_GENERIC: Enables Generic Pointer authentication
+         for arm64 only.
+         Depends on KVM_CAP_ARM_PTRAUTH_GENERIC.
+         If KVM_CAP_ARM_PTRAUTH_ADDRESS and KVM_CAP_ARM_PTRAUTH_GENERIC are
+         both present, then both KVM_ARM_VCPU_PTRAUTH_ADDRESS and
+         KVM_ARM_VCPU_PTRAUTH_GENERIC must be requested or neither must be
+         requested.
+
+       - KVM_ARM_VCPU_SVE: Enables SVE for the CPU (arm64 only).
+         Depends on KVM_CAP_ARM_SVE.
+         Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+
+          * After KVM_ARM_VCPU_INIT:
+
+             - KVM_REG_ARM64_SVE_VLS may be read using KVM_GET_ONE_REG: the
+               initial value of this pseudo-register indicates the best set of
+               vector lengths possible for a vcpu on this host.
+
+          * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+
+             - KVM_RUN and KVM_GET_REG_LIST are not available;
+
+             - KVM_GET_ONE_REG and KVM_SET_ONE_REG cannot be used to access
+               the scalable archietctural SVE registers
+               KVM_REG_ARM64_SVE_ZREG(), KVM_REG_ARM64_SVE_PREG() or
+               KVM_REG_ARM64_SVE_FFR;
+
+             - KVM_REG_ARM64_SVE_VLS may optionally be written using
+               KVM_SET_ONE_REG, to modify the set of vector lengths available
+               for the vcpu.
+
+          * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+
+             - the KVM_REG_ARM64_SVE_VLS pseudo-register is immutable, and can
+               no longer be written using KVM_SET_ONE_REG.
+
+4.83 KVM_ARM_PREFERRED_TARGET
+
+Capability: basic
+Architectures: arm, arm64
+Type: vm ioctl
+Parameters: struct struct kvm_vcpu_init (out)
+Returns: 0 on success; -1 on error
+Errors:
+  ENODEV:    no preferred target available for the host
+
+This queries KVM for preferred CPU target type which can be emulated
+by KVM on underlying host.
+
+The ioctl returns struct kvm_vcpu_init instance containing information
+about preferred CPU target type and recommended features for it.  The
+kvm_vcpu_init->features bitmap returned will have feature bits set if
+the preferred target recommends setting these features, but this is
+not mandatory.
+
+The information returned by this ioctl can be used to prepare an instance
+of struct kvm_vcpu_init for KVM_ARM_VCPU_INIT ioctl which will result in
+in VCPU matching underlying host.
+
+
+4.84 KVM_GET_REG_LIST
+
+Capability: basic
+Architectures: arm, arm64, mips
+Type: vcpu ioctl
+Parameters: struct kvm_reg_list (in/out)
+Returns: 0 on success; -1 on error
+Errors:
+  E2BIG:     the reg index list is too big to fit in the array specified by
+             the user (the number required will be written into n).
+
+struct kvm_reg_list {
+       __u64 n; /* number of registers in reg[] */
+       __u64 reg[0];
+};
+
+This ioctl returns the guest registers that are supported for the
+KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
+
+
+4.85 KVM_ARM_SET_DEVICE_ADDR (deprecated)
+
+Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
+Architectures: arm, arm64
+Type: vm ioctl
+Parameters: struct kvm_arm_device_address (in)
+Returns: 0 on success, -1 on error
+Errors:
+  ENODEV: The device id is unknown
+  ENXIO:  Device not supported on current system
+  EEXIST: Address already set
+  E2BIG:  Address outside guest physical address space
+  EBUSY:  Address overlaps with other device range
+
+struct kvm_arm_device_addr {
+       __u64 id;
+       __u64 addr;
+};
+
+Specify a device address in the guest's physical address space where guests
+can access emulated or directly exposed devices, which the host kernel needs
+to know about. The id field is an architecture specific identifier for a
+specific device.
+
+ARM/arm64 divides the id field into two parts, a device id and an
+address type id specific to the individual device.
+
+  bits:  | 63        ...       32 | 31    ...    16 | 15    ...    0 |
+  field: |        0x00000000      |     device id   |  addr type id  |
+
+ARM/arm64 currently only require this when using the in-kernel GIC
+support for the hardware VGIC features, using KVM_ARM_DEVICE_VGIC_V2
+as the device id.  When setting the base address for the guest's
+mapping of the VGIC virtual CPU and distributor interface, the ioctl
+must be called after calling KVM_CREATE_IRQCHIP, but before calling
+KVM_RUN on any of the VCPUs.  Calling this ioctl twice for any of the
+base addresses will return -EEXIST.
+
+Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
+should be used instead.
+
+
+4.86 KVM_PPC_RTAS_DEFINE_TOKEN
+
+Capability: KVM_CAP_PPC_RTAS
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_rtas_token_args
+Returns: 0 on success, -1 on error
+
+Defines a token value for a RTAS (Run Time Abstraction Services)
+service in order to allow it to be handled in the kernel.  The
+argument struct gives the name of the service, which must be the name
+of a service that has a kernel-side implementation.  If the token
+value is non-zero, it will be associated with that service, and
+subsequent RTAS calls by the guest specifying that token will be
+handled by the kernel.  If the token value is 0, then any token
+associated with the service will be forgotten, and subsequent RTAS
+calls by the guest for that service will be passed to userspace to be
+handled.
+
+4.87 KVM_SET_GUEST_DEBUG
+
+Capability: KVM_CAP_SET_GUEST_DEBUG
+Architectures: x86, s390, ppc, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_guest_debug (in)
+Returns: 0 on success; -1 on error
+
+struct kvm_guest_debug {
+       __u32 control;
+       __u32 pad;
+       struct kvm_guest_debug_arch arch;
+};
+
+Set up the processor specific debug registers and configure vcpu for
+handling guest debug events. There are two parts to the structure, the
+first a control bitfield indicates the type of debug events to handle
+when running. Common control bits are:
+
+  - KVM_GUESTDBG_ENABLE:        guest debugging is enabled
+  - KVM_GUESTDBG_SINGLESTEP:    the next run should single-step
+
+The top 16 bits of the control field are architecture specific control
+flags which can include the following:
+
+  - KVM_GUESTDBG_USE_SW_BP:     using software breakpoints [x86, arm64]
+  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390, arm64]
+  - KVM_GUESTDBG_INJECT_DB:     inject DB type exception [x86]
+  - KVM_GUESTDBG_INJECT_BP:     inject BP type exception [x86]
+  - KVM_GUESTDBG_EXIT_PENDING:  trigger an immediate guest exit [s390]
+
+For example KVM_GUESTDBG_USE_SW_BP indicates that software breakpoints
+are enabled in memory so we need to ensure breakpoint exceptions are
+correctly trapped and the KVM run loop exits at the breakpoint and not
+running off into the normal guest vector. For KVM_GUESTDBG_USE_HW_BP
+we need to ensure the guest vCPUs architecture specific registers are
+updated to the correct (supplied) values.
+
+The second part of the structure is architecture specific and
+typically contains a set of debug registers.
+
+For arm64 the number of debug registers is implementation defined and
+can be determined by querying the KVM_CAP_GUEST_DEBUG_HW_BPS and
+KVM_CAP_GUEST_DEBUG_HW_WPS capabilities which return a positive number
+indicating the number of supported registers.
+
+When debug events exit the main run loop with the reason
+KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
+structure containing architecture specific debug information.
+
+4.88 KVM_GET_EMULATED_CPUID
+
+Capability: KVM_CAP_EXT_EMUL_CPUID
+Architectures: x86
+Type: system ioctl
+Parameters: struct kvm_cpuid2 (in/out)
+Returns: 0 on success, -1 on error
+
+struct kvm_cpuid2 {
+       __u32 nent;
+       __u32 flags;
+       struct kvm_cpuid_entry2 entries[0];
+};
+
+The member 'flags' is used for passing flags from userspace.
+
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX                BIT(0)
+#define KVM_CPUID_FLAG_STATEFUL_FUNC           BIT(1)
+#define KVM_CPUID_FLAG_STATE_READ_NEXT         BIT(2)
+
+struct kvm_cpuid_entry2 {
+       __u32 function;
+       __u32 index;
+       __u32 flags;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding[3];
+};
+
+This ioctl returns x86 cpuid features which are emulated by
+kvm.Userspace can use the information returned by this ioctl to query
+which features are emulated by kvm instead of being present natively.
+
+Userspace invokes KVM_GET_EMULATED_CPUID by passing a kvm_cpuid2
+structure with the 'nent' field indicating the number of entries in
+the variable-size array 'entries'. If the number of entries is too low
+to describe the cpu capabilities, an error (E2BIG) is returned. If the
+number is too high, the 'nent' field is adjusted and an error (ENOMEM)
+is returned. If the number is just right, the 'nent' field is adjusted
+to the number of valid entries in the 'entries' array, which is then
+filled.
+
+The entries returned are the set CPUID bits of the respective features
+which kvm emulates, as returned by the CPUID instruction, with unknown
+or unsupported feature bits cleared.
+
+Features like x2apic, for example, may not be present in the host cpu
+but are exposed by kvm in KVM_GET_SUPPORTED_CPUID because they can be
+emulated efficiently and thus not included here.
+
+The fields in each entry are defined as follows:
+
+  function: the eax value used to obtain the entry
+  index: the ecx value used to obtain the entry (for entries that are
+         affected by ecx)
+  flags: an OR of zero or more of the following:
+        KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
+           if the index field is valid
+        KVM_CPUID_FLAG_STATEFUL_FUNC:
+           if cpuid for this function returns different values for successive
+           invocations; there will be several entries with the same function,
+           all with this flag set
+        KVM_CPUID_FLAG_STATE_READ_NEXT:
+           for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
+           the first entry to be read by a cpu
+   eax, ebx, ecx, edx: the values returned by the cpuid instruction for
+         this function/index combination
+
+4.89 KVM_S390_MEM_OP
+
+Capability: KVM_CAP_S390_MEM_OP
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_mem_op (in)
+Returns: = 0 on success,
+         < 0 on generic error (e.g. -EFAULT or -ENOMEM),
+         > 0 if an exception occurred while walking the page tables
+
+Read or write data from/to the logical (virtual) memory of a VCPU.
+
+Parameters are specified via the following structure:
+
+struct kvm_s390_mem_op {
+       __u64 gaddr;            /* the guest address */
+       __u64 flags;            /* flags */
+       __u32 size;             /* amount of bytes */
+       __u32 op;               /* type of operation */
+       __u64 buf;              /* buffer in userspace */
+       __u8 ar;                /* the access register number */
+       __u8 reserved[31];      /* should be set to 0 */
+};
+
+The type of operation is specified in the "op" field. It is either
+KVM_S390_MEMOP_LOGICAL_READ for reading from logical memory space or
+KVM_S390_MEMOP_LOGICAL_WRITE for writing to logical memory space. The
+KVM_S390_MEMOP_F_CHECK_ONLY flag can be set in the "flags" field to check
+whether the corresponding memory access would create an access exception
+(without touching the data in the memory at the destination). In case an
+access exception occurred while walking the MMU tables of the guest, the
+ioctl returns a positive error number to indicate the type of exception.
+This exception is also raised directly at the corresponding VCPU if the
+flag KVM_S390_MEMOP_F_INJECT_EXCEPTION is set in the "flags" field.
+
+The start address of the memory region has to be specified in the "gaddr"
+field, and the length of the region in the "size" field. "buf" is the buffer
+supplied by the userspace application where the read data should be written
+to for KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written
+is stored for a KVM_S390_MEMOP_LOGICAL_WRITE. "buf" is unused and can be NULL
+when KVM_S390_MEMOP_F_CHECK_ONLY is specified. "ar" designates the access
+register number to be used.
+
+The "reserved" field is meant for future extensions. It is not used by
+KVM with the currently defined set of flags.
+
+4.90 KVM_S390_GET_SKEYS
+
+Capability: KVM_CAP_S390_SKEYS
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_skeys
+Returns: 0 on success, KVM_S390_GET_KEYS_NONE if guest is not using storage
+         keys, negative value on error
+
+This ioctl is used to get guest storage key values on the s390
+architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
+
+struct kvm_s390_skeys {
+       __u64 start_gfn;
+       __u64 count;
+       __u64 skeydata_addr;
+       __u32 flags;
+       __u32 reserved[9];
+};
+
+The start_gfn field is the number of the first guest frame whose storage keys
+you want to get.
+
+The count field is the number of consecutive frames (starting from start_gfn)
+whose storage keys to get. The count field must be at least 1 and the maximum
+allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
+will cause the ioctl to return -EINVAL.
+
+The skeydata_addr field is the address to a buffer large enough to hold count
+bytes. This buffer will be filled with storage key data by the ioctl.
+
+4.91 KVM_S390_SET_SKEYS
+
+Capability: KVM_CAP_S390_SKEYS
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_skeys
+Returns: 0 on success, negative value on error
+
+This ioctl is used to set guest storage key values on the s390
+architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
+See section on KVM_S390_GET_SKEYS for struct definition.
+
+The start_gfn field is the number of the first guest frame whose storage keys
+you want to set.
+
+The count field is the number of consecutive frames (starting from start_gfn)
+whose storage keys to get. The count field must be at least 1 and the maximum
+allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
+will cause the ioctl to return -EINVAL.
+
+The skeydata_addr field is the address to a buffer containing count bytes of
+storage keys. Each byte in the buffer will be set as the storage key for a
+single frame starting at start_gfn for count frames.
+
+Note: If any architecturally invalid key value is found in the given data then
+the ioctl will return -EINVAL.
+
+4.92 KVM_S390_IRQ
+
+Capability: KVM_CAP_S390_INJECT_IRQ
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq (in)
+Returns: 0 on success, -1 on error
+Errors:
+  EINVAL: interrupt type is invalid
+          type is KVM_S390_SIGP_STOP and flag parameter is invalid value
+          type is KVM_S390_INT_EXTERNAL_CALL and code is bigger
+            than the maximum of VCPUs
+  EBUSY:  type is KVM_S390_SIGP_SET_PREFIX and vcpu is not stopped
+          type is KVM_S390_SIGP_STOP and a stop irq is already pending
+          type is KVM_S390_INT_EXTERNAL_CALL and an external call interrupt
+            is already pending
+
+Allows to inject an interrupt to the guest.
+
+Using struct kvm_s390_irq as a parameter allows
+to inject additional payload which is not
+possible via KVM_S390_INTERRUPT.
+
+Interrupt parameters are passed via kvm_s390_irq:
+
+struct kvm_s390_irq {
+       __u64 type;
+       union {
+               struct kvm_s390_io_info io;
+               struct kvm_s390_ext_info ext;
+               struct kvm_s390_pgm_info pgm;
+               struct kvm_s390_emerg_info emerg;
+               struct kvm_s390_extcall_info extcall;
+               struct kvm_s390_prefix_info prefix;
+               struct kvm_s390_stop_info stop;
+               struct kvm_s390_mchk_info mchk;
+               char reserved[64];
+       } u;
+};
+
+type can be one of the following:
+
+KVM_S390_SIGP_STOP - sigp stop; parameter in .stop
+KVM_S390_PROGRAM_INT - program check; parameters in .pgm
+KVM_S390_SIGP_SET_PREFIX - sigp set prefix; parameters in .prefix
+KVM_S390_RESTART - restart; no parameters
+KVM_S390_INT_CLOCK_COMP - clock comparator interrupt; no parameters
+KVM_S390_INT_CPU_TIMER - CPU timer interrupt; no parameters
+KVM_S390_INT_EMERGENCY - sigp emergency; parameters in .emerg
+KVM_S390_INT_EXTERNAL_CALL - sigp external call; parameters in .extcall
+KVM_S390_MCHK - machine check interrupt; parameters in .mchk
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
+4.94 KVM_S390_GET_IRQ_STATE
+
+Capability: KVM_CAP_S390_IRQ_STATE
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq_state (out)
+Returns: >= number of bytes copied into buffer,
+         -EINVAL if buffer size is 0,
+         -ENOBUFS if buffer size is too small to fit all pending interrupts,
+         -EFAULT if the buffer address was invalid
+
+This ioctl allows userspace to retrieve the complete state of all currently
+pending interrupts in a single buffer. Use cases include migration
+and introspection. The parameter structure contains the address of a
+userspace buffer and its length:
+
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 flags;        /* will stay unused for compatibility reasons */
+       __u32 len;
+       __u32 reserved[4];  /* will stay unused for compatibility reasons */
+};
+
+Userspace passes in the above struct and for each pending interrupt a
+struct kvm_s390_irq is copied to the provided buffer.
+
+The structure contains a flags and a reserved field for future extensions. As
+the kernel never checked for flags == 0 and QEMU never pre-zeroed flags and
+reserved, these fields can not be used in the future without breaking
+compatibility.
+
+If -ENOBUFS is returned the buffer provided was too small and userspace
+may retry with a bigger buffer.
+
+4.95 KVM_S390_SET_IRQ_STATE
+
+Capability: KVM_CAP_S390_IRQ_STATE
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq_state (in)
+Returns: 0 on success,
+         -EFAULT if the buffer address was invalid,
+         -EINVAL for an invalid buffer length (see below),
+         -EBUSY if there were already interrupts pending,
+         errors occurring when actually injecting the
+          interrupt. See KVM_S390_IRQ.
+
+This ioctl allows userspace to set the complete state of all cpu-local
+interrupts currently pending for the vcpu. It is intended for restoring
+interrupt state after a migration. The input parameter is a userspace buffer
+containing a struct kvm_s390_irq_state:
+
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 flags;        /* will stay unused for compatibility reasons */
+       __u32 len;
+       __u32 reserved[4];  /* will stay unused for compatibility reasons */
+};
+
+The restrictions for flags and reserved apply as well.
+(see KVM_S390_GET_IRQ_STATE)
+
+The userspace memory referenced by buf contains a struct kvm_s390_irq
+for each interrupt to be injected into the guest.
+If one of the interrupts could not be injected for some reason the
+ioctl aborts.
+
+len must be a multiple of sizeof(struct kvm_s390_irq). It must be > 0
+and it must not exceed (max_vcpus + 32) * sizeof(struct kvm_s390_irq),
+which is the maximum number of possibly pending cpu-local interrupts.
+
+4.96 KVM_SMI
+
+Capability: KVM_CAP_X86_SMM
+Architectures: x86
+Type: vcpu ioctl
+Parameters: none
+Returns: 0 on success, -1 on error
+
+Queues an SMI on the thread's vcpu.
+
+4.97 KVM_CAP_PPC_MULTITCE
+
+Capability: KVM_CAP_PPC_MULTITCE
+Architectures: ppc
+Type: vm
+
+This capability means the kernel is capable of handling hypercalls
+H_PUT_TCE_INDIRECT and H_STUFF_TCE without passing those into the user
+space. This significantly accelerates DMA operations for PPC KVM guests.
+User space should expect that its handlers for these hypercalls
+are not going to be called if user space previously registered LIOBN
+in KVM (via KVM_CREATE_SPAPR_TCE or similar calls).
+
+In order to enable H_PUT_TCE_INDIRECT and H_STUFF_TCE use in the guest,
+user space might have to advertise it for the guest. For example,
+IBM pSeries (sPAPR) guest starts using them if "hcall-multi-tce" is
+present in the "ibm,hypertas-functions" device-tree property.
+
+The hypercalls mentioned above may or may not be processed successfully
+in the kernel based fast path. If they can not be handled by the kernel,
+they will get passed on to user space. So user space still has to have
+an implementation for these despite the in kernel acceleration.
+
+This capability is always enabled.
+
+4.98 KVM_CREATE_SPAPR_TCE_64
+
+Capability: KVM_CAP_SPAPR_TCE_64
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_create_spapr_tce_64 (in)
+Returns: file descriptor for manipulating the created TCE table
+
+This is an extension for KVM_CAP_SPAPR_TCE which only supports 32bit
+windows, described in 4.62 KVM_CREATE_SPAPR_TCE
+
+This capability uses extended struct in ioctl interface:
+
+/* for KVM_CAP_SPAPR_TCE_64 */
+struct kvm_create_spapr_tce_64 {
+       __u64 liobn;
+       __u32 page_shift;
+       __u32 flags;
+       __u64 offset;   /* in pages */
+       __u64 size;     /* in pages */
+};
+
+The aim of extension is to support an additional bigger DMA window with
+a variable page size.
+KVM_CREATE_SPAPR_TCE_64 receives a 64bit window size, an IOMMU page shift and
+a bus offset of the corresponding DMA window, @size and @offset are numbers
+of IOMMU pages.
+
+@flags are not used at the moment.
+
+The rest of functionality is identical to KVM_CREATE_SPAPR_TCE.
+
+4.99 KVM_REINJECT_CONTROL
+
+Capability: KVM_CAP_REINJECT_CONTROL
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_reinject_control (in)
+Returns: 0 on success,
+         -EFAULT if struct kvm_reinject_control cannot be read,
+         -ENXIO if KVM_CREATE_PIT or KVM_CREATE_PIT2 didn't succeed earlier.
+
+i8254 (PIT) has two modes, reinject and !reinject.  The default is reinject,
+where KVM queues elapsed i8254 ticks and monitors completion of interrupt from
+vector(s) that i8254 injects.  Reinject mode dequeues a tick and injects its
+interrupt whenever there isn't a pending interrupt from i8254.
+!reinject mode injects an interrupt as soon as a tick arrives.
+
+struct kvm_reinject_control {
+       __u8 pit_reinject;
+       __u8 reserved[31];
+};
+
+pit_reinject = 0 (!reinject mode) is recommended, unless running an old
+operating system that uses the PIT for timing (e.g. Linux 2.4.x).
+
+4.100 KVM_PPC_CONFIGURE_V3_MMU
+
+Capability: KVM_CAP_PPC_RADIX_MMU or KVM_CAP_PPC_HASH_MMU_V3
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_ppc_mmuv3_cfg (in)
+Returns: 0 on success,
+         -EFAULT if struct kvm_ppc_mmuv3_cfg cannot be read,
+         -EINVAL if the configuration is invalid
+
+This ioctl controls whether the guest will use radix or HPT (hashed
+page table) translation, and sets the pointer to the process table for
+the guest.
+
+struct kvm_ppc_mmuv3_cfg {
+       __u64   flags;
+       __u64   process_table;
+};
+
+There are two bits that can be set in flags; KVM_PPC_MMUV3_RADIX and
+KVM_PPC_MMUV3_GTSE.  KVM_PPC_MMUV3_RADIX, if set, configures the guest
+to use radix tree translation, and if clear, to use HPT translation.
+KVM_PPC_MMUV3_GTSE, if set and if KVM permits it, configures the guest
+to be able to use the global TLB and SLB invalidation instructions;
+if clear, the guest may not use these instructions.
+
+The process_table field specifies the address and size of the guest
+process table, which is in the guest's space.  This field is formatted
+as the second doubleword of the partition table entry, as defined in
+the Power ISA V3.00, Book III section 5.7.6.1.
+
+4.101 KVM_PPC_GET_RMMU_INFO
+
+Capability: KVM_CAP_PPC_RADIX_MMU
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_ppc_rmmu_info (out)
+Returns: 0 on success,
+        -EFAULT if struct kvm_ppc_rmmu_info cannot be written,
+        -EINVAL if no useful information can be returned
+
+This ioctl returns a structure containing two things: (a) a list
+containing supported radix tree geometries, and (b) a list that maps
+page sizes to put in the "AP" (actual page size) field for the tlbie
+(TLB invalidate entry) instruction.
+
+struct kvm_ppc_rmmu_info {
+       struct kvm_ppc_radix_geom {
+               __u8    page_shift;
+               __u8    level_bits[4];
+               __u8    pad[3];
+       }       geometries[8];
+       __u32   ap_encodings[8];
+};
+
+The geometries[] field gives up to 8 supported geometries for the
+radix page table, in terms of the log base 2 of the smallest page
+size, and the number of bits indexed at each level of the tree, from
+the PTE level up to the PGD level in that order.  Any unused entries
+will have 0 in the page_shift field.
+
+The ap_encodings gives the supported page sizes and their AP field
+encodings, encoded with the AP value in the top 3 bits and the log
+base 2 of the page size in the bottom 6 bits.
+
+4.102 KVM_PPC_RESIZE_HPT_PREPARE
+
+Capability: KVM_CAP_SPAPR_RESIZE_HPT
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_ppc_resize_hpt (in)
+Returns: 0 on successful completion,
+        >0 if a new HPT is being prepared, the value is an estimated
+             number of milliseconds until preparation is complete
+         -EFAULT if struct kvm_reinject_control cannot be read,
+        -EINVAL if the supplied shift or flags are invalid
+        -ENOMEM if unable to allocate the new HPT
+        -ENOSPC if there was a hash collision when moving existing
+                  HPT entries to the new HPT
+        -EIO on other error conditions
+
+Used to implement the PAPR extension for runtime resizing of a guest's
+Hashed Page Table (HPT).  Specifically this starts, stops or monitors
+the preparation of a new potential HPT for the guest, essentially
+implementing the H_RESIZE_HPT_PREPARE hypercall.
+
+If called with shift > 0 when there is no pending HPT for the guest,
+this begins preparation of a new pending HPT of size 2^(shift) bytes.
+It then returns a positive integer with the estimated number of
+milliseconds until preparation is complete.
+
+If called when there is a pending HPT whose size does not match that
+requested in the parameters, discards the existing pending HPT and
+creates a new one as above.
+
+If called when there is a pending HPT of the size requested, will:
+  * If preparation of the pending HPT is already complete, return 0
+  * If preparation of the pending HPT has failed, return an error
+    code, then discard the pending HPT.
+  * If preparation of the pending HPT is still in progress, return an
+    estimated number of milliseconds until preparation is complete.
+
+If called with shift == 0, discards any currently pending HPT and
+returns 0 (i.e. cancels any in-progress preparation).
+
+flags is reserved for future expansion, currently setting any bits in
+flags will result in an -EINVAL.
+
+Normally this will be called repeatedly with the same parameters until
+it returns <= 0.  The first call will initiate preparation, subsequent
+ones will monitor preparation until it completes or fails.
+
+struct kvm_ppc_resize_hpt {
+       __u64 flags;
+       __u32 shift;
+       __u32 pad;
+};
+
+4.103 KVM_PPC_RESIZE_HPT_COMMIT
+
+Capability: KVM_CAP_SPAPR_RESIZE_HPT
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_ppc_resize_hpt (in)
+Returns: 0 on successful completion,
+         -EFAULT if struct kvm_reinject_control cannot be read,
+        -EINVAL if the supplied shift or flags are invalid
+        -ENXIO is there is no pending HPT, or the pending HPT doesn't
+                 have the requested size
+        -EBUSY if the pending HPT is not fully prepared
+        -ENOSPC if there was a hash collision when moving existing
+                  HPT entries to the new HPT
+        -EIO on other error conditions
+
+Used to implement the PAPR extension for runtime resizing of a guest's
+Hashed Page Table (HPT).  Specifically this requests that the guest be
+transferred to working with the new HPT, essentially implementing the
+H_RESIZE_HPT_COMMIT hypercall.
+
+This should only be called after KVM_PPC_RESIZE_HPT_PREPARE has
+returned 0 with the same parameters.  In other cases
+KVM_PPC_RESIZE_HPT_COMMIT will return an error (usually -ENXIO or
+-EBUSY, though others may be possible if the preparation was started,
+but failed).
+
+This will have undefined effects on the guest if it has not already
+placed itself in a quiescent state where no vcpu will make MMU enabled
+memory accesses.
+
+On succsful completion, the pending HPT will become the guest's active
+HPT and the previous HPT will be discarded.
+
+On failure, the guest will still be operating on its previous HPT.
+
+struct kvm_ppc_resize_hpt {
+       __u64 flags;
+       __u32 shift;
+       __u32 pad;
+};
+
+4.104 KVM_X86_GET_MCE_CAP_SUPPORTED
+
+Capability: KVM_CAP_MCE
+Architectures: x86
+Type: system ioctl
+Parameters: u64 mce_cap (out)
+Returns: 0 on success, -1 on error
+
+Returns supported MCE capabilities. The u64 mce_cap parameter
+has the same format as the MSR_IA32_MCG_CAP register. Supported
+capabilities will have the corresponding bits set.
+
+4.105 KVM_X86_SETUP_MCE
+
+Capability: KVM_CAP_MCE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: u64 mcg_cap (in)
+Returns: 0 on success,
+         -EFAULT if u64 mcg_cap cannot be read,
+         -EINVAL if the requested number of banks is invalid,
+         -EINVAL if requested MCE capability is not supported.
+
+Initializes MCE support for use. The u64 mcg_cap parameter
+has the same format as the MSR_IA32_MCG_CAP register and
+specifies which capabilities should be enabled. The maximum
+supported number of error-reporting banks can be retrieved when
+checking for KVM_CAP_MCE. The supported capabilities can be
+retrieved with KVM_X86_GET_MCE_CAP_SUPPORTED.
+
+4.106 KVM_X86_SET_MCE
+
+Capability: KVM_CAP_MCE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_x86_mce (in)
+Returns: 0 on success,
+         -EFAULT if struct kvm_x86_mce cannot be read,
+         -EINVAL if the bank number is invalid,
+         -EINVAL if VAL bit is not set in status field.
+
+Inject a machine check error (MCE) into the guest. The input
+parameter is:
+
+struct kvm_x86_mce {
+       __u64 status;
+       __u64 addr;
+       __u64 misc;
+       __u64 mcg_status;
+       __u8 bank;
+       __u8 pad1[7];
+       __u64 pad2[3];
+};
+
+If the MCE being reported is an uncorrected error, KVM will
+inject it as an MCE exception into the guest. If the guest
+MCG_STATUS register reports that an MCE is in progress, KVM
+causes an KVM_EXIT_SHUTDOWN vmexit.
+
+Otherwise, if the MCE is a corrected error, KVM will just
+store it in the corresponding bank (provided this bank is
+not holding a previously reported uncorrected error).
+
+4.107 KVM_S390_GET_CMMA_BITS
+
+Capability: KVM_CAP_S390_CMMA_MIGRATION
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_cmma_log (in, out)
+Returns: 0 on success, a negative value on error
+
+This ioctl is used to get the values of the CMMA bits on the s390
+architecture. It is meant to be used in two scenarios:
+- During live migration to save the CMMA values. Live migration needs
+  to be enabled via the KVM_REQ_START_MIGRATION VM property.
+- To non-destructively peek at the CMMA values, with the flag
+  KVM_S390_CMMA_PEEK set.
+
+The ioctl takes parameters via the kvm_s390_cmma_log struct. The desired
+values are written to a buffer whose location is indicated via the "values"
+member in the kvm_s390_cmma_log struct.  The values in the input struct are
+also updated as needed.
+Each CMMA value takes up one byte.
+
+struct kvm_s390_cmma_log {
+       __u64 start_gfn;
+       __u32 count;
+       __u32 flags;
+       union {
+               __u64 remaining;
+               __u64 mask;
+       };
+       __u64 values;
+};
+
+start_gfn is the number of the first guest frame whose CMMA values are
+to be retrieved,
+
+count is the length of the buffer in bytes,
+
+values points to the buffer where the result will be written to.
+
+If count is greater than KVM_S390_SKEYS_MAX, then it is considered to be
+KVM_S390_SKEYS_MAX. KVM_S390_SKEYS_MAX is re-used for consistency with
+other ioctls.
+
+The result is written in the buffer pointed to by the field values, and
+the values of the input parameter are updated as follows.
+
+Depending on the flags, different actions are performed. The only
+supported flag so far is KVM_S390_CMMA_PEEK.
+
+The default behaviour if KVM_S390_CMMA_PEEK is not set is:
+start_gfn will indicate the first page frame whose CMMA bits were dirty.
+It is not necessarily the same as the one passed as input, as clean pages
+are skipped.
+
+count will indicate the number of bytes actually written in the buffer.
+It can (and very often will) be smaller than the input value, since the
+buffer is only filled until 16 bytes of clean values are found (which
+are then not copied in the buffer). Since a CMMA migration block needs
+the base address and the length, for a total of 16 bytes, we will send
+back some clean data if there is some dirty data afterwards, as long as
+the size of the clean data does not exceed the size of the header. This
+allows to minimize the amount of data to be saved or transferred over
+the network at the expense of more roundtrips to userspace. The next
+invocation of the ioctl will skip over all the clean values, saving
+potentially more than just the 16 bytes we found.
+
+If KVM_S390_CMMA_PEEK is set:
+the existing storage attributes are read even when not in migration
+mode, and no other action is performed;
+
+the output start_gfn will be equal to the input start_gfn,
+
+the output count will be equal to the input count, except if the end of
+memory has been reached.
+
+In both cases:
+the field "remaining" will indicate the total number of dirty CMMA values
+still remaining, or 0 if KVM_S390_CMMA_PEEK is set and migration mode is
+not enabled.
+
+mask is unused.
+
+values points to the userspace buffer where the result will be stored.
+
+This ioctl can fail with -ENOMEM if not enough memory can be allocated to
+complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
+KVM_S390_CMMA_PEEK is not set but migration mode was not enabled, with
+-EFAULT if the userspace address is invalid or if no page table is
+present for the addresses (e.g. when using hugepages).
+
+4.108 KVM_S390_SET_CMMA_BITS
+
+Capability: KVM_CAP_S390_CMMA_MIGRATION
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_cmma_log (in)
+Returns: 0 on success, a negative value on error
+
+This ioctl is used to set the values of the CMMA bits on the s390
+architecture. It is meant to be used during live migration to restore
+the CMMA values, but there are no restrictions on its use.
+The ioctl takes parameters via the kvm_s390_cmma_values struct.
+Each CMMA value takes up one byte.
+
+struct kvm_s390_cmma_log {
+       __u64 start_gfn;
+       __u32 count;
+       __u32 flags;
+       union {
+               __u64 remaining;
+               __u64 mask;
+       };
+       __u64 values;
+};
+
+start_gfn indicates the starting guest frame number,
+
+count indicates how many values are to be considered in the buffer,
+
+flags is not used and must be 0.
+
+mask indicates which PGSTE bits are to be considered.
+
+remaining is not used.
+
+values points to the buffer in userspace where to store the values.
+
+This ioctl can fail with -ENOMEM if not enough memory can be allocated to
+complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
+the count field is too large (e.g. more than KVM_S390_CMMA_SIZE_MAX) or
+if the flags field was not 0, with -EFAULT if the userspace address is
+invalid, if invalid pages are written to (e.g. after the end of memory)
+or if no page table is present for the addresses (e.g. when using
+hugepages).
+
+4.109 KVM_PPC_GET_CPU_CHAR
+
+Capability: KVM_CAP_PPC_GET_CPU_CHAR
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_ppc_cpu_char (out)
+Returns: 0 on successful completion
+        -EFAULT if struct kvm_ppc_cpu_char cannot be written
+
+This ioctl gives userspace information about certain characteristics
+of the CPU relating to speculative execution of instructions and
+possible information leakage resulting from speculative execution (see
+CVE-2017-5715, CVE-2017-5753 and CVE-2017-5754).  The information is
+returned in struct kvm_ppc_cpu_char, which looks like this:
+
+struct kvm_ppc_cpu_char {
+       __u64   character;              /* characteristics of the CPU */
+       __u64   behaviour;              /* recommended software behaviour */
+       __u64   character_mask;         /* valid bits in character */
+       __u64   behaviour_mask;         /* valid bits in behaviour */
+};
+
+For extensibility, the character_mask and behaviour_mask fields
+indicate which bits of character and behaviour have been filled in by
+the kernel.  If the set of defined bits is extended in future then
+userspace will be able to tell whether it is running on a kernel that
+knows about the new bits.
+
+The character field describes attributes of the CPU which can help
+with preventing inadvertent information disclosure - specifically,
+whether there is an instruction to flash-invalidate the L1 data cache
+(ori 30,30,0 or mtspr SPRN_TRIG2,rN), whether the L1 data cache is set
+to a mode where entries can only be used by the thread that created
+them, whether the bcctr[l] instruction prevents speculation, and
+whether a speculation barrier instruction (ori 31,31,0) is provided.
+
+The behaviour field describes actions that software should take to
+prevent inadvertent information disclosure, and thus describes which
+vulnerabilities the hardware is subject to; specifically whether the
+L1 data cache should be flushed when returning to user mode from the
+kernel, and whether a speculation barrier should be placed between an
+array bounds check and the array access.
+
+These fields use the same bit definitions as the new
+H_GET_CPU_CHARACTERISTICS hypercall.
+
+4.110 KVM_MEMORY_ENCRYPT_OP
+
+Capability: basic
+Architectures: x86
+Type: system
+Parameters: an opaque platform specific structure (in/out)
+Returns: 0 on success; -1 on error
+
+If the platform supports creating encrypted VMs then this ioctl can be used
+for issuing platform-specific memory encryption commands to manage those
+encrypted VMs.
+
+Currently, this ioctl is used for issuing Secure Encrypted Virtualization
+(SEV) commands on AMD Processors. The SEV commands are defined in
+Documentation/virt/kvm/amd-memory-encryption.rst.
+
+4.111 KVM_MEMORY_ENCRYPT_REG_REGION
+
+Capability: basic
+Architectures: x86
+Type: system
+Parameters: struct kvm_enc_region (in)
+Returns: 0 on success; -1 on error
+
+This ioctl can be used to register a guest memory region which may
+contain encrypted data (e.g. guest RAM, SMRAM etc).
+
+It is used in the SEV-enabled guest. When encryption is enabled, a guest
+memory region may contain encrypted data. The SEV memory encryption
+engine uses a tweak such that two identical plaintext pages, each at
+different locations will have differing ciphertexts. So swapping or
+moving ciphertext of those pages will not result in plaintext being
+swapped. So relocating (or migrating) physical backing pages for the SEV
+guest will require some additional steps.
+
+Note: The current SEV key management spec does not provide commands to
+swap or migrate (move) ciphertext pages. Hence, for now we pin the guest
+memory region registered with the ioctl.
+
+4.112 KVM_MEMORY_ENCRYPT_UNREG_REGION
+
+Capability: basic
+Architectures: x86
+Type: system
+Parameters: struct kvm_enc_region (in)
+Returns: 0 on success; -1 on error
+
+This ioctl can be used to unregister the guest memory region registered
+with KVM_MEMORY_ENCRYPT_REG_REGION ioctl above.
+
+4.113 KVM_HYPERV_EVENTFD
+
+Capability: KVM_CAP_HYPERV_EVENTFD
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_hyperv_eventfd (in)
+
+This ioctl (un)registers an eventfd to receive notifications from the guest on
+the specified Hyper-V connection id through the SIGNAL_EVENT hypercall, without
+causing a user exit.  SIGNAL_EVENT hypercall with non-zero event flag number
+(bits 24-31) still triggers a KVM_EXIT_HYPERV_HCALL user exit.
+
+struct kvm_hyperv_eventfd {
+       __u32 conn_id;
+       __s32 fd;
+       __u32 flags;
+       __u32 padding[3];
+};
+
+The conn_id field should fit within 24 bits:
+
+#define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
+
+The acceptable values for the flags field are:
+
+#define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
+
+Returns: 0 on success,
+       -EINVAL if conn_id or flags is outside the allowed range
+       -ENOENT on deassign if the conn_id isn't registered
+       -EEXIST on assign if the conn_id is already registered
+
+4.114 KVM_GET_NESTED_STATE
+
+Capability: KVM_CAP_NESTED_STATE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_nested_state (in/out)
+Returns: 0 on success, -1 on error
+Errors:
+  E2BIG:     the total state size exceeds the value of 'size' specified by
+             the user; the size required will be written into size.
+
+struct kvm_nested_state {
+       __u16 flags;
+       __u16 format;
+       __u32 size;
+
+       union {
+               struct kvm_vmx_nested_state_hdr vmx;
+               struct kvm_svm_nested_state_hdr svm;
+
+               /* Pad the header to 128 bytes.  */
+               __u8 pad[120];
+       } hdr;
+
+       union {
+               struct kvm_vmx_nested_state_data vmx[0];
+               struct kvm_svm_nested_state_data svm[0];
+       } data;
+};
+
+#define KVM_STATE_NESTED_GUEST_MODE    0x00000001
+#define KVM_STATE_NESTED_RUN_PENDING   0x00000002
+#define KVM_STATE_NESTED_EVMCS         0x00000004
+
+#define KVM_STATE_NESTED_FORMAT_VMX            0
+#define KVM_STATE_NESTED_FORMAT_SVM            1
+
+#define KVM_STATE_NESTED_VMX_VMCS_SIZE         0x1000
+
+#define KVM_STATE_NESTED_VMX_SMM_GUEST_MODE    0x00000001
+#define KVM_STATE_NESTED_VMX_SMM_VMXON         0x00000002
+
+struct kvm_vmx_nested_state_hdr {
+       __u64 vmxon_pa;
+       __u64 vmcs12_pa;
+
+       struct {
+               __u16 flags;
+       } smm;
+};
+
+struct kvm_vmx_nested_state_data {
+       __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
+       __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
+};
+
+This ioctl copies the vcpu's nested virtualization state from the kernel to
+userspace.
+
+The maximum size of the state can be retrieved by passing KVM_CAP_NESTED_STATE
+to the KVM_CHECK_EXTENSION ioctl().
+
+4.115 KVM_SET_NESTED_STATE
+
+Capability: KVM_CAP_NESTED_STATE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_nested_state (in)
+Returns: 0 on success, -1 on error
+
+This copies the vcpu's kvm_nested_state struct from userspace to the kernel.
+For the definition of struct kvm_nested_state, see KVM_GET_NESTED_STATE.
+
+4.116 KVM_(UN)REGISTER_COALESCED_MMIO
+
+Capability: KVM_CAP_COALESCED_MMIO (for coalesced mmio)
+           KVM_CAP_COALESCED_PIO (for coalesced pio)
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_coalesced_mmio_zone
+Returns: 0 on success, < 0 on error
+
+Coalesced I/O is a performance optimization that defers hardware
+register write emulation so that userspace exits are avoided.  It is
+typically used to reduce the overhead of emulating frequently accessed
+hardware registers.
+
+When a hardware register is configured for coalesced I/O, write accesses
+do not exit to userspace and their value is recorded in a ring buffer
+that is shared between kernel and userspace.
+
+Coalesced I/O is used if one or more write accesses to a hardware
+register can be deferred until a read or a write to another hardware
+register on the same device.  This last access will cause a vmexit and
+userspace will process accesses from the ring buffer before emulating
+it. That will avoid exiting to userspace on repeated writes.
+
+Coalesced pio is based on coalesced mmio. There is little difference
+between coalesced mmio and pio except that coalesced pio records accesses
+to I/O ports.
+
+4.117 KVM_CLEAR_DIRTY_LOG (vm ioctl)
+
+Capability: KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
+Architectures: x86, arm, arm64, mips
+Type: vm ioctl
+Parameters: struct kvm_dirty_log (in)
+Returns: 0 on success, -1 on error
+
+/* for KVM_CLEAR_DIRTY_LOG */
+struct kvm_clear_dirty_log {
+       __u32 slot;
+       __u32 num_pages;
+       __u64 first_page;
+       union {
+               void __user *dirty_bitmap; /* one bit per page */
+               __u64 padding;
+       };
+};
+
+The ioctl clears the dirty status of pages in a memory slot, according to
+the bitmap that is passed in struct kvm_clear_dirty_log's dirty_bitmap
+field.  Bit 0 of the bitmap corresponds to page "first_page" in the
+memory slot, and num_pages is the size in bits of the input bitmap.
+first_page must be a multiple of 64; num_pages must also be a multiple of
+64 unless first_page + num_pages is the size of the memory slot.  For each
+bit that is set in the input bitmap, the corresponding page is marked "clean"
+in KVM's dirty bitmap, and dirty tracking is re-enabled for that page
+(for example via write-protection, or by clearing the dirty bit in
+a page table entry).
+
+If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 specifies
+the address space for which you want to return the dirty bitmap.
+They must be less than the value that KVM_CHECK_EXTENSION returns for
+the KVM_CAP_MULTI_ADDRESS_SPACE capability.
+
+This ioctl is mostly useful when KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
+is enabled; for more information, see the description of the capability.
+However, it can always be used as long as KVM_CHECK_EXTENSION confirms
+that KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is present.
+
+4.118 KVM_GET_SUPPORTED_HV_CPUID
+
+Capability: KVM_CAP_HYPERV_CPUID
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_cpuid2 (in/out)
+Returns: 0 on success, -1 on error
+
+struct kvm_cpuid2 {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry2 entries[0];
+};
+
+struct kvm_cpuid_entry2 {
+       __u32 function;
+       __u32 index;
+       __u32 flags;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding[3];
+};
+
+This ioctl returns x86 cpuid features leaves related to Hyper-V emulation in
+KVM.  Userspace can use the information returned by this ioctl to construct
+cpuid information presented to guests consuming Hyper-V enlightenments (e.g.
+Windows or Hyper-V guests).
+
+CPUID feature leaves returned by this ioctl are defined by Hyper-V Top Level
+Functional Specification (TLFS). These leaves can't be obtained with
+KVM_GET_SUPPORTED_CPUID ioctl because some of them intersect with KVM feature
+leaves (0x40000000, 0x40000001).
+
+Currently, the following list of CPUID leaves are returned:
+ HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS
+ HYPERV_CPUID_INTERFACE
+ HYPERV_CPUID_VERSION
+ HYPERV_CPUID_FEATURES
+ HYPERV_CPUID_ENLIGHTMENT_INFO
+ HYPERV_CPUID_IMPLEMENT_LIMITS
+ HYPERV_CPUID_NESTED_FEATURES
+
+HYPERV_CPUID_NESTED_FEATURES leaf is only exposed when Enlightened VMCS was
+enabled on the corresponding vCPU (KVM_CAP_HYPERV_ENLIGHTENED_VMCS).
+
+Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
+with the 'nent' field indicating the number of entries in the variable-size
+array 'entries'.  If the number of entries is too low to describe all Hyper-V
+feature leaves, an error (E2BIG) is returned. If the number is more or equal
+to the number of Hyper-V feature leaves, the 'nent' field is adjusted to the
+number of valid entries in the 'entries' array, which is then filled.
+
+'index' and 'flags' fields in 'struct kvm_cpuid_entry2' are currently reserved,
+userspace should not expect to get any particular value there.
+
+4.119 KVM_ARM_VCPU_FINALIZE
+
+Architectures: arm, arm64
+Type: vcpu ioctl
+Parameters: int feature (in)
+Returns: 0 on success, -1 on error
+Errors:
+  EPERM:     feature not enabled, needs configuration, or already finalized
+  EINVAL:    feature unknown or not present
+
+Recognised values for feature:
+  arm64      KVM_ARM_VCPU_SVE (requires KVM_CAP_ARM_SVE)
+
+Finalizes the configuration of the specified vcpu feature.
+
+The vcpu must already have been initialised, enabling the affected feature, by
+means of a successful KVM_ARM_VCPU_INIT call with the appropriate flag set in
+features[].
+
+For affected vcpu features, this is a mandatory step that must be performed
+before the vcpu is fully usable.
+
+Between KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE, the feature may be
+configured by use of ioctls such as KVM_SET_ONE_REG.  The exact configuration
+that should be performaned and how to do it are feature-dependent.
+
+Other calls that depend on a particular feature being finalized, such as
+KVM_RUN, KVM_GET_REG_LIST, KVM_GET_ONE_REG and KVM_SET_ONE_REG, will fail with
+-EPERM unless the feature has already been finalized by means of a
+KVM_ARM_VCPU_FINALIZE call.
+
+See KVM_ARM_VCPU_INIT for details of vcpu features that require finalization
+using this ioctl.
+
+4.120 KVM_SET_PMU_EVENT_FILTER
+
+Capability: KVM_CAP_PMU_EVENT_FILTER
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_pmu_event_filter (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_pmu_event_filter {
+       __u32 action;
+       __u32 nevents;
+       __u32 fixed_counter_bitmap;
+       __u32 flags;
+       __u32 pad[4];
+       __u64 events[0];
+};
+
+This ioctl restricts the set of PMU events that the guest can program.
+The argument holds a list of events which will be allowed or denied.
+The eventsel+umask of each event the guest attempts to program is compared
+against the events field to determine whether the guest should have access.
+The events field only controls general purpose counters; fixed purpose
+counters are controlled by the fixed_counter_bitmap.
+
+No flags are defined yet, the field must be zero.
+
+Valid values for 'action':
+#define KVM_PMU_EVENT_ALLOW 0
+#define KVM_PMU_EVENT_DENY 1
+
+
+5. The kvm_run structure
+------------------------
+
+Application code obtains a pointer to the kvm_run structure by
+mmap()ing a vcpu fd.  From that point, application code can control
+execution by changing fields in kvm_run prior to calling the KVM_RUN
+ioctl, and obtain information about the reason KVM_RUN returned by
+looking up structure members.
+
+struct kvm_run {
+       /* in */
+       __u8 request_interrupt_window;
+
+Request that KVM_RUN return when it becomes possible to inject external
+interrupts into the guest.  Useful in conjunction with KVM_INTERRUPT.
+
+       __u8 immediate_exit;
+
+This field is polled once when KVM_RUN starts; if non-zero, KVM_RUN
+exits immediately, returning -EINTR.  In the common scenario where a
+signal is used to "kick" a VCPU out of KVM_RUN, this field can be used
+to avoid usage of KVM_SET_SIGNAL_MASK, which has worse scalability.
+Rather than blocking the signal outside KVM_RUN, userspace can set up
+a signal handler that sets run->immediate_exit to a non-zero value.
+
+This field is ignored if KVM_CAP_IMMEDIATE_EXIT is not available.
+
+       __u8 padding1[6];
+
+       /* out */
+       __u32 exit_reason;
+
+When KVM_RUN has returned successfully (return value 0), this informs
+application code why KVM_RUN has returned.  Allowable values for this
+field are detailed below.
+
+       __u8 ready_for_interrupt_injection;
+
+If request_interrupt_window has been specified, this field indicates
+an interrupt can be injected now with KVM_INTERRUPT.
+
+       __u8 if_flag;
+
+The value of the current interrupt flag.  Only valid if in-kernel
+local APIC is not used.
+
+       __u16 flags;
+
+More architecture-specific flags detailing state of the VCPU that may
+affect the device's behavior.  The only currently defined flag is
+KVM_RUN_X86_SMM, which is valid on x86 machines and is set if the
+VCPU is in system management mode.
+
+       /* in (pre_kvm_run), out (post_kvm_run) */
+       __u64 cr8;
+
+The value of the cr8 register.  Only valid if in-kernel local APIC is
+not used.  Both input and output.
+
+       __u64 apic_base;
+
+The value of the APIC BASE msr.  Only valid if in-kernel local
+APIC is not used.  Both input and output.
+
+       union {
+               /* KVM_EXIT_UNKNOWN */
+               struct {
+                       __u64 hardware_exit_reason;
+               } hw;
+
+If exit_reason is KVM_EXIT_UNKNOWN, the vcpu has exited due to unknown
+reasons.  Further architecture-specific information is available in
+hardware_exit_reason.
+
+               /* KVM_EXIT_FAIL_ENTRY */
+               struct {
+                       __u64 hardware_entry_failure_reason;
+               } fail_entry;
+
+If exit_reason is KVM_EXIT_FAIL_ENTRY, the vcpu could not be run due
+to unknown reasons.  Further architecture-specific information is
+available in hardware_entry_failure_reason.
+
+               /* KVM_EXIT_EXCEPTION */
+               struct {
+                       __u32 exception;
+                       __u32 error_code;
+               } ex;
+
+Unused.
+
+               /* KVM_EXIT_IO */
+               struct {
+#define KVM_EXIT_IO_IN  0
+#define KVM_EXIT_IO_OUT 1
+                       __u8 direction;
+                       __u8 size; /* bytes */
+                       __u16 port;
+                       __u32 count;
+                       __u64 data_offset; /* relative to kvm_run start */
+               } io;
+
+If exit_reason is KVM_EXIT_IO, then the vcpu has
+executed a port I/O instruction which could not be satisfied by kvm.
+data_offset describes where the data is located (KVM_EXIT_IO_OUT) or
+where kvm expects application code to place the data for the next
+KVM_RUN invocation (KVM_EXIT_IO_IN).  Data format is a packed array.
+
+               /* KVM_EXIT_DEBUG */
+               struct {
+                       struct kvm_debug_exit_arch arch;
+               } debug;
+
+If the exit_reason is KVM_EXIT_DEBUG, then a vcpu is processing a debug event
+for which architecture specific information is returned.
+
+               /* KVM_EXIT_MMIO */
+               struct {
+                       __u64 phys_addr;
+                       __u8  data[8];
+                       __u32 len;
+                       __u8  is_write;
+               } mmio;
+
+If exit_reason is KVM_EXIT_MMIO, then the vcpu has
+executed a memory-mapped I/O instruction which could not be satisfied
+by kvm.  The 'data' member contains the written data if 'is_write' is
+true, and should be filled by application code otherwise.
+
+The 'data' member contains, in its first 'len' bytes, the value as it would
+appear if the VCPU performed a load or store of the appropriate width directly
+to the byte array.
+
+NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR and
+      KVM_EXIT_EPR the corresponding
+operations are complete (and guest state is consistent) only after userspace
+has re-entered the kernel with KVM_RUN.  The kernel side will first finish
+incomplete operations and then check for pending signals.  Userspace
+can re-enter the guest with an unmasked signal pending to complete
+pending operations.
+
+               /* KVM_EXIT_HYPERCALL */
+               struct {
+                       __u64 nr;
+                       __u64 args[6];
+                       __u64 ret;
+                       __u32 longmode;
+                       __u32 pad;
+               } hypercall;
+
+Unused.  This was once used for 'hypercall to userspace'.  To implement
+such functionality, use KVM_EXIT_IO (x86) or KVM_EXIT_MMIO (all except s390).
+Note KVM_EXIT_IO is significantly faster than KVM_EXIT_MMIO.
+
+               /* KVM_EXIT_TPR_ACCESS */
+               struct {
+                       __u64 rip;
+                       __u32 is_write;
+                       __u32 pad;
+               } tpr_access;
+
+To be documented (KVM_TPR_ACCESS_REPORTING).
+
+               /* KVM_EXIT_S390_SIEIC */
+               struct {
+                       __u8 icptcode;
+                       __u64 mask; /* psw upper half */
+                       __u64 addr; /* psw lower half */
+                       __u16 ipa;
+                       __u32 ipb;
+               } s390_sieic;
+
+s390 specific.
+
+               /* KVM_EXIT_S390_RESET */
+#define KVM_S390_RESET_POR       1
+#define KVM_S390_RESET_CLEAR     2
+#define KVM_S390_RESET_SUBSYSTEM 4
+#define KVM_S390_RESET_CPU_INIT  8
+#define KVM_S390_RESET_IPL       16
+               __u64 s390_reset_flags;
+
+s390 specific.
+
+               /* KVM_EXIT_S390_UCONTROL */
+               struct {
+                       __u64 trans_exc_code;
+                       __u32 pgm_code;
+               } s390_ucontrol;
+
+s390 specific. A page fault has occurred for a user controlled virtual
+machine (KVM_VM_S390_UNCONTROL) on it's host page table that cannot be
+resolved by the kernel.
+The program code and the translation exception code that were placed
+in the cpu's lowcore are presented here as defined by the z Architecture
+Principles of Operation Book in the Chapter for Dynamic Address Translation
+(DAT)
+
+               /* KVM_EXIT_DCR */
+               struct {
+                       __u32 dcrn;
+                       __u32 data;
+                       __u8  is_write;
+               } dcr;
+
+Deprecated - was used for 440 KVM.
+
+               /* KVM_EXIT_OSI */
+               struct {
+                       __u64 gprs[32];
+               } osi;
+
+MOL uses a special hypercall interface it calls 'OSI'. To enable it, we catch
+hypercalls and exit with this exit struct that contains all the guest gprs.
+
+If exit_reason is KVM_EXIT_OSI, then the vcpu has triggered such a hypercall.
+Userspace can now handle the hypercall and when it's done modify the gprs as
+necessary. Upon guest entry all guest GPRs will then be replaced by the values
+in this struct.
+
+               /* KVM_EXIT_PAPR_HCALL */
+               struct {
+                       __u64 nr;
+                       __u64 ret;
+                       __u64 args[9];
+               } papr_hcall;
+
+This is used on 64-bit PowerPC when emulating a pSeries partition,
+e.g. with the 'pseries' machine type in qemu.  It occurs when the
+guest does a hypercall using the 'sc 1' instruction.  The 'nr' field
+contains the hypercall number (from the guest R3), and 'args' contains
+the arguments (from the guest R4 - R12).  Userspace should put the
+return code in 'ret' and any extra returned values in args[].
+The possible hypercalls are defined in the Power Architecture Platform
+Requirements (PAPR) document available from www.power.org (free
+developer registration required to access it).
+
+               /* KVM_EXIT_S390_TSCH */
+               struct {
+                       __u16 subchannel_id;
+                       __u16 subchannel_nr;
+                       __u32 io_int_parm;
+                       __u32 io_int_word;
+                       __u32 ipb;
+                       __u8 dequeued;
+               } s390_tsch;
+
+s390 specific. This exit occurs when KVM_CAP_S390_CSS_SUPPORT has been enabled
+and TEST SUBCHANNEL was intercepted. If dequeued is set, a pending I/O
+interrupt for the target subchannel has been dequeued and subchannel_id,
+subchannel_nr, io_int_parm and io_int_word contain the parameters for that
+interrupt. ipb is needed for instruction parameter decoding.
+
+               /* KVM_EXIT_EPR */
+               struct {
+                       __u32 epr;
+               } epr;
+
+On FSL BookE PowerPC chips, the interrupt controller has a fast patch
+interrupt acknowledge path to the core. When the core successfully
+delivers an interrupt, it automatically populates the EPR register with
+the interrupt vector number and acknowledges the interrupt inside
+the interrupt controller.
+
+In case the interrupt controller lives in user space, we need to do
+the interrupt acknowledge cycle through it to fetch the next to be
+delivered interrupt vector using this exit.
+
+It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an
+external interrupt has just been delivered into the guest. User space
+should put the acknowledged interrupt vector into the 'epr' field.
+
+               /* KVM_EXIT_SYSTEM_EVENT */
+               struct {
+#define KVM_SYSTEM_EVENT_SHUTDOWN       1
+#define KVM_SYSTEM_EVENT_RESET          2
+#define KVM_SYSTEM_EVENT_CRASH          3
+                       __u32 type;
+                       __u64 flags;
+               } system_event;
+
+If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered
+a system-level event using some architecture specific mechanism (hypercall
+or some special instruction). In case of ARM/ARM64, this is triggered using
+HVC instruction based PSCI call from the vcpu. The 'type' field describes
+the system-level event type. The 'flags' field describes architecture
+specific flags for the system-level event.
+
+Valid values for 'type' are:
+  KVM_SYSTEM_EVENT_SHUTDOWN -- the guest has requested a shutdown of the
+   VM. Userspace is not obliged to honour this, and if it does honour
+   this does not need to destroy the VM synchronously (ie it may call
+   KVM_RUN again before shutdown finally occurs).
+  KVM_SYSTEM_EVENT_RESET -- the guest has requested a reset of the VM.
+   As with SHUTDOWN, userspace can choose to ignore the request, or
+   to schedule the reset to occur in the future and may call KVM_RUN again.
+  KVM_SYSTEM_EVENT_CRASH -- the guest crash occurred and the guest
+   has requested a crash condition maintenance. Userspace can choose
+   to ignore the request, or to gather VM memory core dump and/or
+   reset/shutdown of the VM.
+
+               /* KVM_EXIT_IOAPIC_EOI */
+               struct {
+                       __u8 vector;
+               } eoi;
+
+Indicates that the VCPU's in-kernel local APIC received an EOI for a
+level-triggered IOAPIC interrupt.  This exit only triggers when the
+IOAPIC is implemented in userspace (i.e. KVM_CAP_SPLIT_IRQCHIP is enabled);
+the userspace IOAPIC should process the EOI and retrigger the interrupt if
+it is still asserted.  Vector is the LAPIC interrupt vector for which the
+EOI was received.
+
+               struct kvm_hyperv_exit {
+#define KVM_EXIT_HYPERV_SYNIC          1
+#define KVM_EXIT_HYPERV_HCALL          2
+                       __u32 type;
+                       union {
+                               struct {
+                                       __u32 msr;
+                                       __u64 control;
+                                       __u64 evt_page;
+                                       __u64 msg_page;
+                               } synic;
+                               struct {
+                                       __u64 input;
+                                       __u64 result;
+                                       __u64 params[2];
+                               } hcall;
+                       } u;
+               };
+               /* KVM_EXIT_HYPERV */
+                struct kvm_hyperv_exit hyperv;
+Indicates that the VCPU exits into userspace to process some tasks
+related to Hyper-V emulation.
+Valid values for 'type' are:
+       KVM_EXIT_HYPERV_SYNIC -- synchronously notify user-space about
+Hyper-V SynIC state change. Notification is used to remap SynIC
+event/message pages and to enable/disable SynIC messages/events processing
+in userspace.
+
+               /* Fix the size of the union. */
+               char padding[256];
+       };
+
+       /*
+        * shared registers between kvm and userspace.
+        * kvm_valid_regs specifies the register classes set by the host
+        * kvm_dirty_regs specified the register classes dirtied by userspace
+        * struct kvm_sync_regs is architecture specific, as well as the
+        * bits for kvm_valid_regs and kvm_dirty_regs
+        */
+       __u64 kvm_valid_regs;
+       __u64 kvm_dirty_regs;
+       union {
+               struct kvm_sync_regs regs;
+               char padding[SYNC_REGS_SIZE_BYTES];
+       } s;
+
+If KVM_CAP_SYNC_REGS is defined, these fields allow userspace to access
+certain guest registers without having to call SET/GET_*REGS. Thus we can
+avoid some system call overhead if userspace has to handle the exit.
+Userspace can query the validity of the structure by checking
+kvm_valid_regs for specific bits. These bits are architecture specific
+and usually define the validity of a groups of registers. (e.g. one bit
+ for general purpose registers)
+
+Please note that the kernel is allowed to use the kvm_run structure as the
+primary storage for certain register types. Therefore, the kernel may use the
+values in kvm_run even if the corresponding bit in kvm_dirty_regs is not set.
+
+};
+
+
+
+6. Capabilities that can be enabled on vCPUs
+--------------------------------------------
+
+There are certain capabilities that change the behavior of the virtual CPU or
+the virtual machine when enabled. To enable them, please see section 4.37.
+Below you can find a list of capabilities and what their effect on the vCPU or
+the virtual machine is when enabling them.
+
+The following information is provided along with the description:
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Target: whether this is a per-vcpu or per-vm capability.
+
+  Parameters: what parameters are accepted by the capability.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+
+6.1 KVM_CAP_PPC_OSI
+
+Architectures: ppc
+Target: vcpu
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of OSI hypercalls that otherwise would
+be treated as normal system calls to be injected into the guest. OSI hypercalls
+were invented by Mac-on-Linux to have a standardized communication mechanism
+between the guest and the host.
+
+When this capability is enabled, KVM_EXIT_OSI can occur.
+
+
+6.2 KVM_CAP_PPC_PAPR
+
+Architectures: ppc
+Target: vcpu
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of PAPR hypercalls. PAPR hypercalls are
+done using the hypercall instruction "sc 1".
+
+It also sets the guest privilege level to "supervisor" mode. Usually the guest
+runs in "hypervisor" privilege mode with a few missing features.
+
+In addition to the above, it changes the semantics of SDR1. In this mode, the
+HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
+HTAB invisible to the guest.
+
+When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
+
+
+6.3 KVM_CAP_SW_TLB
+
+Architectures: ppc
+Target: vcpu
+Parameters: args[0] is the address of a struct kvm_config_tlb
+Returns: 0 on success; -1 on error
+
+struct kvm_config_tlb {
+       __u64 params;
+       __u64 array;
+       __u32 mmu_type;
+       __u32 array_len;
+};
+
+Configures the virtual CPU's TLB array, establishing a shared memory area
+between userspace and KVM.  The "params" and "array" fields are userspace
+addresses of mmu-type-specific data structures.  The "array_len" field is an
+safety mechanism, and should be set to the size in bytes of the memory that
+userspace has reserved for the array.  It must be at least the size dictated
+by "mmu_type" and "params".
+
+While KVM_RUN is active, the shared region is under control of KVM.  Its
+contents are undefined, and any modification by userspace results in
+boundedly undefined behavior.
+
+On return from KVM_RUN, the shared region will reflect the current state of
+the guest's TLB.  If userspace makes any changes, it must call KVM_DIRTY_TLB
+to tell KVM which entries have been changed, prior to calling KVM_RUN again
+on this vcpu.
+
+For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
+ - The "params" field is of type "struct kvm_book3e_206_tlb_params".
+ - The "array" field points to an array of type "struct
+   kvm_book3e_206_tlb_entry".
+ - The array consists of all entries in the first TLB, followed by all
+   entries in the second TLB.
+ - Within a TLB, entries are ordered first by increasing set number.  Within a
+   set, entries are ordered by way (increasing ESEL).
+ - The hash for determining set number in TLB0 is: (MAS2 >> 12) & (num_sets - 1)
+   where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value.
+ - The tsize field of mas1 shall be set to 4K on TLB0, even though the
+   hardware ignores this value for TLB0.
+
+6.4 KVM_CAP_S390_CSS_SUPPORT
+
+Architectures: s390
+Target: vcpu
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables support for handling of channel I/O instructions.
+
+TEST PENDING INTERRUPTION and the interrupt portion of TEST SUBCHANNEL are
+handled in-kernel, while the other I/O instructions are passed to userspace.
+
+When this capability is enabled, KVM_EXIT_S390_TSCH will occur on TEST
+SUBCHANNEL intercepts.
+
+Note that even though this capability is enabled per-vcpu, the complete
+virtual machine is affected.
+
+6.5 KVM_CAP_PPC_EPR
+
+Architectures: ppc
+Target: vcpu
+Parameters: args[0] defines whether the proxy facility is active
+Returns: 0 on success; -1 on error
+
+This capability enables or disables the delivery of interrupts through the
+external proxy facility.
+
+When enabled (args[0] != 0), every time the guest gets an external interrupt
+delivered, it automatically exits into user space with a KVM_EXIT_EPR exit
+to receive the topmost interrupt vector.
+
+When disabled (args[0] == 0), behavior is as if this facility is unsupported.
+
+When this capability is enabled, KVM_EXIT_EPR can occur.
+
+6.6 KVM_CAP_IRQ_MPIC
+
+Architectures: ppc
+Parameters: args[0] is the MPIC device fd
+            args[1] is the MPIC CPU number for this vcpu
+
+This capability connects the vcpu to an in-kernel MPIC device.
+
+6.7 KVM_CAP_IRQ_XICS
+
+Architectures: ppc
+Target: vcpu
+Parameters: args[0] is the XICS device fd
+            args[1] is the XICS CPU number (server ID) for this vcpu
+
+This capability connects the vcpu to an in-kernel XICS device.
+
+6.8 KVM_CAP_S390_IRQCHIP
+
+Architectures: s390
+Target: vm
+Parameters: none
+
+This capability enables the in-kernel irqchip for s390. Please refer to
+"4.24 KVM_CREATE_IRQCHIP" for details.
+
+6.9 KVM_CAP_MIPS_FPU
+
+Architectures: mips
+Target: vcpu
+Parameters: args[0] is reserved for future use (should be 0).
+
+This capability allows the use of the host Floating Point Unit by the guest. It
+allows the Config1.FP bit to be set to enable the FPU in the guest. Once this is
+done the KVM_REG_MIPS_FPR_* and KVM_REG_MIPS_FCR_* registers can be accessed
+(depending on the current guest FPU register mode), and the Status.FR,
+Config5.FRE bits are accessible via the KVM API and also from the guest,
+depending on them being supported by the FPU.
+
+6.10 KVM_CAP_MIPS_MSA
+
+Architectures: mips
+Target: vcpu
+Parameters: args[0] is reserved for future use (should be 0).
+
+This capability allows the use of the MIPS SIMD Architecture (MSA) by the guest.
+It allows the Config3.MSAP bit to be set to enable the use of MSA by the guest.
+Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
+accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
+the guest.
+
+6.74 KVM_CAP_SYNC_REGS
+Architectures: s390, x86
+Target: s390: always enabled, x86: vcpu
+Parameters: none
+Returns: x86: KVM_CHECK_EXTENSION returns a bit-array indicating which register
+sets are supported (bitfields defined in arch/x86/include/uapi/asm/kvm.h).
+
+As described above in the kvm_sync_regs struct info in section 5 (kvm_run):
+KVM_CAP_SYNC_REGS "allow[s] userspace to access certain guest registers
+without having to call SET/GET_*REGS". This reduces overhead by eliminating
+repeated ioctl calls for setting and/or getting register values. This is
+particularly important when userspace is making synchronous guest state
+modifications, e.g. when emulating and/or intercepting instructions in
+userspace.
+
+For s390 specifics, please refer to the source code.
+
+For x86:
+- the register sets to be copied out to kvm_run are selectable
+  by userspace (rather that all sets being copied out for every exit).
+- vcpu_events are available in addition to regs and sregs.
+
+For x86, the 'kvm_valid_regs' field of struct kvm_run is overloaded to
+function as an input bit-array field set by userspace to indicate the
+specific register sets to be copied out on the next exit.
+
+To indicate when userspace has modified values that should be copied into
+the vCPU, the all architecture bitarray field, 'kvm_dirty_regs' must be set.
+This is done using the same bitflags as for the 'kvm_valid_regs' field.
+If the dirty bit is not set, then the register set values will not be copied
+into the vCPU even if they've been modified.
+
+Unused bitfields in the bitarrays must be set to zero.
+
+struct kvm_sync_regs {
+        struct kvm_regs regs;
+        struct kvm_sregs sregs;
+        struct kvm_vcpu_events events;
+};
+
+6.75 KVM_CAP_PPC_IRQ_XIVE
+
+Architectures: ppc
+Target: vcpu
+Parameters: args[0] is the XIVE device fd
+            args[1] is the XIVE CPU number (server ID) for this vcpu
+
+This capability connects the vcpu to an in-kernel XIVE device.
+
+7. Capabilities that can be enabled on VMs
+------------------------------------------
+
+There are certain capabilities that change the behavior of the virtual
+machine when enabled. To enable them, please see section 4.37. Below
+you can find a list of capabilities and what their effect on the VM
+is when enabling them.
+
+The following information is provided along with the description:
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Parameters: what parameters are accepted by the capability.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+
+7.1 KVM_CAP_PPC_ENABLE_HCALL
+
+Architectures: ppc
+Parameters: args[0] is the sPAPR hcall number
+           args[1] is 0 to disable, 1 to enable in-kernel handling
+
+This capability controls whether individual sPAPR hypercalls (hcalls)
+get handled by the kernel or not.  Enabling or disabling in-kernel
+handling of an hcall is effective across the VM.  On creation, an
+initial set of hcalls are enabled for in-kernel handling, which
+consists of those hcalls for which in-kernel handlers were implemented
+before this capability was implemented.  If disabled, the kernel will
+not to attempt to handle the hcall, but will always exit to userspace
+to handle it.  Note that it may not make sense to enable some and
+disable others of a group of related hcalls, but KVM does not prevent
+userspace from doing that.
+
+If the hcall number specified is not one that has an in-kernel
+implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL
+error.
+
+7.2 KVM_CAP_S390_USER_SIGP
+
+Architectures: s390
+Parameters: none
+
+This capability controls which SIGP orders will be handled completely in user
+space. With this capability enabled, all fast orders will be handled completely
+in the kernel:
+- SENSE
+- SENSE RUNNING
+- EXTERNAL CALL
+- EMERGENCY SIGNAL
+- CONDITIONAL EMERGENCY SIGNAL
+
+All other orders will be handled completely in user space.
+
+Only privileged operation exceptions will be checked for in the kernel (or even
+in the hardware prior to interception). If this capability is not enabled, the
+old way of handling SIGP orders is used (partially in kernel and user space).
+
+7.3 KVM_CAP_S390_VECTOR_REGISTERS
+
+Architectures: s390
+Parameters: none
+Returns: 0 on success, negative value on error
+
+Allows use of the vector registers introduced with z13 processor, and
+provides for the synchronization between host and user space.  Will
+return -EINVAL if the machine does not support vectors.
+
+7.4 KVM_CAP_S390_USER_STSI
+
+Architectures: s390
+Parameters: none
+
+This capability allows post-handlers for the STSI instruction. After
+initial handling in the kernel, KVM exits to user space with
+KVM_EXIT_S390_STSI to allow user space to insert further data.
+
+Before exiting to userspace, kvm handlers should fill in s390_stsi field of
+vcpu->run:
+struct {
+       __u64 addr;
+       __u8 ar;
+       __u8 reserved;
+       __u8 fc;
+       __u8 sel1;
+       __u16 sel2;
+} s390_stsi;
+
+@addr - guest address of STSI SYSIB
+@fc   - function code
+@sel1 - selector 1
+@sel2 - selector 2
+@ar   - access register number
+
+KVM handlers should exit to userspace with rc = -EREMOTE.
+
+7.5 KVM_CAP_SPLIT_IRQCHIP
+
+Architectures: x86
+Parameters: args[0] - number of routes reserved for userspace IOAPICs
+Returns: 0 on success, -1 on error
+
+Create a local apic for each processor in the kernel. This can be used
+instead of KVM_CREATE_IRQCHIP if the userspace VMM wishes to emulate the
+IOAPIC and PIC (and also the PIT, even though this has to be enabled
+separately).
+
+This capability also enables in kernel routing of interrupt requests;
+when KVM_CAP_SPLIT_IRQCHIP only routes of KVM_IRQ_ROUTING_MSI type are
+used in the IRQ routing table.  The first args[0] MSI routes are reserved
+for the IOAPIC pins.  Whenever the LAPIC receives an EOI for these routes,
+a KVM_EXIT_IOAPIC_EOI vmexit will be reported to userspace.
+
+Fails if VCPU has already been created, or if the irqchip is already in the
+kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
+
+7.6 KVM_CAP_S390_RI
+
+Architectures: s390
+Parameters: none
+
+Allows use of runtime-instrumentation introduced with zEC12 processor.
+Will return -EINVAL if the machine does not support runtime-instrumentation.
+Will return -EBUSY if a VCPU has already been created.
+
+7.7 KVM_CAP_X2APIC_API
+
+Architectures: x86
+Parameters: args[0] - features that should be enabled
+Returns: 0 on success, -EINVAL when args[0] contains invalid features
+
+Valid feature flags in args[0] are
+
+#define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
+#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
+
+Enabling KVM_X2APIC_API_USE_32BIT_IDS changes the behavior of
+KVM_SET_GSI_ROUTING, KVM_SIGNAL_MSI, KVM_SET_LAPIC, and KVM_GET_LAPIC,
+allowing the use of 32-bit APIC IDs.  See KVM_CAP_X2APIC_API in their
+respective sections.
+
+KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK must be enabled for x2APIC to work
+in logical mode or with more than 255 VCPUs.  Otherwise, KVM treats 0xff
+as a broadcast even in x2APIC mode in order to support physical x2APIC
+without interrupt remapping.  This is undesirable in logical mode,
+where 0xff represents CPUs 0-7 in cluster 0.
+
+7.8 KVM_CAP_S390_USER_INSTR0
+
+Architectures: s390
+Parameters: none
+
+With this capability enabled, all illegal instructions 0x0000 (2 bytes) will
+be intercepted and forwarded to user space. User space can use this
+mechanism e.g. to realize 2-byte software breakpoints. The kernel will
+not inject an operating exception for these instructions, user space has
+to take care of that.
+
+This capability can be enabled dynamically even if VCPUs were already
+created and are running.
+
+7.9 KVM_CAP_S390_GS
+
+Architectures: s390
+Parameters: none
+Returns: 0 on success; -EINVAL if the machine does not support
+        guarded storage; -EBUSY if a VCPU has already been created.
+
+Allows use of guarded storage for the KVM guest.
+
+7.10 KVM_CAP_S390_AIS
+
+Architectures: s390
+Parameters: none
+
+Allow use of adapter-interruption suppression.
+Returns: 0 on success; -EBUSY if a VCPU has already been created.
+
+7.11 KVM_CAP_PPC_SMT
+
+Architectures: ppc
+Parameters: vsmt_mode, flags
+
+Enabling this capability on a VM provides userspace with a way to set
+the desired virtual SMT mode (i.e. the number of virtual CPUs per
+virtual core).  The virtual SMT mode, vsmt_mode, must be a power of 2
+between 1 and 8.  On POWER8, vsmt_mode must also be no greater than
+the number of threads per subcore for the host.  Currently flags must
+be 0.  A successful call to enable this capability will result in
+vsmt_mode being returned when the KVM_CAP_PPC_SMT capability is
+subsequently queried for the VM.  This capability is only supported by
+HV KVM, and can only be set before any VCPUs have been created.
+The KVM_CAP_PPC_SMT_POSSIBLE capability indicates which virtual SMT
+modes are available.
+
+7.12 KVM_CAP_PPC_FWNMI
+
+Architectures: ppc
+Parameters: none
+
+With this capability a machine check exception in the guest address
+space will cause KVM to exit the guest with NMI exit reason. This
+enables QEMU to build error log and branch to guest kernel registered
+machine check handling routine. Without this capability KVM will
+branch to guests' 0x200 interrupt vector.
+
+7.13 KVM_CAP_X86_DISABLE_EXITS
+
+Architectures: x86
+Parameters: args[0] defines which exits are disabled
+Returns: 0 on success, -EINVAL when args[0] contains invalid exits
+
+Valid bits in args[0] are
+
+#define KVM_X86_DISABLE_EXITS_MWAIT            (1 << 0)
+#define KVM_X86_DISABLE_EXITS_HLT              (1 << 1)
+#define KVM_X86_DISABLE_EXITS_PAUSE            (1 << 2)
+#define KVM_X86_DISABLE_EXITS_CSTATE           (1 << 3)
+
+Enabling this capability on a VM provides userspace with a way to no
+longer intercept some instructions for improved latency in some
+workloads, and is suggested when vCPUs are associated to dedicated
+physical CPUs.  More bits can be added in the future; userspace can
+just pass the KVM_CHECK_EXTENSION result to KVM_ENABLE_CAP to disable
+all such vmexits.
+
+Do not enable KVM_FEATURE_PV_UNHALT if you disable HLT exits.
+
+7.14 KVM_CAP_S390_HPAGE_1M
+
+Architectures: s390
+Parameters: none
+Returns: 0 on success, -EINVAL if hpage module parameter was not set
+        or cmma is enabled, or the VM has the KVM_VM_S390_UCONTROL
+        flag set
+
+With this capability the KVM support for memory backing with 1m pages
+through hugetlbfs can be enabled for a VM. After the capability is
+enabled, cmma can't be enabled anymore and pfmfi and the storage key
+interpretation are disabled. If cmma has already been enabled or the
+hpage module parameter is not set to 1, -EINVAL is returned.
+
+While it is generally possible to create a huge page backed VM without
+this capability, the VM will not be able to run.
+
+7.15 KVM_CAP_MSR_PLATFORM_INFO
+
+Architectures: x86
+Parameters: args[0] whether feature should be enabled or not
+
+With this capability, a guest may read the MSR_PLATFORM_INFO MSR. Otherwise,
+a #GP would be raised when the guest tries to access. Currently, this
+capability does not enable write permissions of this MSR for the guest.
+
+7.16 KVM_CAP_PPC_NESTED_HV
+
+Architectures: ppc
+Parameters: none
+Returns: 0 on success, -EINVAL when the implementation doesn't support
+        nested-HV virtualization.
+
+HV-KVM on POWER9 and later systems allows for "nested-HV"
+virtualization, which provides a way for a guest VM to run guests that
+can run using the CPU's supervisor mode (privileged non-hypervisor
+state).  Enabling this capability on a VM depends on the CPU having
+the necessary functionality and on the facility being enabled with a
+kvm-hv module parameter.
+
+7.17 KVM_CAP_EXCEPTION_PAYLOAD
+
+Architectures: x86
+Parameters: args[0] whether feature should be enabled or not
+
+With this capability enabled, CR2 will not be modified prior to the
+emulated VM-exit when L1 intercepts a #PF exception that occurs in
+L2. Similarly, for kvm-intel only, DR6 will not be modified prior to
+the emulated VM-exit when L1 intercepts a #DB exception that occurs in
+L2. As a result, when KVM_GET_VCPU_EVENTS reports a pending #PF (or
+#DB) exception for L2, exception.has_payload will be set and the
+faulting address (or the new DR6 bits*) will be reported in the
+exception_payload field. Similarly, when userspace injects a #PF (or
+#DB) into L2 using KVM_SET_VCPU_EVENTS, it is expected to set
+exception.has_payload and to put the faulting address (or the new DR6
+bits*) in the exception_payload field.
+
+This capability also enables exception.pending in struct
+kvm_vcpu_events, which allows userspace to distinguish between pending
+and injected exceptions.
+
+
+* For the new DR6 bits, note that bit 16 is set iff the #DB exception
+  will clear DR6.RTM.
+
+7.18 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
+
+Architectures: x86, arm, arm64, mips
+Parameters: args[0] whether feature should be enabled or not
+
+With this capability enabled, KVM_GET_DIRTY_LOG will not automatically
+clear and write-protect all pages that are returned as dirty.
+Rather, userspace will have to do this operation separately using
+KVM_CLEAR_DIRTY_LOG.
+
+At the cost of a slightly more complicated operation, this provides better
+scalability and responsiveness for two reasons.  First,
+KVM_CLEAR_DIRTY_LOG ioctl can operate on a 64-page granularity rather
+than requiring to sync a full memslot; this ensures that KVM does not
+take spinlocks for an extended period of time.  Second, in some cases a
+large amount of time can pass between a call to KVM_GET_DIRTY_LOG and
+userspace actually using the data in the page.  Pages can be modified
+during this time, which is inefficint for both the guest and userspace:
+the guest will incur a higher penalty due to write protection faults,
+while userspace can see false reports of dirty pages.  Manual reprotection
+helps reducing this time, improving guest performance and reducing the
+number of dirty log false positives.
+
+KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 was previously available under the name
+KVM_CAP_MANUAL_DIRTY_LOG_PROTECT, but the implementation had bugs that make
+it hard or impossible to use it correctly.  The availability of
+KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 signals that those bugs are fixed.
+Userspace should not try to use KVM_CAP_MANUAL_DIRTY_LOG_PROTECT.
+
+8. Other capabilities.
+----------------------
+
+This section lists capabilities that give information about other
+features of the KVM implementation.
+
+8.1 KVM_CAP_PPC_HWRNG
+
+Architectures: ppc
+
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel has an implementation of the
+H_RANDOM hypercall backed by a hardware random-number generator.
+If present, the kernel H_RANDOM handler can be enabled for guest use
+with the KVM_CAP_PPC_ENABLE_HCALL capability.
+
+8.2 KVM_CAP_HYPERV_SYNIC
+
+Architectures: x86
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel has an implementation of the
+Hyper-V Synthetic interrupt controller(SynIC). Hyper-V SynIC is
+used to support Windows Hyper-V based guest paravirt drivers(VMBus).
+
+In order to use SynIC, it has to be activated by setting this
+capability via KVM_ENABLE_CAP ioctl on the vcpu fd. Note that this
+will disable the use of APIC hardware virtualization even if supported
+by the CPU, as it's incompatible with SynIC auto-EOI behavior.
+
+8.3 KVM_CAP_PPC_RADIX_MMU
+
+Architectures: ppc
+
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel can support guests using the
+radix MMU defined in Power ISA V3.00 (as implemented in the POWER9
+processor).
+
+8.4 KVM_CAP_PPC_HASH_MMU_V3
+
+Architectures: ppc
+
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel can support guests using the
+hashed page table MMU defined in Power ISA V3.00 (as implemented in
+the POWER9 processor), including in-memory segment tables.
+
+8.5 KVM_CAP_MIPS_VZ
+
+Architectures: mips
+
+This capability, if KVM_CHECK_EXTENSION on the main kvm handle indicates that
+it is available, means that full hardware assisted virtualization capabilities
+of the hardware are available for use through KVM. An appropriate
+KVM_VM_MIPS_* type must be passed to KVM_CREATE_VM to create a VM which
+utilises it.
+
+If KVM_CHECK_EXTENSION on a kvm VM handle indicates that this capability is
+available, it means that the VM is using full hardware assisted virtualization
+capabilities of the hardware. This is useful to check after creating a VM with
+KVM_VM_MIPS_DEFAULT.
+
+The value returned by KVM_CHECK_EXTENSION should be compared against known
+values (see below). All other values are reserved. This is to allow for the
+possibility of other hardware assisted virtualization implementations which
+may be incompatible with the MIPS VZ ASE.
+
+ 0: The trap & emulate implementation is in use to run guest code in user
+    mode. Guest virtual memory segments are rearranged to fit the guest in the
+    user mode address space.
+
+ 1: The MIPS VZ ASE is in use, providing full hardware assisted
+    virtualization, including standard guest virtual memory segments.
+
+8.6 KVM_CAP_MIPS_TE
+
+Architectures: mips
+
+This capability, if KVM_CHECK_EXTENSION on the main kvm handle indicates that
+it is available, means that the trap & emulate implementation is available to
+run guest code in user mode, even if KVM_CAP_MIPS_VZ indicates that hardware
+assisted virtualisation is also available. KVM_VM_MIPS_TE (0) must be passed
+to KVM_CREATE_VM to create a VM which utilises it.
+
+If KVM_CHECK_EXTENSION on a kvm VM handle indicates that this capability is
+available, it means that the VM is using trap & emulate.
+
+8.7 KVM_CAP_MIPS_64BIT
+
+Architectures: mips
+
+This capability indicates the supported architecture type of the guest, i.e. the
+supported register and address width.
+
+The values returned when this capability is checked by KVM_CHECK_EXTENSION on a
+kvm VM handle correspond roughly to the CP0_Config.AT register field, and should
+be checked specifically against known values (see below). All other values are
+reserved.
+
+ 0: MIPS32 or microMIPS32.
+    Both registers and addresses are 32-bits wide.
+    It will only be possible to run 32-bit guest code.
+
+ 1: MIPS64 or microMIPS64 with access only to 32-bit compatibility segments.
+    Registers are 64-bits wide, but addresses are 32-bits wide.
+    64-bit guest code may run but cannot access MIPS64 memory segments.
+    It will also be possible to run 32-bit guest code.
+
+ 2: MIPS64 or microMIPS64 with access to all address segments.
+    Both registers and addresses are 64-bits wide.
+    It will be possible to run 64-bit or 32-bit guest code.
+
+8.9 KVM_CAP_ARM_USER_IRQ
+
+Architectures: arm, arm64
+This capability, if KVM_CHECK_EXTENSION indicates that it is available, means
+that if userspace creates a VM without an in-kernel interrupt controller, it
+will be notified of changes to the output level of in-kernel emulated devices,
+which can generate virtual interrupts, presented to the VM.
+For such VMs, on every return to userspace, the kernel
+updates the vcpu's run->s.regs.device_irq_level field to represent the actual
+output level of the device.
+
+Whenever kvm detects a change in the device output level, kvm guarantees at
+least one return to userspace before running the VM.  This exit could either
+be a KVM_EXIT_INTR or any other exit event, like KVM_EXIT_MMIO. This way,
+userspace can always sample the device output level and re-compute the state of
+the userspace interrupt controller.  Userspace should always check the state
+of run->s.regs.device_irq_level on every kvm exit.
+The value in run->s.regs.device_irq_level can represent both level and edge
+triggered interrupt signals, depending on the device.  Edge triggered interrupt
+signals will exit to userspace with the bit in run->s.regs.device_irq_level
+set exactly once per edge signal.
+
+The field run->s.regs.device_irq_level is available independent of
+run->kvm_valid_regs or run->kvm_dirty_regs bits.
+
+If KVM_CAP_ARM_USER_IRQ is supported, the KVM_CHECK_EXTENSION ioctl returns a
+number larger than 0 indicating the version of this capability is implemented
+and thereby which bits in in run->s.regs.device_irq_level can signal values.
+
+Currently the following bits are defined for the device_irq_level bitmap:
+
+  KVM_CAP_ARM_USER_IRQ >= 1:
+
+    KVM_ARM_DEV_EL1_VTIMER -  EL1 virtual timer
+    KVM_ARM_DEV_EL1_PTIMER -  EL1 physical timer
+    KVM_ARM_DEV_PMU        -  ARM PMU overflow interrupt signal
+
+Future versions of kvm may implement additional events. These will get
+indicated by returning a higher number from KVM_CHECK_EXTENSION and will be
+listed above.
+
+8.10 KVM_CAP_PPC_SMT_POSSIBLE
+
+Architectures: ppc
+
+Querying this capability returns a bitmap indicating the possible
+virtual SMT modes that can be set using KVM_CAP_PPC_SMT.  If bit N
+(counting from the right) is set, then a virtual SMT mode of 2^N is
+available.
+
+8.11 KVM_CAP_HYPERV_SYNIC2
+
+Architectures: x86
+
+This capability enables a newer version of Hyper-V Synthetic interrupt
+controller (SynIC).  The only difference with KVM_CAP_HYPERV_SYNIC is that KVM
+doesn't clear SynIC message and event flags pages when they are enabled by
+writing to the respective MSRs.
+
+8.12 KVM_CAP_HYPERV_VP_INDEX
+
+Architectures: x86
+
+This capability indicates that userspace can load HV_X64_MSR_VP_INDEX msr.  Its
+value is used to denote the target vcpu for a SynIC interrupt.  For
+compatibilty, KVM initializes this msr to KVM's internal vcpu index.  When this
+capability is absent, userspace can still query this msr's value.
+
+8.13 KVM_CAP_S390_AIS_MIGRATION
+
+Architectures: s390
+Parameters: none
+
+This capability indicates if the flic device will be able to get/set the
+AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows
+to discover this without having to create a flic device.
+
+8.14 KVM_CAP_S390_PSW
+
+Architectures: s390
+
+This capability indicates that the PSW is exposed via the kvm_run structure.
+
+8.15 KVM_CAP_S390_GMAP
+
+Architectures: s390
+
+This capability indicates that the user space memory used as guest mapping can
+be anywhere in the user memory address space, as long as the memory slots are
+aligned and sized to a segment (1MB) boundary.
+
+8.16 KVM_CAP_S390_COW
+
+Architectures: s390
+
+This capability indicates that the user space memory used as guest mapping can
+use copy-on-write semantics as well as dirty pages tracking via read-only page
+tables.
+
+8.17 KVM_CAP_S390_BPB
+
+Architectures: s390
+
+This capability indicates that kvm will implement the interfaces to handle
+reset, migration and nested KVM for branch prediction blocking. The stfle
+facility 82 should not be provided to the guest without this capability.
+
+8.18 KVM_CAP_HYPERV_TLBFLUSH
+
+Architectures: x86
+
+This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush
+hypercalls:
+HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx,
+HvFlushVirtualAddressList, HvFlushVirtualAddressListEx.
+
+8.19 KVM_CAP_ARM_INJECT_SERROR_ESR
+
+Architectures: arm, arm64
+
+This capability indicates that userspace can specify (via the
+KVM_SET_VCPU_EVENTS ioctl) the syndrome value reported to the guest when it
+takes a virtual SError interrupt exception.
+If KVM advertises this capability, userspace can only specify the ISS field for
+the ESR syndrome. Other parts of the ESR, such as the EC are generated by the
+CPU when the exception is taken. If this virtual SError is taken to EL1 using
+AArch64, this value will be reported in the ISS field of ESR_ELx.
+
+See KVM_CAP_VCPU_EVENTS for more details.
+8.20 KVM_CAP_HYPERV_SEND_IPI
+
+Architectures: x86
+
+This capability indicates that KVM supports paravirtualized Hyper-V IPI send
+hypercalls:
+HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx.
diff --git a/Documentation/virt/kvm/arm/hyp-abi.txt b/Documentation/virt/kvm/arm/hyp-abi.txt
new file mode 100644 (file)
index 0000000..a20a0be
--- /dev/null
@@ -0,0 +1,53 @@
+* Internal ABI between the kernel and HYP
+
+This file documents the interaction between the Linux kernel and the
+hypervisor layer when running Linux as a hypervisor (for example
+KVM). It doesn't cover the interaction of the kernel with the
+hypervisor when running as a guest (under Xen, KVM or any other
+hypervisor), or any hypervisor-specific interaction when the kernel is
+used as a host.
+
+On arm and arm64 (without VHE), the kernel doesn't run in hypervisor
+mode, but still needs to interact with it, allowing a built-in
+hypervisor to be either installed or torn down.
+
+In order to achieve this, the kernel must be booted at HYP (arm) or
+EL2 (arm64), allowing it to install a set of stubs before dropping to
+SVC/EL1. These stubs are accessible by using a 'hvc #0' instruction,
+and only act on individual CPUs.
+
+Unless specified otherwise, any built-in hypervisor must implement
+these functions (see arch/arm{,64}/include/asm/virt.h):
+
+* r0/x0 = HVC_SET_VECTORS
+  r1/x1 = vectors
+
+  Set HVBAR/VBAR_EL2 to 'vectors' to enable a hypervisor. 'vectors'
+  must be a physical address, and respect the alignment requirements
+  of the architecture. Only implemented by the initial stubs, not by
+  Linux hypervisors.
+
+* r0/x0 = HVC_RESET_VECTORS
+
+  Turn HYP/EL2 MMU off, and reset HVBAR/VBAR_EL2 to the initials
+  stubs' exception vector value. This effectively disables an existing
+  hypervisor.
+
+* r0/x0 = HVC_SOFT_RESTART
+  r1/x1 = restart address
+  x2 = x0's value when entering the next payload (arm64)
+  x3 = x1's value when entering the next payload (arm64)
+  x4 = x2's value when entering the next payload (arm64)
+
+  Mask all exceptions, disable the MMU, move the arguments into place
+  (arm64 only), and jump to the restart address while at HYP/EL2. This
+  hypercall is not expected to return to its caller.
+
+Any other value of r0/x0 triggers a hypervisor-specific handling,
+which is not documented here.
+
+The return value of a stub hypercall is held by r0/x0, and is 0 on
+success, and HVC_STUB_ERR on error. A stub hypercall is allowed to
+clobber any of the caller-saved registers (x0-x18 on arm64, r0-r3 and
+ip on arm). It is thus recommended to use a function call to perform
+the hypercall.
diff --git a/Documentation/virt/kvm/arm/psci.txt b/Documentation/virt/kvm/arm/psci.txt
new file mode 100644 (file)
index 0000000..559586f
--- /dev/null
@@ -0,0 +1,61 @@
+KVM implements the PSCI (Power State Coordination Interface)
+specification in order to provide services such as CPU on/off, reset
+and power-off to the guest.
+
+The PSCI specification is regularly updated to provide new features,
+and KVM implements these updates if they make sense from a virtualization
+point of view.
+
+This means that a guest booted on two different versions of KVM can
+observe two different "firmware" revisions. This could cause issues if
+a given guest is tied to a particular PSCI revision (unlikely), or if
+a migration causes a different PSCI version to be exposed out of the
+blue to an unsuspecting guest.
+
+In order to remedy this situation, KVM exposes a set of "firmware
+pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
+interface. These registers can be saved/restored by userspace, and set
+to a convenient value if required.
+
+The following register is defined:
+
+* KVM_REG_ARM_PSCI_VERSION:
+
+  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
+    (and thus has already been initialized)
+  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
+    highest PSCI version implemented by KVM and compatible with v0.2)
+  - Allows any PSCI version implemented by KVM and compatible with
+    v0.2 to be set with SET_ONE_REG
+  - Affects the whole VM (even if the register view is per-vcpu)
+
+* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
+  Holds the state of the firmware support to mitigate CVE-2017-5715, as
+  offered by KVM to the guest via a HVC call. The workaround is described
+  under SMCCC_ARCH_WORKAROUND_1 in [1].
+  Accepted values are:
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL: KVM does not offer
+      firmware support for the workaround. The mitigation status for the
+      guest is unknown.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL: The workaround HVC call is
+      available to the guest and required for the mitigation.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED: The workaround HVC call
+      is available to the guest, but it is not needed on this VCPU.
+
+* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
+  Holds the state of the firmware support to mitigate CVE-2018-3639, as
+  offered by KVM to the guest via a HVC call. The workaround is described
+  under SMCCC_ARCH_WORKAROUND_2 in [1].
+  Accepted values are:
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL: A workaround is not
+      available. KVM does not offer firmware support for the workaround.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN: The workaround state is
+      unknown. KVM does not offer firmware support for the workaround.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL: The workaround is available,
+      and can be disabled by a vCPU. If
+      KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED is set, it is active for
+      this vCPU.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED: The workaround is
+      always active on this vCPU or it is not needed.
+
+[1] https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf
diff --git a/Documentation/virt/kvm/cpuid.rst b/Documentation/virt/kvm/cpuid.rst
new file mode 100644 (file)
index 0000000..01b081f
--- /dev/null
@@ -0,0 +1,107 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============
+KVM CPUID bits
+==============
+
+:Author: Glauber Costa <glommer@gmail.com>
+
+A guest running on a kvm host, can check some of its features using
+cpuid. This is not always guaranteed to work, since userspace can
+mask-out some, or even all KVM-related cpuid features before launching
+a guest.
+
+KVM cpuid functions are:
+
+function: KVM_CPUID_SIGNATURE (0x40000000)
+
+returns::
+
+   eax = 0x40000001
+   ebx = 0x4b4d564b
+   ecx = 0x564b4d56
+   edx = 0x4d
+
+Note that this value in ebx, ecx and edx corresponds to the string "KVMKVMKVM".
+The value in eax corresponds to the maximum cpuid function present in this leaf,
+and will be updated if more functions are added in the future.
+Note also that old hosts set eax value to 0x0. This should
+be interpreted as if the value was 0x40000001.
+This function queries the presence of KVM cpuid leafs.
+
+function: define KVM_CPUID_FEATURES (0x40000001)
+
+returns::
+
+          ebx, ecx
+          eax = an OR'ed group of (1 << flag)
+
+where ``flag`` is defined as below:
+
+================================= =========== ================================
+flag                              value       meaning
+================================= =========== ================================
+KVM_FEATURE_CLOCKSOURCE           0           kvmclock available at msrs
+                                              0x11 and 0x12
+
+KVM_FEATURE_NOP_IO_DELAY          1           not necessary to perform delays
+                                              on PIO operations
+
+KVM_FEATURE_MMU_OP                2           deprecated
+
+KVM_FEATURE_CLOCKSOURCE2          3           kvmclock available at msrs
+
+                                              0x4b564d00 and 0x4b564d01
+KVM_FEATURE_ASYNC_PF              4           async pf can be enabled by
+                                              writing to msr 0x4b564d02
+
+KVM_FEATURE_STEAL_TIME            5           steal time can be enabled by
+                                              writing to msr 0x4b564d03
+
+KVM_FEATURE_PV_EOI                6           paravirtualized end of interrupt
+                                              handler can be enabled by
+                                              writing to msr 0x4b564d04
+
+KVM_FEATURE_PV_UNHAULT            7           guest checks this feature bit
+                                              before enabling paravirtualized
+                                              spinlock support
+
+KVM_FEATURE_PV_TLB_FLUSH          9           guest checks this feature bit
+                                              before enabling paravirtualized
+                                              tlb flush
+
+KVM_FEATURE_ASYNC_PF_VMEXIT       10          paravirtualized async PF VM EXIT
+                                              can be enabled by setting bit 2
+                                              when writing to msr 0x4b564d02
+
+KVM_FEATURE_PV_SEND_IPI           11          guest checks this feature bit
+                                              before enabling paravirtualized
+                                              sebd IPIs
+
+KVM_FEATURE_PV_POLL_CONTROL       12          host-side polling on HLT can
+                                              be disabled by writing
+                                              to msr 0x4b564d05.
+
+KVM_FEATURE_PV_SCHED_YIELD        13          guest checks this feature bit
+                                              before using paravirtualized
+                                              sched yield.
+
+KVM_FEATURE_CLOCSOURCE_STABLE_BIT 24          host will warn if no guest-side
+                                              per-cpu warps are expeced in
+                                              kvmclock
+================================= =========== ================================
+
+::
+
+      edx = an OR'ed group of (1 << flag)
+
+Where ``flag`` here is defined as below:
+
+================== ============ =================================
+flag               value        meaning
+================== ============ =================================
+KVM_HINTS_REALTIME 0            guest checks this feature bit to
+                                determine that vCPUs are never
+                                preempted for an unlimited time
+                                allowing optimizations
+================== ============ =================================
diff --git a/Documentation/virt/kvm/devices/README b/Documentation/virt/kvm/devices/README
new file mode 100644 (file)
index 0000000..34a6983
--- /dev/null
@@ -0,0 +1 @@
+This directory contains specific device bindings for KVM_CAP_DEVICE_CTRL.
diff --git a/Documentation/virt/kvm/devices/arm-vgic-its.txt b/Documentation/virt/kvm/devices/arm-vgic-its.txt
new file mode 100644 (file)
index 0000000..eeaa95b
--- /dev/null
@@ -0,0 +1,181 @@
+ARM Virtual Interrupt Translation Service (ITS)
+===============================================
+
+Device types supported:
+  KVM_DEV_TYPE_ARM_VGIC_ITS    ARM Interrupt Translation Service Controller
+
+The ITS allows MSI(-X) interrupts to be injected into guests. This extension is
+optional.  Creating a virtual ITS controller also requires a host GICv3 (see
+arm-vgic-v3.txt), but does not depend on having physical ITS controllers.
+
+There can be multiple ITS controllers per guest, each of them has to have
+a separate, non-overlapping MMIO region.
+
+
+Groups:
+  KVM_DEV_ARM_VGIC_GRP_ADDR
+  Attributes:
+    KVM_VGIC_ITS_ADDR_TYPE (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3 ITS
+      control register frame.
+      This address needs to be 64K aligned and the region covers 128K.
+  Errors:
+    -E2BIG:  Address outside of addressable IPA range
+    -EINVAL: Incorrectly aligned address
+    -EEXIST: Address already configured
+    -EFAULT: Invalid user pointer for attr->addr.
+    -ENODEV: Incorrect attribute or the ITS is not supported.
+
+
+  KVM_DEV_ARM_VGIC_GRP_CTRL
+  Attributes:
+    KVM_DEV_ARM_VGIC_CTRL_INIT
+      request the initialization of the ITS, no additional parameter in
+      kvm_device_attr.addr.
+
+    KVM_DEV_ARM_ITS_CTRL_RESET
+      reset the ITS, no additional parameter in kvm_device_attr.addr.
+      See "ITS Reset State" section.
+
+    KVM_DEV_ARM_ITS_SAVE_TABLES
+      save the ITS table data into guest RAM, at the location provisioned
+      by the guest in corresponding registers/table entries.
+
+      The layout of the tables in guest memory defines an ABI. The entries
+      are laid out in little endian format as described in the last paragraph.
+
+    KVM_DEV_ARM_ITS_RESTORE_TABLES
+      restore the ITS tables from guest RAM to ITS internal structures.
+
+      The GICV3 must be restored before the ITS and all ITS registers but
+      the GITS_CTLR must be restored before restoring the ITS tables.
+
+      The GITS_IIDR read-only register must also be restored before
+      calling KVM_DEV_ARM_ITS_RESTORE_TABLES as the IIDR revision field
+      encodes the ABI revision.
+
+      The expected ordering when restoring the GICv3/ITS is described in section
+      "ITS Restore Sequence".
+
+  Errors:
+    -ENXIO:  ITS not properly configured as required prior to setting
+             this attribute
+    -ENOMEM: Memory shortage when allocating ITS internal data
+    -EINVAL: Inconsistent restored data
+    -EFAULT: Invalid guest ram access
+    -EBUSY:  One or more VCPUS are running
+    -EACCES: The virtual ITS is backed by a physical GICv4 ITS, and the
+            state is not available
+
+  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
+  Attributes:
+      The attr field of kvm_device_attr encodes the offset of the
+      ITS register, relative to the ITS control frame base address
+      (ITS_base).
+
+      kvm_device_attr.addr points to a __u64 value whatever the width
+      of the addressed register (32/64 bits). 64 bit registers can only
+      be accessed with full length.
+
+      Writes to read-only registers are ignored by the kernel except for:
+      - GITS_CREADR. It must be restored otherwise commands in the queue
+        will be re-executed after restoring CWRITER. GITS_CREADR must be
+        restored before restoring the GITS_CTLR which is likely to enable the
+        ITS. Also it must be restored after GITS_CBASER since a write to
+        GITS_CBASER resets GITS_CREADR.
+      - GITS_IIDR. The Revision field encodes the table layout ABI revision.
+        In the future we might implement direct injection of virtual LPIs.
+        This will require an upgrade of the table layout and an evolution of
+        the ABI. GITS_IIDR must be restored before calling
+        KVM_DEV_ARM_ITS_RESTORE_TABLES.
+
+      For other registers, getting or setting a register has the same
+      effect as reading/writing the register on real hardware.
+  Errors:
+    -ENXIO: Offset does not correspond to any supported register
+    -EFAULT: Invalid user pointer for attr->addr
+    -EINVAL: Offset is not 64-bit aligned
+    -EBUSY: one or more VCPUS are running
+
+ ITS Restore Sequence:
+ -------------------------
+
+The following ordering must be followed when restoring the GIC and the ITS:
+a) restore all guest memory and create vcpus
+b) restore all redistributors
+c) provide the ITS base address
+   (KVM_DEV_ARM_VGIC_GRP_ADDR)
+d) restore the ITS in the following order:
+   1. Restore GITS_CBASER
+   2. Restore all other GITS_ registers, except GITS_CTLR!
+   3. Load the ITS table data (KVM_DEV_ARM_ITS_RESTORE_TABLES)
+   4. Restore GITS_CTLR
+
+Then vcpus can be started.
+
+ ITS Table ABI REV0:
+ -------------------
+
+ Revision 0 of the ABI only supports the features of a virtual GICv3, and does
+ not support a virtual GICv4 with support for direct injection of virtual
+ interrupts for nested hypervisors.
+
+ The device table and ITT are indexed by the DeviceID and EventID,
+ respectively. The collection table is not indexed by CollectionID, and the
+ entries in the collection are listed in no particular order.
+ All entries are 8 bytes.
+
+ Device Table Entry (DTE):
+
+ bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
+ values:   | V |   next    | ITT_addr |  Size   |
+
+ where;
+ - V indicates whether the entry is valid. If not, other fields
+   are not meaningful.
+ - next: equals to 0 if this entry is the last one; otherwise it
+   corresponds to the DeviceID offset to the next DTE, capped by
+   2^14 -1.
+ - ITT_addr matches bits [51:8] of the ITT address (256 Byte aligned).
+ - Size specifies the supported number of bits for the EventID,
+   minus one
+
+ Collection Table Entry (CTE):
+
+ bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
+ values:   | V |    RES0    |  RDBase   |    ICID     |
+
+ where:
+ - V indicates whether the entry is valid. If not, other fields are
+   not meaningful.
+ - RES0: reserved field with Should-Be-Zero-or-Preserved behavior.
+ - RDBase is the PE number (GICR_TYPER.Processor_Number semantic),
+ - ICID is the collection ID
+
+ Interrupt Translation Entry (ITE):
+
+ bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
+ values:   |    next   |   pINTID  |  ICID    |
+
+ where:
+ - next: equals to 0 if this entry is the last one; otherwise it corresponds
+   to the EventID offset to the next ITE capped by 2^16 -1.
+ - pINTID is the physical LPI ID; if zero, it means the entry is not valid
+   and other fields are not meaningful.
+ - ICID is the collection ID
+
+ ITS Reset State:
+ ----------------
+
+RESET returns the ITS to the same state that it was when first created and
+initialized. When the RESET command returns, the following things are
+guaranteed:
+
+- The ITS is not enabled and quiescent
+  GITS_CTLR.Enabled = 0 .Quiescent=1
+- There is no internally cached state
+- No collection or device table are used
+  GITS_BASER<n>.Valid = 0
+- GITS_CBASER = 0, GITS_CREADR = 0, GITS_CWRITER = 0
+- The ABI version is unchanged and remains the one set when the ITS
+  device was first created.
diff --git a/Documentation/virt/kvm/devices/arm-vgic-v3.txt b/Documentation/virt/kvm/devices/arm-vgic-v3.txt
new file mode 100644 (file)
index 0000000..ff290b4
--- /dev/null
@@ -0,0 +1,251 @@
+ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
+==============================================================
+
+
+Device types supported:
+  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
+
+Only one VGIC instance may be instantiated through this API.  The created VGIC
+will act as the VM interrupt controller, requiring emulated user-space devices
+to inject interrupts to the VGIC instead of directly to CPUs.  It is not
+possible to create both a GICv3 and GICv2 on the same VM.
+
+Creating a guest GICv3 device requires a host GICv3 as well.
+
+
+Groups:
+  KVM_DEV_ARM_VGIC_GRP_ADDR
+  Attributes:
+    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3 distributor
+      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned and the region covers 64 KByte.
+
+    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3
+      redistributor register mappings. There are two 64K pages for each
+      VCPU and all of the redistributor pages are contiguous.
+      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned.
+
+    KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION (rw, 64-bit)
+      The attribute data pointed to by kvm_device_attr.addr is a __u64 value:
+      bits:     | 63   ....  52  |  51   ....   16 | 15 - 12  |11 - 0
+      values:   |     count      |       base      |  flags   | index
+      - index encodes the unique redistributor region index
+      - flags: reserved for future use, currently 0
+      - base field encodes bits [51:16] of the guest physical base address
+        of the first redistributor in the region.
+      - count encodes the number of redistributors in the region. Must be
+        greater than 0.
+      There are two 64K pages for each redistributor in the region and
+      redistributors are laid out contiguously within the region. Regions
+      are filled with redistributors in the index order. The sum of all
+      region count fields must be greater than or equal to the number of
+      VCPUs. Redistributor regions must be registered in the incremental
+      index order, starting from index 0.
+      The characteristics of a specific redistributor region can be read
+      by presetting the index field in the attr data.
+      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+
+  It is invalid to mix calls with KVM_VGIC_V3_ADDR_TYPE_REDIST and
+  KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attributes.
+
+  Errors:
+    -E2BIG:  Address outside of addressable IPA range
+    -EINVAL: Incorrectly aligned address, bad redistributor region
+             count/index, mixed redistributor region attribute usage
+    -EEXIST: Address already configured
+    -ENOENT: Attempt to read the characteristics of a non existing
+             redistributor region
+    -ENXIO:  The group or attribute is unknown/unsupported for this device
+             or hardware support is missing.
+    -EFAULT: Invalid user pointer for attr->addr.
+
+
+  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
+  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63   ....  32  |  31   ....    0 |
+    values:   |      mpidr     |      offset     |
+
+    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
+    __u32 value.  64-bit registers must be accessed by separately accessing the
+    lower and higher word.
+
+    Writes to read-only registers are ignored by the kernel.
+
+    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
+    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
+    specified by the mpidr.
+
+    The offset is relative to the "[Re]Distributor base address" as defined
+    in the GICv3/4 specs.  Getting or setting such a register has the same
+    effect as reading or writing the register on real hardware, except for the
+    following registers: GICD_STATUSR, GICR_STATUSR, GICD_ISPENDR,
+    GICR_ISPENDR0, GICD_ICPENDR, and GICR_ICPENDR0.  These registers behave
+    differently when accessed via this interface compared to their
+    architecturally defined behavior to allow software a full view of the
+    VGIC's internal state.
+
+    The mpidr field is used to specify which
+    redistributor is accessed.  The mpidr is ignored for the distributor.
+
+    The mpidr encoding is based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+
+    Note that distributor fields are not banked, but return the same value
+    regardless of the mpidr used to access the register.
+
+    GICD_IIDR.Revision is updated when the KVM implementation is changed in a
+    way directly observable by the guest or userspace.  Userspace should read
+    GICD_IIDR from KVM and write back the read value to confirm its expected
+    behavior is aligned with the KVM implementation.  Userspace should set
+    GICD_IIDR before setting any other registers to ensure the expected
+    behavior.
+
+
+    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
+    that a write of a clear bit has no effect, whereas a write with a set bit
+    clears that value.  To allow userspace to freely set the values of these two
+    registers, setting the attributes with the register offsets for these two
+    registers simply sets the non-reserved bits to the value written.
+
+
+    Accesses (reads and writes) to the GICD_ISPENDR register region and
+    GICR_ISPENDR0 registers get/set the value of the latched pending state for
+    the interrupts.
+
+    This is identical to the value returned by a guest read from ISPENDR for an
+    edge triggered interrupt, but may differ for level triggered interrupts.
+    For edge triggered interrupts, once an interrupt becomes pending (whether
+    because of an edge detected on the input line or because of a guest write
+    to ISPENDR) this state is "latched", and only cleared when either the
+    interrupt is activated or when the guest writes to ICPENDR. A level
+    triggered interrupt may be pending either because the level input is held
+    high by a device, or because of a guest write to the ISPENDR register. Only
+    ISPENDR writes are latched; if the device lowers the line level then the
+    interrupt is no longer pending unless the guest also wrote to ISPENDR, and
+    conversely writes to ICPENDR or activations of the interrupt do not clear
+    the pending status if the line level is still being held high.  (These
+    rules are documented in the GICv3 specification descriptions of the ICPENDR
+    and ISPENDR registers.) For a level triggered interrupt the value accessed
+    here is that of the latch which is set by ISPENDR and cleared by ICPENDR or
+    interrupt activation, whereas the value returned by a guest read from
+    ISPENDR is the logical OR of the latch value and the input line level.
+
+    Raw access to the latch state is provided to userspace so that it can save
+    and restore the entire GIC internal state (which is defined by the
+    combination of the current input line level and the latch state, and cannot
+    be deduced from purely the line level and the value of the ISPENDR
+    registers).
+
+    Accesses to GICD_ICPENDR register region and GICR_ICPENDR0 registers have
+    RAZ/WI semantics, meaning that reads always return 0 and writes are always
+    ignored.
+
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: One or more VCPUs are running
+
+
+  KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
+    values:   |         mpidr         |      RES     |    instr    |
+
+    The mpidr field encodes the CPU ID based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+
+    The instr field encodes the system register to access based on the fields
+    defined in the A64 instruction set encoding for system register access
+    (RES means the bits are reserved for future use and should be zero):
+
+      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
+      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
+
+    All system regs accessed through this API are (rw, 64-bit) and
+    kvm_device_attr.addr points to a __u64 value.
+
+    KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS accesses the CPU interface registers for the
+    CPU specified by the mpidr field.
+
+    CPU interface registers access is not implemented for AArch32 mode.
+    Error -ENXIO is returned when accessed in AArch32 mode.
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: VCPU is running
+    -EINVAL: Invalid mpidr or register value supplied
+
+
+  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
+  Attributes:
+    A value describing the number of interrupts (SGI, PPI and SPI) for
+    this GIC instance, ranging from 64 to 1024, in increments of 32.
+
+    kvm_device_attr.addr points to a __u32 value.
+
+  Errors:
+    -EINVAL: Value set is out of the expected range
+    -EBUSY: Value has already be set.
+
+
+  KVM_DEV_ARM_VGIC_GRP_CTRL
+  Attributes:
+    KVM_DEV_ARM_VGIC_CTRL_INIT
+      request the initialization of the VGIC, no additional parameter in
+      kvm_device_attr.addr.
+    KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES
+      save all LPI pending bits into guest RAM pending tables.
+
+      The first kB of the pending table is not altered by this operation.
+  Errors:
+    -ENXIO: VGIC not properly configured as required prior to calling
+     this attribute
+    -ENODEV: no online VCPU
+    -ENOMEM: memory shortage when allocating vgic internal data
+    -EFAULT: Invalid guest ram access
+    -EBUSY:  One or more VCPUS are running
+
+
+  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
+  Attributes:
+    The attr field of kvm_device_attr encodes the following values:
+    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
+    values:   |         mpidr         |      info       |   vINTID   |
+
+    The vINTID specifies which set of IRQs is reported on.
+
+    The info field specifies which information userspace wants to get or set
+    using this interface.  Currently we support the following info values:
+
+      VGIC_LEVEL_INFO_LINE_LEVEL:
+       Get/Set the input level of the IRQ line for a set of 32 contiguously
+       numbered interrupts.
+       vINTID must be a multiple of 32.
+
+       kvm_device_attr.addr points to a __u32 value which will contain a
+       bitmap where a set bit means the interrupt level is asserted.
+
+       Bit[n] indicates the status for interrupt vINTID + n.
+
+    SGIs and any interrupt with a higher ID than the number of interrupts
+    supported, will be RAZ/WI.  LPIs are always edge-triggered and are
+    therefore not supported by this interface.
+
+    PPIs are reported per VCPU as specified in the mpidr field, and SPIs are
+    reported with the same value regardless of the mpidr specified.
+
+    The mpidr field encodes the CPU ID based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+  Errors:
+    -EINVAL: vINTID is not multiple of 32 or
+     info field is not VGIC_LEVEL_INFO_LINE_LEVEL
diff --git a/Documentation/virt/kvm/devices/arm-vgic.txt b/Documentation/virt/kvm/devices/arm-vgic.txt
new file mode 100644 (file)
index 0000000..97b6518
--- /dev/null
@@ -0,0 +1,127 @@
+ARM Virtual Generic Interrupt Controller v2 (VGIC)
+==================================================
+
+Device types supported:
+  KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0
+
+Only one VGIC instance may be instantiated through either this API or the
+legacy KVM_CREATE_IRQCHIP API.  The created VGIC will act as the VM interrupt
+controller, requiring emulated user-space devices to inject interrupts to the
+VGIC instead of directly to CPUs.
+
+GICv3 implementations with hardware compatibility support allow creating a
+guest GICv2 through this interface.  For information on creating a guest GICv3
+device and guest ITS devices, see arm-vgic-v3.txt.  It is not possible to
+create both a GICv3 and GICv2 device on the same VM.
+
+
+Groups:
+  KVM_DEV_ARM_VGIC_GRP_ADDR
+  Attributes:
+    KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
+      Base address in the guest physical address space of the GIC distributor
+      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
+      This address needs to be 4K aligned and the region covers 4 KByte.
+
+    KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
+      Base address in the guest physical address space of the GIC virtual cpu
+      interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
+      This address needs to be 4K aligned and the region covers 4 KByte.
+  Errors:
+    -E2BIG:  Address outside of addressable IPA range
+    -EINVAL: Incorrectly aligned address
+    -EEXIST: Address already configured
+    -ENXIO:  The group or attribute is unknown/unsupported for this device
+             or hardware support is missing.
+    -EFAULT: Invalid user pointer for attr->addr.
+
+  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
+    values:   |    reserved   | vcpu_index |      offset     |
+
+    All distributor regs are (rw, 32-bit)
+
+    The offset is relative to the "Distributor base address" as defined in the
+    GICv2 specs.  Getting or setting such a register has the same effect as
+    reading or writing the register on the actual hardware from the cpu whose
+    index is specified with the vcpu_index field.  Note that most distributor
+    fields are not banked, but return the same value regardless of the
+    vcpu_index used to access the register.
+
+    GICD_IIDR.Revision is updated when the KVM implementation of an emulated
+    GICv2 is changed in a way directly observable by the guest or userspace.
+    Userspace should read GICD_IIDR from KVM and write back the read value to
+    confirm its expected behavior is aligned with the KVM implementation.
+    Userspace should set GICD_IIDR before setting any other registers (both
+    KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_CPU_REGS) to ensure
+    the expected behavior. Unless GICD_IIDR has been set from userspace, writes
+    to the interrupt group registers (GICD_IGROUPR) are ignored.
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: One or more VCPUs are running
+    -EINVAL: Invalid vcpu_index supplied
+
+  KVM_DEV_ARM_VGIC_GRP_CPU_REGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
+    values:   |    reserved   | vcpu_index |      offset     |
+
+    All CPU interface regs are (rw, 32-bit)
+
+    The offset specifies the offset from the "CPU interface base address" as
+    defined in the GICv2 specs.  Getting or setting such a register has the
+    same effect as reading or writing the register on the actual hardware.
+
+    The Active Priorities Registers APRn are implementation defined, so we set a
+    fixed format for our implementation that fits with the model of a "GICv2
+    implementation without the security extensions" which we present to the
+    guest.  This interface always exposes four register APR[0-3] describing the
+    maximum possible 128 preemption levels.  The semantics of the register
+    indicate if any interrupts in a given preemption level are in the active
+    state by setting the corresponding bit.
+
+    Thus, preemption level X has one or more active interrupts if and only if:
+
+      APRn[X mod 32] == 0b1,  where n = X / 32
+
+    Bits for undefined preemption levels are RAZ/WI.
+
+    Note that this differs from a CPU's view of the APRs on hardware in which
+    a GIC without the security extensions expose group 0 and group 1 active
+    priorities in separate register groups, whereas we show a combined view
+    similar to GICv2's GICH_APR.
+
+    For historical reasons and to provide ABI compatibility with userspace we
+    export the GICC_PMR register in the format of the GICH_VMCR.VMPriMask
+    field in the lower 5 bits of a word, meaning that userspace must always
+    use the lower 5 bits to communicate with the KVM device and must shift the
+    value left by 3 places to obtain the actual priority mask level.
+
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: One or more VCPUs are running
+    -EINVAL: Invalid vcpu_index supplied
+
+  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
+  Attributes:
+    A value describing the number of interrupts (SGI, PPI and SPI) for
+    this GIC instance, ranging from 64 to 1024, in increments of 32.
+
+  Errors:
+    -EINVAL: Value set is out of the expected range
+    -EBUSY: Value has already be set, or GIC has already been initialized
+            with default values.
+
+  KVM_DEV_ARM_VGIC_GRP_CTRL
+  Attributes:
+    KVM_DEV_ARM_VGIC_CTRL_INIT
+      request the initialization of the VGIC or ITS, no additional parameter
+      in kvm_device_attr.addr.
+  Errors:
+    -ENXIO: VGIC not properly configured as required prior to calling
+     this attribute
+    -ENODEV: no online VCPU
+    -ENOMEM: memory shortage when allocating vgic internal data
diff --git a/Documentation/virt/kvm/devices/mpic.txt b/Documentation/virt/kvm/devices/mpic.txt
new file mode 100644 (file)
index 0000000..8257397
--- /dev/null
@@ -0,0 +1,53 @@
+MPIC interrupt controller
+=========================
+
+Device types supported:
+  KVM_DEV_TYPE_FSL_MPIC_20     Freescale MPIC v2.0
+  KVM_DEV_TYPE_FSL_MPIC_42     Freescale MPIC v4.2
+
+Only one MPIC instance, of any type, may be instantiated.  The created
+MPIC will act as the system interrupt controller, connecting to each
+vcpu's interrupt inputs.
+
+Groups:
+  KVM_DEV_MPIC_GRP_MISC
+  Attributes:
+    KVM_DEV_MPIC_BASE_ADDR (rw, 64-bit)
+      Base address of the 256 KiB MPIC register space.  Must be
+      naturally aligned.  A value of zero disables the mapping.
+      Reset value is zero.
+
+  KVM_DEV_MPIC_GRP_REGISTER (rw, 32-bit)
+    Access an MPIC register, as if the access were made from the guest.
+    "attr" is the byte offset into the MPIC register space.  Accesses
+    must be 4-byte aligned.
+
+    MSIs may be signaled by using this attribute group to write
+    to the relevant MSIIR.
+
+  KVM_DEV_MPIC_GRP_IRQ_ACTIVE (rw, 32-bit)
+    IRQ input line for each standard openpic source.  0 is inactive and 1
+    is active, regardless of interrupt sense.
+
+    For edge-triggered interrupts:  Writing 1 is considered an activating
+    edge, and writing 0 is ignored.  Reading returns 1 if a previously
+    signaled edge has not been acknowledged, and 0 otherwise.
+
+    "attr" is the IRQ number.  IRQ numbers for standard sources are the
+    byte offset of the relevant IVPR from EIVPR0, divided by 32.
+
+IRQ Routing:
+
+  The MPIC emulation supports IRQ routing. Only a single MPIC device can
+  be instantiated. Once that device has been created, it's available as
+  irqchip id 0.
+
+  This irqchip 0 has 256 interrupt pins, which expose the interrupts in
+  the main array of interrupt sources (a.k.a. "SRC" interrupts).
+
+  The numbering is the same as the MPIC device tree binding -- based on
+  the register offset from the beginning of the sources array, without
+  regard to any subdivisions in chip documentation such as "internal"
+  or "external" interrupts.
+
+  Access to non-SRC interrupts is not implemented through IRQ routing mechanisms.
diff --git a/Documentation/virt/kvm/devices/s390_flic.txt b/Documentation/virt/kvm/devices/s390_flic.txt
new file mode 100644 (file)
index 0000000..a4e20a0
--- /dev/null
@@ -0,0 +1,163 @@
+FLIC (floating interrupt controller)
+====================================
+
+FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some
+machine check interruptions. All interrupts are stored in a per-vm list of
+pending interrupts. FLIC performs operations on this list.
+
+Only one FLIC instance may be instantiated.
+
+FLIC provides support to
+- add interrupts (KVM_DEV_FLIC_ENQUEUE)
+- inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS)
+- purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS)
+- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
+- enable/disable for the guest transparent async page faults
+- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
+- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
+- inject adapter interrupts on a specified adapter (KVM_DEV_FLIC_AIRQ_INJECT)
+- get/set all AIS mode states (KVM_DEV_FLIC_AISM_ALL)
+
+Groups:
+  KVM_DEV_FLIC_ENQUEUE
+    Passes a buffer and length into the kernel which are then injected into
+    the list of pending interrupts.
+    attr->addr contains the pointer to the buffer and attr->attr contains
+    the length of the buffer.
+    The format of the data structure kvm_s390_irq as it is copied from userspace
+    is defined in usr/include/linux/kvm.h.
+
+  KVM_DEV_FLIC_GET_ALL_IRQS
+    Copies all floating interrupts into a buffer provided by userspace.
+    When the buffer is too small it returns -ENOMEM, which is the indication
+    for userspace to try again with a bigger buffer.
+    -ENOBUFS is returned when the allocation of a kernelspace buffer has
+    failed.
+    -EFAULT is returned when copying data to userspace failed.
+    All interrupts remain pending, i.e. are not deleted from the list of
+    currently pending interrupts.
+    attr->addr contains the userspace address of the buffer into which all
+    interrupt data will be copied.
+    attr->attr contains the size of the buffer in bytes.
+
+  KVM_DEV_FLIC_CLEAR_IRQS
+    Simply deletes all elements from the list of currently pending floating
+    interrupts.  No interrupts are injected into the guest.
+
+  KVM_DEV_FLIC_CLEAR_IO_IRQ
+    Deletes one (if any) I/O interrupt for a subchannel identified by the
+    subsystem identification word passed via the buffer specified by
+    attr->addr (address) and attr->attr (length).
+
+  KVM_DEV_FLIC_APF_ENABLE
+    Enables async page faults for the guest. So in case of a major page fault
+    the host is allowed to handle this async and continues the guest.
+
+  KVM_DEV_FLIC_APF_DISABLE_WAIT
+    Disables async page faults for the guest and waits until already pending
+    async page faults are done. This is necessary to trigger a completion interrupt
+    for every init interrupt before migrating the interrupt list.
+
+  KVM_DEV_FLIC_ADAPTER_REGISTER
+    Register an I/O adapter interrupt source. Takes a kvm_s390_io_adapter
+    describing the adapter to register:
+
+struct kvm_s390_io_adapter {
+       __u32 id;
+       __u8 isc;
+       __u8 maskable;
+       __u8 swap;
+       __u8 flags;
+};
+
+   id contains the unique id for the adapter, isc the I/O interruption subclass
+   to use, maskable whether this adapter may be masked (interrupts turned off),
+   swap whether the indicators need to be byte swapped, and flags contains
+   further characteristics of the adapter.
+   Currently defined values for 'flags' are:
+   - KVM_S390_ADAPTER_SUPPRESSIBLE: adapter is subject to AIS
+     (adapter-interrupt-suppression) facility. This flag only has an effect if
+     the AIS capability is enabled.
+   Unknown flag values are ignored.
+
+
+  KVM_DEV_FLIC_ADAPTER_MODIFY
+    Modifies attributes of an existing I/O adapter interrupt source. Takes
+    a kvm_s390_io_adapter_req specifying the adapter and the operation:
+
+struct kvm_s390_io_adapter_req {
+       __u32 id;
+       __u8 type;
+       __u8 mask;
+       __u16 pad0;
+       __u64 addr;
+};
+
+    id specifies the adapter and type the operation. The supported operations
+    are:
+
+    KVM_S390_IO_ADAPTER_MASK
+      mask or unmask the adapter, as specified in mask
+
+    KVM_S390_IO_ADAPTER_MAP
+      perform a gmap translation for the guest address provided in addr,
+      pin a userspace page for the translated address and add it to the
+      list of mappings
+      Note: A new mapping will be created unconditionally; therefore,
+            the calling code should avoid making duplicate mappings.
+
+    KVM_S390_IO_ADAPTER_UNMAP
+      release a userspace page for the translated address specified in addr
+      from the list of mappings
+
+  KVM_DEV_FLIC_AISM
+    modify the adapter-interruption-suppression mode for a given isc if the
+    AIS capability is enabled. Takes a kvm_s390_ais_req describing:
+
+struct kvm_s390_ais_req {
+       __u8 isc;
+       __u16 mode;
+};
+
+    isc contains the target I/O interruption subclass, mode the target
+    adapter-interruption-suppression mode. The following modes are
+    currently supported:
+    - KVM_S390_AIS_MODE_ALL: ALL-Interruptions Mode, i.e. airq injection
+      is always allowed;
+    - KVM_S390_AIS_MODE_SINGLE: SINGLE-Interruption Mode, i.e. airq
+      injection is only allowed once and the following adapter interrupts
+      will be suppressed until the mode is set again to ALL-Interruptions
+      or SINGLE-Interruption mode.
+
+  KVM_DEV_FLIC_AIRQ_INJECT
+    Inject adapter interrupts on a specified adapter.
+    attr->attr contains the unique id for the adapter, which allows for
+    adapter-specific checks and actions.
+    For adapters subject to AIS, handle the airq injection suppression for
+    an isc according to the adapter-interruption-suppression mode on condition
+    that the AIS capability is enabled.
+
+  KVM_DEV_FLIC_AISM_ALL
+    Gets or sets the adapter-interruption-suppression mode for all ISCs. Takes
+    a kvm_s390_ais_all describing:
+
+struct kvm_s390_ais_all {
+       __u8 simm; /* Single-Interruption-Mode mask */
+       __u8 nimm; /* No-Interruption-Mode mask *
+};
+
+    simm contains Single-Interruption-Mode mask for all ISCs, nimm contains
+    No-Interruption-Mode mask for all ISCs. Each bit in simm and nimm corresponds
+    to an ISC (MSB0 bit 0 to ISC 0 and so on). The combination of simm bit and
+    nimm bit presents AIS mode for a ISC.
+
+    KVM_DEV_FLIC_AISM_ALL is indicated by KVM_CAP_S390_AIS_MIGRATION.
+
+Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
+FLIC with an unknown group or attribute gives the error code EINVAL (instead of
+ENXIO, as specified in the API documentation). It is not possible to conclude
+that a FLIC operation is unavailable based on the error code resulting from a
+usage attempt.
+
+Note: The KVM_DEV_FLIC_CLEAR_IO_IRQ ioctl will return EINVAL in case a zero
+schid is specified.
diff --git a/Documentation/virt/kvm/devices/vcpu.txt b/Documentation/virt/kvm/devices/vcpu.txt
new file mode 100644 (file)
index 0000000..2b5dab1
--- /dev/null
@@ -0,0 +1,62 @@
+Generic vcpu interface
+====================================
+
+The virtual cpu "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
+KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same struct
+kvm_device_attr as other devices, but targets VCPU-wide settings and controls.
+
+The groups and attributes per virtual cpu, if any, are architecture specific.
+
+1. GROUP: KVM_ARM_VCPU_PMU_V3_CTRL
+Architectures: ARM64
+
+1.1. ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_IRQ
+Parameters: in kvm_device_attr.addr the address for PMU overflow interrupt is a
+            pointer to an int
+Returns: -EBUSY: The PMU overflow interrupt is already set
+         -ENXIO: The overflow interrupt not set when attempting to get it
+         -ENODEV: PMUv3 not supported
+         -EINVAL: Invalid PMU overflow interrupt number supplied or
+                  trying to set the IRQ number without using an in-kernel
+                  irqchip.
+
+A value describing the PMUv3 (Performance Monitor Unit v3) overflow interrupt
+number for this vcpu. This interrupt could be a PPI or SPI, but the interrupt
+type must be same for each vcpu. As a PPI, the interrupt number is the same for
+all vcpus, while as an SPI it must be a separate number per vcpu.
+
+1.2 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_INIT
+Parameters: no additional parameter in kvm_device_attr.addr
+Returns: -ENODEV: PMUv3 not supported or GIC not initialized
+         -ENXIO: PMUv3 not properly configured or in-kernel irqchip not
+                 configured as required prior to calling this attribute
+         -EBUSY: PMUv3 already initialized
+
+Request the initialization of the PMUv3.  If using the PMUv3 with an in-kernel
+virtual GIC implementation, this must be done after initializing the in-kernel
+irqchip.
+
+
+2. GROUP: KVM_ARM_VCPU_TIMER_CTRL
+Architectures: ARM,ARM64
+
+2.1. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_VTIMER
+2.2. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_PTIMER
+Parameters: in kvm_device_attr.addr the address for the timer interrupt is a
+            pointer to an int
+Returns: -EINVAL: Invalid timer interrupt number
+         -EBUSY:  One or more VCPUs has already run
+
+A value describing the architected timer interrupt number when connected to an
+in-kernel virtual GIC.  These must be a PPI (16 <= intid < 32).  Setting the
+attribute overrides the default values (see below).
+
+KVM_ARM_VCPU_TIMER_IRQ_VTIMER: The EL1 virtual timer intid (default: 27)
+KVM_ARM_VCPU_TIMER_IRQ_PTIMER: The EL1 physical timer intid (default: 30)
+
+Setting the same PPI for different timers will prevent the VCPUs from running.
+Setting the interrupt number on a VCPU configures all VCPUs created at that
+time to use the number provided for a given timer, overwriting any previously
+configured values on other VCPUs.  Userspace should configure the interrupt
+numbers on at least one VCPU after creating all VCPUs and before running any
+VCPUs.
diff --git a/Documentation/virt/kvm/devices/vfio.txt b/Documentation/virt/kvm/devices/vfio.txt
new file mode 100644 (file)
index 0000000..528c77c
--- /dev/null
@@ -0,0 +1,36 @@
+VFIO virtual device
+===================
+
+Device types supported:
+  KVM_DEV_TYPE_VFIO
+
+Only one VFIO instance may be created per VM.  The created device
+tracks VFIO groups in use by the VM and features of those groups
+important to the correctness and acceleration of the VM.  As groups
+are enabled and disabled for use by the VM, KVM should be updated
+about their presence.  When registered with KVM, a reference to the
+VFIO-group is held by KVM.
+
+Groups:
+  KVM_DEV_VFIO_GROUP
+
+KVM_DEV_VFIO_GROUP attributes:
+  KVM_DEV_VFIO_GROUP_ADD: Add a VFIO group to VFIO-KVM device tracking
+       kvm_device_attr.addr points to an int32_t file descriptor
+       for the VFIO group.
+  KVM_DEV_VFIO_GROUP_DEL: Remove a VFIO group from VFIO-KVM device tracking
+       kvm_device_attr.addr points to an int32_t file descriptor
+       for the VFIO group.
+  KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE: attaches a guest visible TCE table
+       allocated by sPAPR KVM.
+       kvm_device_attr.addr points to a struct:
+
+       struct kvm_vfio_spapr_tce {
+               __s32   groupfd;
+               __s32   tablefd;
+       };
+
+       where
+       @groupfd is a file descriptor for a VFIO group;
+       @tablefd is a file descriptor for a TCE table allocated via
+               KVM_CREATE_SPAPR_TCE.
diff --git a/Documentation/virt/kvm/devices/vm.txt b/Documentation/virt/kvm/devices/vm.txt
new file mode 100644 (file)
index 0000000..4ffb82b
--- /dev/null
@@ -0,0 +1,270 @@
+Generic vm interface
+====================================
+
+The virtual machine "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
+KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same
+struct kvm_device_attr as other devices, but targets VM-wide settings
+and controls.
+
+The groups and attributes per virtual machine, if any, are architecture
+specific.
+
+1. GROUP: KVM_S390_VM_MEM_CTRL
+Architectures: s390
+
+1.1. ATTRIBUTE: KVM_S390_VM_MEM_ENABLE_CMMA
+Parameters: none
+Returns: -EBUSY if a vcpu is already defined, otherwise 0
+
+Enables Collaborative Memory Management Assist (CMMA) for the virtual machine.
+
+1.2. ATTRIBUTE: KVM_S390_VM_MEM_CLR_CMMA
+Parameters: none
+Returns: -EINVAL if CMMA was not enabled
+         0 otherwise
+
+Clear the CMMA status for all guest pages, so any pages the guest marked
+as unused are again used any may not be reclaimed by the host.
+
+1.3. ATTRIBUTE KVM_S390_VM_MEM_LIMIT_SIZE
+Parameters: in attr->addr the address for the new limit of guest memory
+Returns: -EFAULT if the given address is not accessible
+         -EINVAL if the virtual machine is of type UCONTROL
+         -E2BIG if the given guest memory is to big for that machine
+         -EBUSY if a vcpu is already defined
+         -ENOMEM if not enough memory is available for a new shadow guest mapping
+          0 otherwise
+
+Allows userspace to query the actual limit and set a new limit for
+the maximum guest memory size. The limit will be rounded up to
+2048 MB, 4096 GB, 8192 TB respectively, as this limit is governed by
+the number of page table levels. In the case that there is no limit we will set
+the limit to KVM_S390_NO_MEM_LIMIT (U64_MAX).
+
+2. GROUP: KVM_S390_VM_CPU_MODEL
+Architectures: s390
+
+2.1. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE (r/o)
+
+Allows user space to retrieve machine and kvm specific cpu related information:
+
+struct kvm_s390_vm_cpu_machine {
+       __u64 cpuid;           # CPUID of host
+       __u32 ibc;             # IBC level range offered by host
+       __u8  pad[4];
+       __u64 fac_mask[256];   # set of cpu facilities enabled by KVM
+       __u64 fac_list[256];   # set of cpu facilities offered by host
+}
+
+Parameters: address of buffer to store the machine related cpu data
+            of type struct kvm_s390_vm_cpu_machine*
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           -ENOMEM if not enough memory is available to process the ioctl
+           0 in case of success
+
+2.2. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR (r/w)
+
+Allows user space to retrieve or request to change cpu related information for a vcpu:
+
+struct kvm_s390_vm_cpu_processor {
+       __u64 cpuid;           # CPUID currently (to be) used by this vcpu
+       __u16 ibc;             # IBC level currently (to be) used by this vcpu
+       __u8  pad[6];
+       __u64 fac_list[256];   # set of cpu facilities currently (to be) used
+                              # by this vcpu
+}
+
+KVM does not enforce or limit the cpu model data in any form. Take the information
+retrieved by means of KVM_S390_VM_CPU_MACHINE as hint for reasonable configuration
+setups. Instruction interceptions triggered by additionally set facility bits that
+are not handled by KVM need to by imlemented in the VM driver code.
+
+Parameters: address of buffer to store/set the processor related cpu
+           data of type struct kvm_s390_vm_cpu_processor*.
+Returns:    -EBUSY in case 1 or more vcpus are already activated (only in write case)
+           -EFAULT if the given address is not accessible from kernel space
+           -ENOMEM if not enough memory is available to process the ioctl
+           0 in case of success
+
+2.3. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE_FEAT (r/o)
+
+Allows user space to retrieve available cpu features. A feature is available if
+provided by the hardware and supported by kvm. In theory, cpu features could
+even be completely emulated by kvm.
+
+struct kvm_s390_vm_cpu_feat {
+        __u64 feat[16]; # Bitmap (1 = feature available), MSB 0 bit numbering
+};
+
+Parameters: address of a buffer to load the feature list from.
+Returns:    -EFAULT if the given address is not accessible from kernel space.
+           0 in case of success.
+
+2.4. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR_FEAT (r/w)
+
+Allows user space to retrieve or change enabled cpu features for all VCPUs of a
+VM. Features that are not available cannot be enabled.
+
+See 2.3. for a description of the parameter struct.
+
+Parameters: address of a buffer to store/load the feature list from.
+Returns:    -EFAULT if the given address is not accessible from kernel space.
+           -EINVAL if a cpu feature that is not available is to be enabled.
+           -EBUSY if at least one VCPU has already been defined.
+           0 in case of success.
+
+2.5. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE_SUBFUNC (r/o)
+
+Allows user space to retrieve available cpu subfunctions without any filtering
+done by a set IBC. These subfunctions are indicated to the guest VCPU via
+query or "test bit" subfunctions and used e.g. by cpacf functions, plo and ptff.
+
+A subfunction block is only valid if KVM_S390_VM_CPU_MACHINE contains the
+STFL(E) bit introducing the affected instruction. If the affected instruction
+indicates subfunctions via a "query subfunction", the response block is
+contained in the returned struct. If the affected instruction
+indicates subfunctions via a "test bit" mechanism, the subfunction codes are
+contained in the returned struct in MSB 0 bit numbering.
+
+struct kvm_s390_vm_cpu_subfunc {
+       u8 plo[32];           # always valid (ESA/390 feature)
+       u8 ptff[16];          # valid with TOD-clock steering
+       u8 kmac[16];          # valid with Message-Security-Assist
+       u8 kmc[16];           # valid with Message-Security-Assist
+       u8 km[16];            # valid with Message-Security-Assist
+       u8 kimd[16];          # valid with Message-Security-Assist
+       u8 klmd[16];          # valid with Message-Security-Assist
+       u8 pckmo[16];         # valid with Message-Security-Assist-Extension 3
+       u8 kmctr[16];         # valid with Message-Security-Assist-Extension 4
+       u8 kmf[16];           # valid with Message-Security-Assist-Extension 4
+       u8 kmo[16];           # valid with Message-Security-Assist-Extension 4
+       u8 pcc[16];           # valid with Message-Security-Assist-Extension 4
+       u8 ppno[16];          # valid with Message-Security-Assist-Extension 5
+       u8 kma[16];           # valid with Message-Security-Assist-Extension 8
+       u8 kdsa[16];          # valid with Message-Security-Assist-Extension 9
+       u8 reserved[1792];    # reserved for future instructions
+};
+
+Parameters: address of a buffer to load the subfunction blocks from.
+Returns:    -EFAULT if the given address is not accessible from kernel space.
+           0 in case of success.
+
+2.6. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR_SUBFUNC (r/w)
+
+Allows user space to retrieve or change cpu subfunctions to be indicated for
+all VCPUs of a VM. This attribute will only be available if kernel and
+hardware support are in place.
+
+The kernel uses the configured subfunction blocks for indication to
+the guest. A subfunction block will only be used if the associated STFL(E) bit
+has not been disabled by user space (so the instruction to be queried is
+actually available for the guest).
+
+As long as no data has been written, a read will fail. The IBC will be used
+to determine available subfunctions in this case, this will guarantee backward
+compatibility.
+
+See 2.5. for a description of the parameter struct.
+
+Parameters: address of a buffer to store/load the subfunction blocks from.
+Returns:    -EFAULT if the given address is not accessible from kernel space.
+           -EINVAL when reading, if there was no write yet.
+           -EBUSY if at least one VCPU has already been defined.
+           0 in case of success.
+
+3. GROUP: KVM_S390_VM_TOD
+Architectures: s390
+
+3.1. ATTRIBUTE: KVM_S390_VM_TOD_HIGH
+
+Allows user space to set/get the TOD clock extension (u8) (superseded by
+KVM_S390_VM_TOD_EXT).
+
+Parameters: address of a buffer in user space to store the data (u8) to
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           -EINVAL if setting the TOD clock extension to != 0 is not supported
+
+3.2. ATTRIBUTE: KVM_S390_VM_TOD_LOW
+
+Allows user space to set/get bits 0-63 of the TOD clock register as defined in
+the POP (u64).
+
+Parameters: address of a buffer in user space to store the data (u64) to
+Returns:    -EFAULT if the given address is not accessible from kernel space
+
+3.3. ATTRIBUTE: KVM_S390_VM_TOD_EXT
+Allows user space to set/get bits 0-63 of the TOD clock register as defined in
+the POP (u64). If the guest CPU model supports the TOD clock extension (u8), it
+also allows user space to get/set it. If the guest CPU model does not support
+it, it is stored as 0 and not allowed to be set to a value != 0.
+
+Parameters: address of a buffer in user space to store the data
+            (kvm_s390_vm_tod_clock) to
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           -EINVAL if setting the TOD clock extension to != 0 is not supported
+
+4. GROUP: KVM_S390_VM_CRYPTO
+Architectures: s390
+
+4.1. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_AES_KW (w/o)
+
+Allows user space to enable aes key wrapping, including generating a new
+wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.2. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_DEA_KW (w/o)
+
+Allows user space to enable dea key wrapping, including generating a new
+wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.3. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_AES_KW (w/o)
+
+Allows user space to disable aes key wrapping, clearing the wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.4. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_DEA_KW (w/o)
+
+Allows user space to disable dea key wrapping, clearing the wrapping key.
+
+Parameters: none
+Returns:    0
+
+5. GROUP: KVM_S390_VM_MIGRATION
+Architectures: s390
+
+5.1. ATTRIBUTE: KVM_S390_VM_MIGRATION_STOP (w/o)
+
+Allows userspace to stop migration mode, needed for PGSTE migration.
+Setting this attribute when migration mode is not active will have no
+effects.
+
+Parameters: none
+Returns:    0
+
+5.2. ATTRIBUTE: KVM_S390_VM_MIGRATION_START (w/o)
+
+Allows userspace to start migration mode, needed for PGSTE migration.
+Setting this attribute when migration mode is already active will have
+no effects.
+
+Parameters: none
+Returns:    -ENOMEM if there is not enough free memory to start migration mode
+           -EINVAL if the state of the VM is invalid (e.g. no memory defined)
+           0 in case of success.
+
+5.3. ATTRIBUTE: KVM_S390_VM_MIGRATION_STATUS (r/o)
+
+Allows userspace to query the status of migration mode.
+
+Parameters: address of a buffer in user space to store the data (u64) to;
+           the data itself is either 0 if migration mode is disabled or 1
+           if it is enabled
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           0 in case of success.
diff --git a/Documentation/virt/kvm/devices/xics.txt b/Documentation/virt/kvm/devices/xics.txt
new file mode 100644 (file)
index 0000000..4286493
--- /dev/null
@@ -0,0 +1,66 @@
+XICS interrupt controller
+
+Device type supported: KVM_DEV_TYPE_XICS
+
+Groups:
+  KVM_DEV_XICS_SOURCES
+  Attributes: One per interrupt source, indexed by the source number.
+
+This device emulates the XICS (eXternal Interrupt Controller
+Specification) defined in PAPR.  The XICS has a set of interrupt
+sources, each identified by a 20-bit source number, and a set of
+Interrupt Control Presentation (ICP) entities, also called "servers",
+each associated with a virtual CPU.
+
+The ICP entities are created by enabling the KVM_CAP_IRQ_ARCH
+capability for each vcpu, specifying KVM_CAP_IRQ_XICS in args[0] and
+the interrupt server number (i.e. the vcpu number from the XICS's
+point of view) in args[1] of the kvm_enable_cap struct.  Each ICP has
+64 bits of state which can be read and written using the
+KVM_GET_ONE_REG and KVM_SET_ONE_REG ioctls on the vcpu.  The 64 bit
+state word has the following bitfields, starting at the
+least-significant end of the word:
+
+* Unused, 16 bits
+
+* Pending interrupt priority, 8 bits
+  Zero is the highest priority, 255 means no interrupt is pending.
+
+* Pending IPI (inter-processor interrupt) priority, 8 bits
+  Zero is the highest priority, 255 means no IPI is pending.
+
+* Pending interrupt source number, 24 bits
+  Zero means no interrupt pending, 2 means an IPI is pending
+
+* Current processor priority, 8 bits
+  Zero is the highest priority, meaning no interrupts can be
+  delivered, and 255 is the lowest priority.
+
+Each source has 64 bits of state that can be read and written using
+the KVM_GET_DEVICE_ATTR and KVM_SET_DEVICE_ATTR ioctls, specifying the
+KVM_DEV_XICS_SOURCES attribute group, with the attribute number being
+the interrupt source number.  The 64 bit state word has the following
+bitfields, starting from the least-significant end of the word:
+
+* Destination (server number), 32 bits
+  This specifies where the interrupt should be sent, and is the
+  interrupt server number specified for the destination vcpu.
+
+* Priority, 8 bits
+  This is the priority specified for this interrupt source, where 0 is
+  the highest priority and 255 is the lowest.  An interrupt with a
+  priority of 255 will never be delivered.
+
+* Level sensitive flag, 1 bit
+  This bit is 1 for a level-sensitive interrupt source, or 0 for
+  edge-sensitive (or MSI).
+
+* Masked flag, 1 bit
+  This bit is set to 1 if the interrupt is masked (cannot be delivered
+  regardless of its priority), for example by the ibm,int-off RTAS
+  call, or 0 if it is not masked.
+
+* Pending flag, 1 bit
+  This bit is 1 if the source has a pending interrupt, otherwise 0.
+
+Only one XICS instance may be created per VM.
diff --git a/Documentation/virt/kvm/devices/xive.txt b/Documentation/virt/kvm/devices/xive.txt
new file mode 100644 (file)
index 0000000..9a24a45
--- /dev/null
@@ -0,0 +1,197 @@
+POWER9 eXternal Interrupt Virtualization Engine (XIVE Gen1)
+==========================================================
+
+Device types supported:
+  KVM_DEV_TYPE_XIVE     POWER9 XIVE Interrupt Controller generation 1
+
+This device acts as a VM interrupt controller. It provides the KVM
+interface to configure the interrupt sources of a VM in the underlying
+POWER9 XIVE interrupt controller.
+
+Only one XIVE instance may be instantiated. A guest XIVE device
+requires a POWER9 host and the guest OS should have support for the
+XIVE native exploitation interrupt mode. If not, it should run using
+the legacy interrupt mode, referred as XICS (POWER7/8).
+
+* Device Mappings
+
+  The KVM device exposes different MMIO ranges of the XIVE HW which
+  are required for interrupt management. These are exposed to the
+  guest in VMAs populated with a custom VM fault handler.
+
+  1. Thread Interrupt Management Area (TIMA)
+
+  Each thread has an associated Thread Interrupt Management context
+  composed of a set of registers. These registers let the thread
+  handle priority management and interrupt acknowledgment. The most
+  important are :
+
+      - Interrupt Pending Buffer     (IPB)
+      - Current Processor Priority   (CPPR)
+      - Notification Source Register (NSR)
+
+  They are exposed to software in four different pages each proposing
+  a view with a different privilege. The first page is for the
+  physical thread context and the second for the hypervisor. Only the
+  third (operating system) and the fourth (user level) are exposed the
+  guest.
+
+  2. Event State Buffer (ESB)
+
+  Each source is associated with an Event State Buffer (ESB) with
+  either a pair of even/odd pair of pages which provides commands to
+  manage the source: to trigger, to EOI, to turn off the source for
+  instance.
+
+  3. Device pass-through
+
+  When a device is passed-through into the guest, the source
+  interrupts are from a different HW controller (PHB4) and the ESB
+  pages exposed to the guest should accommadate this change.
+
+  The passthru_irq helpers, kvmppc_xive_set_mapped() and
+  kvmppc_xive_clr_mapped() are called when the device HW irqs are
+  mapped into or unmapped from the guest IRQ number space. The KVM
+  device extends these helpers to clear the ESB pages of the guest IRQ
+  number being mapped and then lets the VM fault handler repopulate.
+  The handler will insert the ESB page corresponding to the HW
+  interrupt of the device being passed-through or the initial IPI ESB
+  page if the device has being removed.
+
+  The ESB remapping is fully transparent to the guest and the OS
+  device driver. All handling is done within VFIO and the above
+  helpers in KVM-PPC.
+
+* Groups:
+
+  1. KVM_DEV_XIVE_GRP_CTRL
+  Provides global controls on the device
+  Attributes:
+    1.1 KVM_DEV_XIVE_RESET (write only)
+    Resets the interrupt controller configuration for sources and event
+    queues. To be used by kexec and kdump.
+    Errors: none
+
+    1.2 KVM_DEV_XIVE_EQ_SYNC (write only)
+    Sync all the sources and queues and mark the EQ pages dirty. This
+    to make sure that a consistent memory state is captured when
+    migrating the VM.
+    Errors: none
+
+  2. KVM_DEV_XIVE_GRP_SOURCE (write only)
+  Initializes a new source in the XIVE device and mask it.
+  Attributes:
+    Interrupt source number  (64-bit)
+  The kvm_device_attr.addr points to a __u64 value:
+  bits:     | 63   ....  2 |   1   |   0
+  values:   |    unused    | level | type
+  - type:  0:MSI 1:LSI
+  - level: assertion level in case of an LSI.
+  Errors:
+    -E2BIG:  Interrupt source number is out of range
+    -ENOMEM: Could not create a new source block
+    -EFAULT: Invalid user pointer for attr->addr.
+    -ENXIO:  Could not allocate underlying HW interrupt
+
+  3. KVM_DEV_XIVE_GRP_SOURCE_CONFIG (write only)
+  Configures source targeting
+  Attributes:
+    Interrupt source number  (64-bit)
+  The kvm_device_attr.addr points to a __u64 value:
+  bits:     | 63   ....  33 |  32  | 31 .. 3 |  2 .. 0
+  values:   |    eisn       | mask |  server | priority
+  - priority: 0-7 interrupt priority level
+  - server: CPU number chosen to handle the interrupt
+  - mask: mask flag (unused)
+  - eisn: Effective Interrupt Source Number
+  Errors:
+    -ENOENT: Unknown source number
+    -EINVAL: Not initialized source number
+    -EINVAL: Invalid priority
+    -EINVAL: Invalid CPU number.
+    -EFAULT: Invalid user pointer for attr->addr.
+    -ENXIO:  CPU event queues not configured or configuration of the
+             underlying HW interrupt failed
+    -EBUSY:  No CPU available to serve interrupt
+
+  4. KVM_DEV_XIVE_GRP_EQ_CONFIG (read-write)
+  Configures an event queue of a CPU
+  Attributes:
+    EQ descriptor identifier (64-bit)
+  The EQ descriptor identifier is a tuple (server, priority) :
+  bits:     | 63   ....  32 | 31 .. 3 |  2 .. 0
+  values:   |    unused     |  server | priority
+  The kvm_device_attr.addr points to :
+    struct kvm_ppc_xive_eq {
+       __u32 flags;
+       __u32 qshift;
+       __u64 qaddr;
+       __u32 qtoggle;
+       __u32 qindex;
+       __u8  pad[40];
+    };
+  - flags: queue flags
+    KVM_XIVE_EQ_ALWAYS_NOTIFY (required)
+       forces notification without using the coalescing mechanism
+       provided by the XIVE END ESBs.
+  - qshift: queue size (power of 2)
+  - qaddr: real address of queue
+  - qtoggle: current queue toggle bit
+  - qindex: current queue index
+  - pad: reserved for future use
+  Errors:
+    -ENOENT: Invalid CPU number
+    -EINVAL: Invalid priority
+    -EINVAL: Invalid flags
+    -EINVAL: Invalid queue size
+    -EINVAL: Invalid queue address
+    -EFAULT: Invalid user pointer for attr->addr.
+    -EIO:    Configuration of the underlying HW failed
+
+  5. KVM_DEV_XIVE_GRP_SOURCE_SYNC (write only)
+  Synchronize the source to flush event notifications
+  Attributes:
+    Interrupt source number  (64-bit)
+  Errors:
+    -ENOENT: Unknown source number
+    -EINVAL: Not initialized source number
+
+* VCPU state
+
+  The XIVE IC maintains VP interrupt state in an internal structure
+  called the NVT. When a VP is not dispatched on a HW processor
+  thread, this structure can be updated by HW if the VP is the target
+  of an event notification.
+
+  It is important for migration to capture the cached IPB from the NVT
+  as it synthesizes the priorities of the pending interrupts. We
+  capture a bit more to report debug information.
+
+  KVM_REG_PPC_VP_STATE (2 * 64bits)
+  bits:     |  63  ....  32  |  31  ....  0  |
+  values:   |   TIMA word0   |   TIMA word1  |
+  bits:     | 127       ..........       64  |
+  values:   |            unused              |
+
+* Migration:
+
+  Saving the state of a VM using the XIVE native exploitation mode
+  should follow a specific sequence. When the VM is stopped :
+
+  1. Mask all sources (PQ=01) to stop the flow of events.
+
+  2. Sync the XIVE device with the KVM control KVM_DEV_XIVE_EQ_SYNC to
+  flush any in-flight event notification and to stabilize the EQs. At
+  this stage, the EQ pages are marked dirty to make sure they are
+  transferred in the migration sequence.
+
+  3. Capture the state of the source targeting, the EQs configuration
+  and the state of thread interrupt context registers.
+
+  Restore is similar :
+
+  1. Restore the EQ configuration. As targeting depends on it.
+  2. Restore targeting
+  3. Restore the thread interrupt contexts
+  4. Restore the source states
+  5. Let the vCPU run
diff --git a/Documentation/virt/kvm/halt-polling.txt b/Documentation/virt/kvm/halt-polling.txt
new file mode 100644 (file)
index 0000000..4f791b1
--- /dev/null
@@ -0,0 +1,136 @@
+The KVM halt polling system
+===========================
+
+The KVM halt polling system provides a feature within KVM whereby the latency
+of a guest can, under some circumstances, be reduced by polling in the host
+for some time period after the guest has elected to no longer run by cedeing.
+That is, when a guest vcpu has ceded, or in the case of powerpc when all of the
+vcpus of a single vcore have ceded, the host kernel polls for wakeup conditions
+before giving up the cpu to the scheduler in order to let something else run.
+
+Polling provides a latency advantage in cases where the guest can be run again
+very quickly by at least saving us a trip through the scheduler, normally on
+the order of a few micro-seconds, although performance benefits are workload
+dependant. In the event that no wakeup source arrives during the polling
+interval or some other task on the runqueue is runnable the scheduler is
+invoked. Thus halt polling is especially useful on workloads with very short
+wakeup periods where the time spent halt polling is minimised and the time
+savings of not invoking the scheduler are distinguishable.
+
+The generic halt polling code is implemented in:
+
+       virt/kvm/kvm_main.c: kvm_vcpu_block()
+
+The powerpc kvm-hv specific case is implemented in:
+
+       arch/powerpc/kvm/book3s_hv.c: kvmppc_vcore_blocked()
+
+Halt Polling Interval
+=====================
+
+The maximum time for which to poll before invoking the scheduler, referred to
+as the halt polling interval, is increased and decreased based on the perceived
+effectiveness of the polling in an attempt to limit pointless polling.
+This value is stored in either the vcpu struct:
+
+       kvm_vcpu->halt_poll_ns
+
+or in the case of powerpc kvm-hv, in the vcore struct:
+
+       kvmppc_vcore->halt_poll_ns
+
+Thus this is a per vcpu (or vcore) value.
+
+During polling if a wakeup source is received within the halt polling interval,
+the interval is left unchanged. In the event that a wakeup source isn't
+received during the polling interval (and thus schedule is invoked) there are
+two options, either the polling interval and total block time[0] were less than
+the global max polling interval (see module params below), or the total block
+time was greater than the global max polling interval.
+
+In the event that both the polling interval and total block time were less than
+the global max polling interval then the polling interval can be increased in
+the hope that next time during the longer polling interval the wake up source
+will be received while the host is polling and the latency benefits will be
+received. The polling interval is grown in the function grow_halt_poll_ns() and
+is multiplied by the module parameters halt_poll_ns_grow and
+halt_poll_ns_grow_start.
+
+In the event that the total block time was greater than the global max polling
+interval then the host will never poll for long enough (limited by the global
+max) to wakeup during the polling interval so it may as well be shrunk in order
+to avoid pointless polling. The polling interval is shrunk in the function
+shrink_halt_poll_ns() and is divided by the module parameter
+halt_poll_ns_shrink, or set to 0 iff halt_poll_ns_shrink == 0.
+
+It is worth noting that this adjustment process attempts to hone in on some
+steady state polling interval but will only really do a good job for wakeups
+which come at an approximately constant rate, otherwise there will be constant
+adjustment of the polling interval.
+
+[0] total block time: the time between when the halt polling function is
+                     invoked and a wakeup source received (irrespective of
+                     whether the scheduler is invoked within that function).
+
+Module Parameters
+=================
+
+The kvm module has 3 tuneable module parameters to adjust the global max
+polling interval as well as the rate at which the polling interval is grown and
+shrunk. These variables are defined in include/linux/kvm_host.h and as module
+parameters in virt/kvm/kvm_main.c, or arch/powerpc/kvm/book3s_hv.c in the
+powerpc kvm-hv case.
+
+Module Parameter       |   Description             |        Default Value
+--------------------------------------------------------------------------------
+halt_poll_ns           | The global max polling    | KVM_HALT_POLL_NS_DEFAULT
+                       | interval which defines    |
+                       | the ceiling value of the  |
+                       | polling interval for      | (per arch value)
+                       | each vcpu.                |
+--------------------------------------------------------------------------------
+halt_poll_ns_grow      | The value by which the    | 2
+                       | halt polling interval is  |
+                       | multiplied in the         |
+                       | grow_halt_poll_ns()       |
+                       | function.                 |
+--------------------------------------------------------------------------------
+halt_poll_ns_grow_start | The initial value to grow | 10000
+                       | to from zero in the       |
+                       | grow_halt_poll_ns()       |
+                       | function.                 |
+--------------------------------------------------------------------------------
+halt_poll_ns_shrink    | The value by which the    | 0
+                       | halt polling interval is  |
+                       | divided in the            |
+                       | shrink_halt_poll_ns()     |
+                       | function.                 |
+--------------------------------------------------------------------------------
+
+These module parameters can be set from the debugfs files in:
+
+       /sys/module/kvm/parameters/
+
+Note: that these module parameters are system wide values and are not able to
+      be tuned on a per vm basis.
+
+Further Notes
+=============
+
+- Care should be taken when setting the halt_poll_ns module parameter as a
+large value has the potential to drive the cpu usage to 100% on a machine which
+would be almost entirely idle otherwise. This is because even if a guest has
+wakeups during which very little work is done and which are quite far apart, if
+the period is shorter than the global max polling interval (halt_poll_ns) then
+the host will always poll for the entire block time and thus cpu utilisation
+will go to 100%.
+
+- Halt polling essentially presents a trade off between power usage and latency
+and the module parameters should be used to tune the affinity for this. Idle
+cpu time is essentially converted to host kernel time with the aim of decreasing
+latency when entering the guest.
+
+- Halt polling will only be conducted by the host when no other tasks are
+runnable on that cpu, otherwise the polling will cease immediately and
+schedule will be invoked to allow that other task to run. Thus this doesn't
+allow a guest to denial of service the cpu.
diff --git a/Documentation/virt/kvm/hypercalls.txt b/Documentation/virt/kvm/hypercalls.txt
new file mode 100644 (file)
index 0000000..5f6d291
--- /dev/null
@@ -0,0 +1,154 @@
+Linux KVM Hypercall:
+===================
+X86:
+ KVM Hypercalls have a three-byte sequence of either the vmcall or the vmmcall
+ instruction. The hypervisor can replace it with instructions that are
+ guaranteed to be supported.
+
+ Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
+ The hypercall number should be placed in rax and the return value will be
+ placed in rax.  No other registers will be clobbered unless explicitly stated
+ by the particular hypercall.
+
+S390:
+  R2-R7 are used for parameters 1-6. In addition, R1 is used for hypercall
+  number. The return value is written to R2.
+
+  S390 uses diagnose instruction as hypercall (0x500) along with hypercall
+  number in R1.
+
+  For further information on the S390 diagnose call as supported by KVM,
+  refer to Documentation/virt/kvm/s390-diag.txt.
+
+ PowerPC:
+  It uses R3-R10 and hypercall number in R11. R4-R11 are used as output registers.
+  Return value is placed in R3.
+
+  KVM hypercalls uses 4 byte opcode, that are patched with 'hypercall-instructions'
+  property inside the device tree's /hypervisor node.
+  For more information refer to Documentation/virt/kvm/ppc-pv.txt
+
+MIPS:
+  KVM hypercalls use the HYPCALL instruction with code 0 and the hypercall
+  number in $2 (v0). Up to four arguments may be placed in $4-$7 (a0-a3) and
+  the return value is placed in $2 (v0).
+
+KVM Hypercalls Documentation
+===========================
+The template for each hypercall is:
+1. Hypercall name.
+2. Architecture(s)
+3. Status (deprecated, obsolete, active)
+4. Purpose
+
+1. KVM_HC_VAPIC_POLL_IRQ
+------------------------
+Architecture: x86
+Status: active
+Purpose: Trigger guest exit so that the host can check for pending
+interrupts on reentry.
+
+2. KVM_HC_MMU_OP
+------------------------
+Architecture: x86
+Status: deprecated.
+Purpose: Support MMU operations such as writing to PTE,
+flushing TLB, release PT.
+
+3. KVM_HC_FEATURES
+------------------------
+Architecture: PPC
+Status: active
+Purpose: Expose hypercall availability to the guest. On x86 platforms, cpuid
+used to enumerate which hypercalls are available. On PPC, either device tree
+based lookup ( which is also what EPAPR dictates) OR KVM specific enumeration
+mechanism (which is this hypercall) can be used.
+
+4. KVM_HC_PPC_MAP_MAGIC_PAGE
+------------------------
+Architecture: PPC
+Status: active
+Purpose: To enable communication between the hypervisor and guest there is a
+shared page that contains parts of supervisor visible register state.
+The guest can map this shared page to access its supervisor register through
+memory using this hypercall.
+
+5. KVM_HC_KICK_CPU
+------------------------
+Architecture: x86
+Status: active
+Purpose: Hypercall used to wakeup a vcpu from HLT state
+Usage example : A vcpu of a paravirtualized guest that is busywaiting in guest
+kernel mode for an event to occur (ex: a spinlock to become available) can
+execute HLT instruction once it has busy-waited for more than a threshold
+time-interval. Execution of HLT instruction would cause the hypervisor to put
+the vcpu to sleep until occurrence of an appropriate event. Another vcpu of the
+same guest can wakeup the sleeping vcpu by issuing KVM_HC_KICK_CPU hypercall,
+specifying APIC ID (a1) of the vcpu to be woken up. An additional argument (a0)
+is used in the hypercall for future use.
+
+
+6. KVM_HC_CLOCK_PAIRING
+------------------------
+Architecture: x86
+Status: active
+Purpose: Hypercall used to synchronize host and guest clocks.
+Usage:
+
+a0: guest physical address where host copies
+"struct kvm_clock_offset" structure.
+
+a1: clock_type, ATM only KVM_CLOCK_PAIRING_WALLCLOCK (0)
+is supported (corresponding to the host's CLOCK_REALTIME clock).
+
+               struct kvm_clock_pairing {
+                       __s64 sec;
+                       __s64 nsec;
+                       __u64 tsc;
+                       __u32 flags;
+                       __u32 pad[9];
+               };
+
+       Where:
+               * sec: seconds from clock_type clock.
+               * nsec: nanoseconds from clock_type clock.
+               * tsc: guest TSC value used to calculate sec/nsec pair
+               * flags: flags, unused (0) at the moment.
+
+The hypercall lets a guest compute a precise timestamp across
+host and guest.  The guest can use the returned TSC value to
+compute the CLOCK_REALTIME for its clock, at the same instant.
+
+Returns KVM_EOPNOTSUPP if the host does not use TSC clocksource,
+or if clock type is different than KVM_CLOCK_PAIRING_WALLCLOCK.
+
+6. KVM_HC_SEND_IPI
+------------------------
+Architecture: x86
+Status: active
+Purpose: Send IPIs to multiple vCPUs.
+
+a0: lower part of the bitmap of destination APIC IDs
+a1: higher part of the bitmap of destination APIC IDs
+a2: the lowest APIC ID in bitmap
+a3: APIC ICR
+
+The hypercall lets a guest send multicast IPIs, with at most 128
+128 destinations per hypercall in 64-bit mode and 64 vCPUs per
+hypercall in 32-bit mode.  The destinations are represented by a
+bitmap contained in the first two arguments (a0 and a1). Bit 0 of
+a0 corresponds to the APIC ID in the third argument (a2), bit 1
+corresponds to the APIC ID a2+1, and so on.
+
+Returns the number of CPUs to which the IPIs were delivered successfully.
+
+7. KVM_HC_SCHED_YIELD
+------------------------
+Architecture: x86
+Status: active
+Purpose: Hypercall used to yield if the IPI target vCPU is preempted
+
+a0: destination APIC ID
+
+Usage example: When sending a call-function IPI-many to vCPUs, yield if
+any of the IPI target vCPUs was preempted.
diff --git a/Documentation/virt/kvm/index.rst b/Documentation/virt/kvm/index.rst
new file mode 100644 (file)
index 0000000..ada224a
--- /dev/null
@@ -0,0 +1,12 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===
+KVM
+===
+
+.. toctree::
+   :maxdepth: 2
+
+   amd-memory-encryption
+   cpuid
+   vcpu-requests
diff --git a/Documentation/virt/kvm/locking.txt b/Documentation/virt/kvm/locking.txt
new file mode 100644 (file)
index 0000000..635cd6e
--- /dev/null
@@ -0,0 +1,215 @@
+KVM Lock Overview
+=================
+
+1. Acquisition Orders
+---------------------
+
+The acquisition orders for mutexes are as follows:
+
+- kvm->lock is taken outside vcpu->mutex
+
+- kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock
+
+- kvm->slots_lock is taken outside kvm->irq_lock, though acquiring
+  them together is quite rare.
+
+On x86, vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock.
+
+Everything else is a leaf: no other lock is taken inside the critical
+sections.
+
+2: Exception
+------------
+
+Fast page fault:
+
+Fast page fault is the fast path which fixes the guest page fault out of
+the mmu-lock on x86. Currently, the page fault can be fast in one of the
+following two cases:
+
+1. Access Tracking: The SPTE is not present, but it is marked for access
+tracking i.e. the SPTE_SPECIAL_MASK is set. That means we need to
+restore the saved R/X bits. This is described in more detail later below.
+
+2. Write-Protection: The SPTE is present and the fault is
+caused by write-protect. That means we just need to change the W bit of the 
+spte.
+
+What we use to avoid all the race is the SPTE_HOST_WRITEABLE bit and
+SPTE_MMU_WRITEABLE bit on the spte:
+- SPTE_HOST_WRITEABLE means the gfn is writable on host.
+- SPTE_MMU_WRITEABLE means the gfn is writable on mmu. The bit is set when
+  the gfn is writable on guest mmu and it is not write-protected by shadow
+  page write-protection.
+
+On fast page fault path, we will use cmpxchg to atomically set the spte W
+bit if spte.SPTE_HOST_WRITEABLE = 1 and spte.SPTE_WRITE_PROTECT = 1, or 
+restore the saved R/X bits if VMX_EPT_TRACK_ACCESS mask is set, or both. This
+is safe because whenever changing these bits can be detected by cmpxchg.
+
+But we need carefully check these cases:
+1): The mapping from gfn to pfn
+The mapping from gfn to pfn may be changed since we can only ensure the pfn
+is not changed during cmpxchg. This is a ABA problem, for example, below case
+will happen:
+
+At the beginning:
+gpte = gfn1
+gfn1 is mapped to pfn1 on host
+spte is the shadow page table entry corresponding with gpte and
+spte = pfn1
+
+   VCPU 0                           VCPU0
+on fast page fault path:
+
+   old_spte = *spte;
+                                 pfn1 is swapped out:
+                                    spte = 0;
+
+                                 pfn1 is re-alloced for gfn2.
+
+                                 gpte is changed to point to
+                                 gfn2 by the guest:
+                                    spte = pfn1;
+
+   if (cmpxchg(spte, old_spte, old_spte+W)
+       mark_page_dirty(vcpu->kvm, gfn1)
+             OOPS!!!
+
+We dirty-log for gfn1, that means gfn2 is lost in dirty-bitmap.
+
+For direct sp, we can easily avoid it since the spte of direct sp is fixed
+to gfn. For indirect sp, before we do cmpxchg, we call gfn_to_pfn_atomic()
+to pin gfn to pfn, because after gfn_to_pfn_atomic():
+- We have held the refcount of pfn that means the pfn can not be freed and
+  be reused for another gfn.
+- The pfn is writable that means it can not be shared between different gfns
+  by KSM.
+
+Then, we can ensure the dirty bitmaps is correctly set for a gfn.
+
+Currently, to simplify the whole things, we disable fast page fault for
+indirect shadow page.
+
+2): Dirty bit tracking
+In the origin code, the spte can be fast updated (non-atomically) if the
+spte is read-only and the Accessed bit has already been set since the
+Accessed bit and Dirty bit can not be lost.
+
+But it is not true after fast page fault since the spte can be marked
+writable between reading spte and updating spte. Like below case:
+
+At the beginning:
+spte.W = 0
+spte.Accessed = 1
+
+   VCPU 0                                       VCPU0
+In mmu_spte_clear_track_bits():
+
+   old_spte = *spte;
+
+   /* 'if' condition is satisfied. */
+   if (old_spte.Accessed == 1 &&
+        old_spte.W == 0)
+      spte = 0ull;
+                                         on fast page fault path:
+                                             spte.W = 1
+                                         memory write on the spte:
+                                             spte.Dirty = 1
+
+
+   else
+      old_spte = xchg(spte, 0ull)
+
+
+   if (old_spte.Accessed == 1)
+      kvm_set_pfn_accessed(spte.pfn);
+   if (old_spte.Dirty == 1)
+      kvm_set_pfn_dirty(spte.pfn);
+      OOPS!!!
+
+The Dirty bit is lost in this case.
+
+In order to avoid this kind of issue, we always treat the spte as "volatile"
+if it can be updated out of mmu-lock, see spte_has_volatile_bits(), it means,
+the spte is always atomically updated in this case.
+
+3): flush tlbs due to spte updated
+If the spte is updated from writable to readonly, we should flush all TLBs,
+otherwise rmap_write_protect will find a read-only spte, even though the
+writable spte might be cached on a CPU's TLB.
+
+As mentioned before, the spte can be updated to writable out of mmu-lock on
+fast page fault path, in order to easily audit the path, we see if TLBs need
+be flushed caused by this reason in mmu_spte_update() since this is a common
+function to update spte (present -> present).
+
+Since the spte is "volatile" if it can be updated out of mmu-lock, we always
+atomically update the spte, the race caused by fast page fault can be avoided,
+See the comments in spte_has_volatile_bits() and mmu_spte_update().
+
+Lockless Access Tracking:
+
+This is used for Intel CPUs that are using EPT but do not support the EPT A/D
+bits. In this case, when the KVM MMU notifier is called to track accesses to a
+page (via kvm_mmu_notifier_clear_flush_young), it marks the PTE as not-present
+by clearing the RWX bits in the PTE and storing the original R & X bits in
+some unused/ignored bits. In addition, the SPTE_SPECIAL_MASK is also set on the
+PTE (using the ignored bit 62). When the VM tries to access the page later on,
+a fault is generated and the fast page fault mechanism described above is used
+to atomically restore the PTE to a Present state. The W bit is not saved when
+the PTE is marked for access tracking and during restoration to the Present
+state, the W bit is set depending on whether or not it was a write access. If
+it wasn't, then the W bit will remain clear until a write access happens, at 
+which time it will be set using the Dirty tracking mechanism described above.
+
+3. Reference
+------------
+
+Name:          kvm_lock
+Type:          mutex
+Arch:          any
+Protects:      - vm_list
+
+Name:          kvm_count_lock
+Type:          raw_spinlock_t
+Arch:          any
+Protects:      - hardware virtualization enable/disable
+Comment:       'raw' because hardware enabling/disabling must be atomic /wrt
+               migration.
+
+Name:          kvm_arch::tsc_write_lock
+Type:          raw_spinlock
+Arch:          x86
+Protects:      - kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}
+               - tsc offset in vmcb
+Comment:       'raw' because updating the tsc offsets must not be preempted.
+
+Name:          kvm->mmu_lock
+Type:          spinlock_t
+Arch:          any
+Protects:      -shadow page/shadow tlb entry
+Comment:       it is a spinlock since it is used in mmu notifier.
+
+Name:          kvm->srcu
+Type:          srcu lock
+Arch:          any
+Protects:      - kvm->memslots
+               - kvm->buses
+Comment:       The srcu read lock must be held while accessing memslots (e.g.
+               when using gfn_to_* functions) and while accessing in-kernel
+               MMIO/PIO address->device structure mapping (kvm->buses).
+               The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
+               if it is needed by multiple functions.
+
+Name:          blocked_vcpu_on_cpu_lock
+Type:          spinlock_t
+Arch:          x86
+Protects:      blocked_vcpu_on_cpu
+Comment:       This is a per-CPU lock and it is used for VT-d posted-interrupts.
+               When VT-d posted-interrupts is supported and the VM has assigned
+               devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu
+               protected by blocked_vcpu_on_cpu_lock, when VT-d hardware issues
+               wakeup notification event since external interrupts from the
+               assigned devices happens, we will find the vCPU on the list to
+               wakeup.
diff --git a/Documentation/virt/kvm/mmu.txt b/Documentation/virt/kvm/mmu.txt
new file mode 100644 (file)
index 0000000..1b9880d
--- /dev/null
@@ -0,0 +1,449 @@
+The x86 kvm shadow mmu
+======================
+
+The mmu (in arch/x86/kvm, files mmu.[ch] and paging_tmpl.h) is responsible
+for presenting a standard x86 mmu to the guest, while translating guest
+physical addresses to host physical addresses.
+
+The mmu code attempts to satisfy the following requirements:
+
+- correctness: the guest should not be able to determine that it is running
+               on an emulated mmu except for timing (we attempt to comply
+               with the specification, not emulate the characteristics of
+               a particular implementation such as tlb size)
+- security:    the guest must not be able to touch host memory not assigned
+               to it
+- performance: minimize the performance penalty imposed by the mmu
+- scaling:     need to scale to large memory and large vcpu guests
+- hardware:    support the full range of x86 virtualization hardware
+- integration: Linux memory management code must be in control of guest memory
+               so that swapping, page migration, page merging, transparent
+               hugepages, and similar features work without change
+- dirty tracking: report writes to guest memory to enable live migration
+               and framebuffer-based displays
+- footprint:   keep the amount of pinned kernel memory low (most memory
+               should be shrinkable)
+- reliability:  avoid multipage or GFP_ATOMIC allocations
+
+Acronyms
+========
+
+pfn   host page frame number
+hpa   host physical address
+hva   host virtual address
+gfn   guest frame number
+gpa   guest physical address
+gva   guest virtual address
+ngpa  nested guest physical address
+ngva  nested guest virtual address
+pte   page table entry (used also to refer generically to paging structure
+      entries)
+gpte  guest pte (referring to gfns)
+spte  shadow pte (referring to pfns)
+tdp   two dimensional paging (vendor neutral term for NPT and EPT)
+
+Virtual and real hardware supported
+===================================
+
+The mmu supports first-generation mmu hardware, which allows an atomic switch
+of the current paging mode and cr3 during guest entry, as well as
+two-dimensional paging (AMD's NPT and Intel's EPT).  The emulated hardware
+it exposes is the traditional 2/3/4 level x86 mmu, with support for global
+pages, pae, pse, pse36, cr0.wp, and 1GB pages. Emulated hardware also
+able to expose NPT capable hardware on NPT capable hosts.
+
+Translation
+===========
+
+The primary job of the mmu is to program the processor's mmu to translate
+addresses for the guest.  Different translations are required at different
+times:
+
+- when guest paging is disabled, we translate guest physical addresses to
+  host physical addresses (gpa->hpa)
+- when guest paging is enabled, we translate guest virtual addresses, to
+  guest physical addresses, to host physical addresses (gva->gpa->hpa)
+- when the guest launches a guest of its own, we translate nested guest
+  virtual addresses, to nested guest physical addresses, to guest physical
+  addresses, to host physical addresses (ngva->ngpa->gpa->hpa)
+
+The primary challenge is to encode between 1 and 3 translations into hardware
+that support only 1 (traditional) and 2 (tdp) translations.  When the
+number of required translations matches the hardware, the mmu operates in
+direct mode; otherwise it operates in shadow mode (see below).
+
+Memory
+======
+
+Guest memory (gpa) is part of the user address space of the process that is
+using kvm.  Userspace defines the translation between guest addresses and user
+addresses (gpa->hva); note that two gpas may alias to the same hva, but not
+vice versa.
+
+These hvas may be backed using any method available to the host: anonymous
+memory, file backed memory, and device memory.  Memory might be paged by the
+host at any time.
+
+Events
+======
+
+The mmu is driven by events, some from the guest, some from the host.
+
+Guest generated events:
+- writes to control registers (especially cr3)
+- invlpg/invlpga instruction execution
+- access to missing or protected translations
+
+Host generated events:
+- changes in the gpa->hpa translation (either through gpa->hva changes or
+  through hva->hpa changes)
+- memory pressure (the shrinker)
+
+Shadow pages
+============
+
+The principal data structure is the shadow page, 'struct kvm_mmu_page'.  A
+shadow page contains 512 sptes, which can be either leaf or nonleaf sptes.  A
+shadow page may contain a mix of leaf and nonleaf sptes.
+
+A nonleaf spte allows the hardware mmu to reach the leaf pages and
+is not related to a translation directly.  It points to other shadow pages.
+
+A leaf spte corresponds to either one or two translations encoded into
+one paging structure entry.  These are always the lowest level of the
+translation stack, with optional higher level translations left to NPT/EPT.
+Leaf ptes point at guest pages.
+
+The following table shows translations encoded by leaf ptes, with higher-level
+translations in parentheses:
+
+ Non-nested guests:
+  nonpaging:     gpa->hpa
+  paging:        gva->gpa->hpa
+  paging, tdp:   (gva->)gpa->hpa
+ Nested guests:
+  non-tdp:       ngva->gpa->hpa  (*)
+  tdp:           (ngva->)ngpa->gpa->hpa
+
+(*) the guest hypervisor will encode the ngva->gpa translation into its page
+    tables if npt is not present
+
+Shadow pages contain the following information:
+  role.level:
+    The level in the shadow paging hierarchy that this shadow page belongs to.
+    1=4k sptes, 2=2M sptes, 3=1G sptes, etc.
+  role.direct:
+    If set, leaf sptes reachable from this page are for a linear range.
+    Examples include real mode translation, large guest pages backed by small
+    host pages, and gpa->hpa translations when NPT or EPT is active.
+    The linear range starts at (gfn << PAGE_SHIFT) and its size is determined
+    by role.level (2MB for first level, 1GB for second level, 0.5TB for third
+    level, 256TB for fourth level)
+    If clear, this page corresponds to a guest page table denoted by the gfn
+    field.
+  role.quadrant:
+    When role.gpte_is_8_bytes=0, the guest uses 32-bit gptes while the host uses 64-bit
+    sptes.  That means a guest page table contains more ptes than the host,
+    so multiple shadow pages are needed to shadow one guest page.
+    For first-level shadow pages, role.quadrant can be 0 or 1 and denotes the
+    first or second 512-gpte block in the guest page table.  For second-level
+    page tables, each 32-bit gpte is converted to two 64-bit sptes
+    (since each first-level guest page is shadowed by two first-level
+    shadow pages) so role.quadrant takes values in the range 0..3.  Each
+    quadrant maps 1GB virtual address space.
+  role.access:
+    Inherited guest access permissions in the form uwx.  Note execute
+    permission is positive, not negative.
+  role.invalid:
+    The page is invalid and should not be used.  It is a root page that is
+    currently pinned (by a cpu hardware register pointing to it); once it is
+    unpinned it will be destroyed.
+  role.gpte_is_8_bytes:
+    Reflects the size of the guest PTE for which the page is valid, i.e. '1'
+    if 64-bit gptes are in use, '0' if 32-bit gptes are in use.
+  role.nxe:
+    Contains the value of efer.nxe for which the page is valid.
+  role.cr0_wp:
+    Contains the value of cr0.wp for which the page is valid.
+  role.smep_andnot_wp:
+    Contains the value of cr4.smep && !cr0.wp for which the page is valid
+    (pages for which this is true are different from other pages; see the
+    treatment of cr0.wp=0 below).
+  role.smap_andnot_wp:
+    Contains the value of cr4.smap && !cr0.wp for which the page is valid
+    (pages for which this is true are different from other pages; see the
+    treatment of cr0.wp=0 below).
+  role.ept_sp:
+    This is a virtual flag to denote a shadowed nested EPT page.  ept_sp
+    is true if "cr0_wp && smap_andnot_wp", an otherwise invalid combination.
+  role.smm:
+    Is 1 if the page is valid in system management mode.  This field
+    determines which of the kvm_memslots array was used to build this
+    shadow page; it is also used to go back from a struct kvm_mmu_page
+    to a memslot, through the kvm_memslots_for_spte_role macro and
+    __gfn_to_memslot.
+  role.ad_disabled:
+    Is 1 if the MMU instance cannot use A/D bits.  EPT did not have A/D
+    bits before Haswell; shadow EPT page tables also cannot use A/D bits
+    if the L1 hypervisor does not enable them.
+  gfn:
+    Either the guest page table containing the translations shadowed by this
+    page, or the base page frame for linear translations.  See role.direct.
+  spt:
+    A pageful of 64-bit sptes containing the translations for this page.
+    Accessed by both kvm and hardware.
+    The page pointed to by spt will have its page->private pointing back
+    at the shadow page structure.
+    sptes in spt point either at guest pages, or at lower-level shadow pages.
+    Specifically, if sp1 and sp2 are shadow pages, then sp1->spt[n] may point
+    at __pa(sp2->spt).  sp2 will point back at sp1 through parent_pte.
+    The spt array forms a DAG structure with the shadow page as a node, and
+    guest pages as leaves.
+  gfns:
+    An array of 512 guest frame numbers, one for each present pte.  Used to
+    perform a reverse map from a pte to a gfn. When role.direct is set, any
+    element of this array can be calculated from the gfn field when used, in
+    this case, the array of gfns is not allocated. See role.direct and gfn.
+  root_count:
+    A counter keeping track of how many hardware registers (guest cr3 or
+    pdptrs) are now pointing at the page.  While this counter is nonzero, the
+    page cannot be destroyed.  See role.invalid.
+  parent_ptes:
+    The reverse mapping for the pte/ptes pointing at this page's spt. If
+    parent_ptes bit 0 is zero, only one spte points at this page and
+    parent_ptes points at this single spte, otherwise, there exists multiple
+    sptes pointing at this page and (parent_ptes & ~0x1) points at a data
+    structure with a list of parent sptes.
+  unsync:
+    If true, then the translations in this page may not match the guest's
+    translation.  This is equivalent to the state of the tlb when a pte is
+    changed but before the tlb entry is flushed.  Accordingly, unsync ptes
+    are synchronized when the guest executes invlpg or flushes its tlb by
+    other means.  Valid for leaf pages.
+  unsync_children:
+    How many sptes in the page point at pages that are unsync (or have
+    unsynchronized children).
+  unsync_child_bitmap:
+    A bitmap indicating which sptes in spt point (directly or indirectly) at
+    pages that may be unsynchronized.  Used to quickly locate all unsychronized
+    pages reachable from a given page.
+  clear_spte_count:
+    Only present on 32-bit hosts, where a 64-bit spte cannot be written
+    atomically.  The reader uses this while running out of the MMU lock
+    to detect in-progress updates and retry them until the writer has
+    finished the write.
+  write_flooding_count:
+    A guest may write to a page table many times, causing a lot of
+    emulations if the page needs to be write-protected (see "Synchronized
+    and unsynchronized pages" below).  Leaf pages can be unsynchronized
+    so that they do not trigger frequent emulation, but this is not
+    possible for non-leafs.  This field counts the number of emulations
+    since the last time the page table was actually used; if emulation
+    is triggered too frequently on this page, KVM will unmap the page
+    to avoid emulation in the future.
+
+Reverse map
+===========
+
+The mmu maintains a reverse mapping whereby all ptes mapping a page can be
+reached given its gfn.  This is used, for example, when swapping out a page.
+
+Synchronized and unsynchronized pages
+=====================================
+
+The guest uses two events to synchronize its tlb and page tables: tlb flushes
+and page invalidations (invlpg).
+
+A tlb flush means that we need to synchronize all sptes reachable from the
+guest's cr3.  This is expensive, so we keep all guest page tables write
+protected, and synchronize sptes to gptes when a gpte is written.
+
+A special case is when a guest page table is reachable from the current
+guest cr3.  In this case, the guest is obliged to issue an invlpg instruction
+before using the translation.  We take advantage of that by removing write
+protection from the guest page, and allowing the guest to modify it freely.
+We synchronize modified gptes when the guest invokes invlpg.  This reduces
+the amount of emulation we have to do when the guest modifies multiple gptes,
+or when the a guest page is no longer used as a page table and is used for
+random guest data.
+
+As a side effect we have to resynchronize all reachable unsynchronized shadow
+pages on a tlb flush.
+
+
+Reaction to events
+==================
+
+- guest page fault (or npt page fault, or ept violation)
+
+This is the most complicated event.  The cause of a page fault can be:
+
+  - a true guest fault (the guest translation won't allow the access) (*)
+  - access to a missing translation
+  - access to a protected translation
+    - when logging dirty pages, memory is write protected
+    - synchronized shadow pages are write protected (*)
+  - access to untranslatable memory (mmio)
+
+  (*) not applicable in direct mode
+
+Handling a page fault is performed as follows:
+
+ - if the RSV bit of the error code is set, the page fault is caused by guest
+   accessing MMIO and cached MMIO information is available.
+   - walk shadow page table
+   - check for valid generation number in the spte (see "Fast invalidation of
+     MMIO sptes" below)
+   - cache the information to vcpu->arch.mmio_gva, vcpu->arch.access and
+     vcpu->arch.mmio_gfn, and call the emulator
+ - If both P bit and R/W bit of error code are set, this could possibly
+   be handled as a "fast page fault" (fixed without taking the MMU lock).  See
+   the description in Documentation/virt/kvm/locking.txt.
+ - if needed, walk the guest page tables to determine the guest translation
+   (gva->gpa or ngpa->gpa)
+   - if permissions are insufficient, reflect the fault back to the guest
+ - determine the host page
+   - if this is an mmio request, there is no host page; cache the info to
+     vcpu->arch.mmio_gva, vcpu->arch.access and vcpu->arch.mmio_gfn
+ - walk the shadow page table to find the spte for the translation,
+   instantiating missing intermediate page tables as necessary
+   - If this is an mmio request, cache the mmio info to the spte and set some
+     reserved bit on the spte (see callers of kvm_mmu_set_mmio_spte_mask)
+ - try to unsynchronize the page
+   - if successful, we can let the guest continue and modify the gpte
+ - emulate the instruction
+   - if failed, unshadow the page and let the guest continue
+ - update any translations that were modified by the instruction
+
+invlpg handling:
+
+  - walk the shadow page hierarchy and drop affected translations
+  - try to reinstantiate the indicated translation in the hope that the
+    guest will use it in the near future
+
+Guest control register updates:
+
+- mov to cr3
+  - look up new shadow roots
+  - synchronize newly reachable shadow pages
+
+- mov to cr0/cr4/efer
+  - set up mmu context for new paging mode
+  - look up new shadow roots
+  - synchronize newly reachable shadow pages
+
+Host translation updates:
+
+  - mmu notifier called with updated hva
+  - look up affected sptes through reverse map
+  - drop (or update) translations
+
+Emulating cr0.wp
+================
+
+If tdp is not enabled, the host must keep cr0.wp=1 so page write protection
+works for the guest kernel, not guest guest userspace.  When the guest
+cr0.wp=1, this does not present a problem.  However when the guest cr0.wp=0,
+we cannot map the permissions for gpte.u=1, gpte.w=0 to any spte (the
+semantics require allowing any guest kernel access plus user read access).
+
+We handle this by mapping the permissions to two possible sptes, depending
+on fault type:
+
+- kernel write fault: spte.u=0, spte.w=1 (allows full kernel access,
+  disallows user access)
+- read fault: spte.u=1, spte.w=0 (allows full read access, disallows kernel
+  write access)
+
+(user write faults generate a #PF)
+
+In the first case there are two additional complications:
+- if CR4.SMEP is enabled: since we've turned the page into a kernel page,
+  the kernel may now execute it.  We handle this by also setting spte.nx.
+  If we get a user fetch or read fault, we'll change spte.u=1 and
+  spte.nx=gpte.nx back.  For this to work, KVM forces EFER.NX to 1 when
+  shadow paging is in use.
+- if CR4.SMAP is disabled: since the page has been changed to a kernel
+  page, it can not be reused when CR4.SMAP is enabled. We set
+  CR4.SMAP && !CR0.WP into shadow page's role to avoid this case. Note,
+  here we do not care the case that CR4.SMAP is enabled since KVM will
+  directly inject #PF to guest due to failed permission check.
+
+To prevent an spte that was converted into a kernel page with cr0.wp=0
+from being written by the kernel after cr0.wp has changed to 1, we make
+the value of cr0.wp part of the page role.  This means that an spte created
+with one value of cr0.wp cannot be used when cr0.wp has a different value -
+it will simply be missed by the shadow page lookup code.  A similar issue
+exists when an spte created with cr0.wp=0 and cr4.smep=0 is used after
+changing cr4.smep to 1.  To avoid this, the value of !cr0.wp && cr4.smep
+is also made a part of the page role.
+
+Large pages
+===========
+
+The mmu supports all combinations of large and small guest and host pages.
+Supported page sizes include 4k, 2M, 4M, and 1G.  4M pages are treated as
+two separate 2M pages, on both guest and host, since the mmu always uses PAE
+paging.
+
+To instantiate a large spte, four constraints must be satisfied:
+
+- the spte must point to a large host page
+- the guest pte must be a large pte of at least equivalent size (if tdp is
+  enabled, there is no guest pte and this condition is satisfied)
+- if the spte will be writeable, the large page frame may not overlap any
+  write-protected pages
+- the guest page must be wholly contained by a single memory slot
+
+To check the last two conditions, the mmu maintains a ->disallow_lpage set of
+arrays for each memory slot and large page size.  Every write protected page
+causes its disallow_lpage to be incremented, thus preventing instantiation of
+a large spte.  The frames at the end of an unaligned memory slot have
+artificially inflated ->disallow_lpages so they can never be instantiated.
+
+Fast invalidation of MMIO sptes
+===============================
+
+As mentioned in "Reaction to events" above, kvm will cache MMIO
+information in leaf sptes.  When a new memslot is added or an existing
+memslot is changed, this information may become stale and needs to be
+invalidated.  This also needs to hold the MMU lock while walking all
+shadow pages, and is made more scalable with a similar technique.
+
+MMIO sptes have a few spare bits, which are used to store a
+generation number.  The global generation number is stored in
+kvm_memslots(kvm)->generation, and increased whenever guest memory info
+changes.
+
+When KVM finds an MMIO spte, it checks the generation number of the spte.
+If the generation number of the spte does not equal the global generation
+number, it will ignore the cached MMIO information and handle the page
+fault through the slow path.
+
+Since only 19 bits are used to store generation-number on mmio spte, all
+pages are zapped when there is an overflow.
+
+Unfortunately, a single memory access might access kvm_memslots(kvm) multiple
+times, the last one happening when the generation number is retrieved and
+stored into the MMIO spte.  Thus, the MMIO spte might be created based on
+out-of-date information, but with an up-to-date generation number.
+
+To avoid this, the generation number is incremented again after synchronize_srcu
+returns; thus, bit 63 of kvm_memslots(kvm)->generation set to 1 only during a
+memslot update, while some SRCU readers might be using the old copy.  We do not
+want to use an MMIO sptes created with an odd generation number, and we can do
+this without losing a bit in the MMIO spte.  The "update in-progress" bit of the
+generation is not stored in MMIO spte, and is so is implicitly zero when the
+generation is extracted out of the spte.  If KVM is unlucky and creates an MMIO
+spte while an update is in-progress, the next access to the spte will always be
+a cache miss.  For example, a subsequent access during the update window will
+miss due to the in-progress flag diverging, while an access after the update
+window closes will have a higher generation number (as compared to the spte).
+
+
+Further reading
+===============
+
+- NPT presentation from KVM Forum 2008
+  http://www.linux-kvm.org/images/c/c8/KvmForum2008%24kdf2008_21.pdf
+
diff --git a/Documentation/virt/kvm/msr.txt b/Documentation/virt/kvm/msr.txt
new file mode 100644 (file)
index 0000000..df1f433
--- /dev/null
@@ -0,0 +1,284 @@
+KVM-specific MSRs.
+Glauber Costa <glommer@redhat.com>, Red Hat Inc, 2010
+=====================================================
+
+KVM makes use of some custom MSRs to service some requests.
+
+Custom MSRs have a range reserved for them, that goes from
+0x4b564d00 to 0x4b564dff. There are MSRs outside this area,
+but they are deprecated and their use is discouraged.
+
+Custom MSR list
+--------
+
+The current supported Custom MSR list is:
+
+MSR_KVM_WALL_CLOCK_NEW:   0x4b564d00
+
+       data: 4-byte alignment physical address of a memory area which must be
+       in guest RAM. This memory is expected to hold a copy of the following
+       structure:
+
+       struct pvclock_wall_clock {
+               u32   version;
+               u32   sec;
+               u32   nsec;
+       } __attribute__((__packed__));
+
+       whose data will be filled in by the hypervisor. The hypervisor is only
+       guaranteed to update this data at the moment of MSR write.
+       Users that want to reliably query this information more than once have
+       to write more than once to this MSR. Fields have the following meanings:
+
+               version: guest has to check version before and after grabbing
+               time information and check that they are both equal and even.
+               An odd version indicates an in-progress update.
+
+               sec: number of seconds for wallclock at time of boot.
+
+               nsec: number of nanoseconds for wallclock at time of boot.
+
+       In order to get the current wallclock time, the system_time from
+       MSR_KVM_SYSTEM_TIME_NEW needs to be added.
+
+       Note that although MSRs are per-CPU entities, the effect of this
+       particular MSR is global.
+
+       Availability of this MSR must be checked via bit 3 in 0x4000001 cpuid
+       leaf prior to usage.
+
+MSR_KVM_SYSTEM_TIME_NEW:  0x4b564d01
+
+       data: 4-byte aligned physical address of a memory area which must be in
+       guest RAM, plus an enable bit in bit 0. This memory is expected to hold
+       a copy of the following structure:
+
+       struct pvclock_vcpu_time_info {
+               u32   version;
+               u32   pad0;
+               u64   tsc_timestamp;
+               u64   system_time;
+               u32   tsc_to_system_mul;
+               s8    tsc_shift;
+               u8    flags;
+               u8    pad[2];
+       } __attribute__((__packed__)); /* 32 bytes */
+
+       whose data will be filled in by the hypervisor periodically. Only one
+       write, or registration, is needed for each VCPU. The interval between
+       updates of this structure is arbitrary and implementation-dependent.
+       The hypervisor may update this structure at any time it sees fit until
+       anything with bit0 == 0 is written to it.
+
+       Fields have the following meanings:
+
+               version: guest has to check version before and after grabbing
+               time information and check that they are both equal and even.
+               An odd version indicates an in-progress update.
+
+               tsc_timestamp: the tsc value at the current VCPU at the time
+               of the update of this structure. Guests can subtract this value
+               from current tsc to derive a notion of elapsed time since the
+               structure update.
+
+               system_time: a host notion of monotonic time, including sleep
+               time at the time this structure was last updated. Unit is
+               nanoseconds.
+
+               tsc_to_system_mul: multiplier to be used when converting
+               tsc-related quantity to nanoseconds
+
+               tsc_shift: shift to be used when converting tsc-related
+               quantity to nanoseconds. This shift will ensure that
+               multiplication with tsc_to_system_mul does not overflow.
+               A positive value denotes a left shift, a negative value
+               a right shift.
+
+               The conversion from tsc to nanoseconds involves an additional
+               right shift by 32 bits. With this information, guests can
+               derive per-CPU time by doing:
+
+                       time = (current_tsc - tsc_timestamp)
+                       if (tsc_shift >= 0)
+                               time <<= tsc_shift;
+                       else
+                               time >>= -tsc_shift;
+                       time = (time * tsc_to_system_mul) >> 32
+                       time = time + system_time
+
+               flags: bits in this field indicate extended capabilities
+               coordinated between the guest and the hypervisor. Availability
+               of specific flags has to be checked in 0x40000001 cpuid leaf.
+               Current flags are:
+
+                flag bit   | cpuid bit    | meaning
+               -------------------------------------------------------------
+                           |              | time measures taken across
+                    0      |      24      | multiple cpus are guaranteed to
+                           |              | be monotonic
+               -------------------------------------------------------------
+                           |              | guest vcpu has been paused by
+                    1      |     N/A      | the host
+                           |              | See 4.70 in api.txt
+               -------------------------------------------------------------
+
+       Availability of this MSR must be checked via bit 3 in 0x4000001 cpuid
+       leaf prior to usage.
+
+
+MSR_KVM_WALL_CLOCK:  0x11
+
+       data and functioning: same as MSR_KVM_WALL_CLOCK_NEW. Use that instead.
+
+       This MSR falls outside the reserved KVM range and may be removed in the
+       future. Its usage is deprecated.
+
+       Availability of this MSR must be checked via bit 0 in 0x4000001 cpuid
+       leaf prior to usage.
+
+MSR_KVM_SYSTEM_TIME: 0x12
+
+       data and functioning: same as MSR_KVM_SYSTEM_TIME_NEW. Use that instead.
+
+       This MSR falls outside the reserved KVM range and may be removed in the
+       future. Its usage is deprecated.
+
+       Availability of this MSR must be checked via bit 0 in 0x4000001 cpuid
+       leaf prior to usage.
+
+       The suggested algorithm for detecting kvmclock presence is then:
+
+               if (!kvm_para_available())    /* refer to cpuid.txt */
+                       return NON_PRESENT;
+
+               flags = cpuid_eax(0x40000001);
+               if (flags & 3) {
+                       msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
+                       msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;
+                       return PRESENT;
+               } else if (flags & 0) {
+                       msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
+                       msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
+                       return PRESENT;
+               } else
+                       return NON_PRESENT;
+
+MSR_KVM_ASYNC_PF_EN: 0x4b564d02
+       data: Bits 63-6 hold 64-byte aligned physical address of a
+       64 byte memory area which must be in guest RAM and must be
+       zeroed. Bits 5-3 are reserved and should be zero. Bit 0 is 1
+       when asynchronous page faults are enabled on the vcpu 0 when
+       disabled. Bit 1 is 1 if asynchronous page faults can be injected
+       when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
+       are delivered to L1 as #PF vmexits.  Bit 2 can be set only if
+       KVM_FEATURE_ASYNC_PF_VMEXIT is present in CPUID.
+
+       First 4 byte of 64 byte memory location will be written to by
+       the hypervisor at the time of asynchronous page fault (APF)
+       injection to indicate type of asynchronous page fault. Value
+       of 1 means that the page referred to by the page fault is not
+       present. Value 2 means that the page is now available. Disabling
+       interrupt inhibits APFs. Guest must not enable interrupt
+       before the reason is read, or it may be overwritten by another
+       APF. Since APF uses the same exception vector as regular page
+       fault guest must reset the reason to 0 before it does
+       something that can generate normal page fault.  If during page
+       fault APF reason is 0 it means that this is regular page
+       fault.
+
+       During delivery of type 1 APF cr2 contains a token that will
+       be used to notify a guest when missing page becomes
+       available. When page becomes available type 2 APF is sent with
+       cr2 set to the token associated with the page. There is special
+       kind of token 0xffffffff which tells vcpu that it should wake
+       up all processes waiting for APFs and no individual type 2 APFs
+       will be sent.
+
+       If APF is disabled while there are outstanding APFs, they will
+       not be delivered.
+
+       Currently type 2 APF will be always delivered on the same vcpu as
+       type 1 was, but guest should not rely on that.
+
+MSR_KVM_STEAL_TIME: 0x4b564d03
+
+       data: 64-byte alignment physical address of a memory area which must be
+       in guest RAM, plus an enable bit in bit 0. This memory is expected to
+       hold a copy of the following structure:
+
+       struct kvm_steal_time {
+               __u64 steal;
+               __u32 version;
+               __u32 flags;
+               __u8  preempted;
+               __u8  u8_pad[3];
+               __u32 pad[11];
+       }
+
+       whose data will be filled in by the hypervisor periodically. Only one
+       write, or registration, is needed for each VCPU. The interval between
+       updates of this structure is arbitrary and implementation-dependent.
+       The hypervisor may update this structure at any time it sees fit until
+       anything with bit0 == 0 is written to it. Guest is required to make sure
+       this structure is initialized to zero.
+
+       Fields have the following meanings:
+
+               version: a sequence counter. In other words, guest has to check
+               this field before and after grabbing time information and make
+               sure they are both equal and even. An odd version indicates an
+               in-progress update.
+
+               flags: At this point, always zero. May be used to indicate
+               changes in this structure in the future.
+
+               steal: the amount of time in which this vCPU did not run, in
+               nanoseconds. Time during which the vcpu is idle, will not be
+               reported as steal time.
+
+               preempted: indicate the vCPU who owns this struct is running or
+               not. Non-zero values mean the vCPU has been preempted. Zero
+               means the vCPU is not preempted. NOTE, it is always zero if the
+               the hypervisor doesn't support this field.
+
+MSR_KVM_EOI_EN: 0x4b564d04
+       data: Bit 0 is 1 when PV end of interrupt is enabled on the vcpu; 0
+       when disabled.  Bit 1 is reserved and must be zero.  When PV end of
+       interrupt is enabled (bit 0 set), bits 63-2 hold a 4-byte aligned
+       physical address of a 4 byte memory area which must be in guest RAM and
+       must be zeroed.
+
+       The first, least significant bit of 4 byte memory location will be
+       written to by the hypervisor, typically at the time of interrupt
+       injection.  Value of 1 means that guest can skip writing EOI to the apic
+       (using MSR or MMIO write); instead, it is sufficient to signal
+       EOI by clearing the bit in guest memory - this location will
+       later be polled by the hypervisor.
+       Value of 0 means that the EOI write is required.
+
+       It is always safe for the guest to ignore the optimization and perform
+       the APIC EOI write anyway.
+
+       Hypervisor is guaranteed to only modify this least
+       significant bit while in the current VCPU context, this means that
+       guest does not need to use either lock prefix or memory ordering
+       primitives to synchronise with the hypervisor.
+
+       However, hypervisor can set and clear this memory bit at any time:
+       therefore to make sure hypervisor does not interrupt the
+       guest and clear the least significant bit in the memory area
+       in the window between guest testing it to detect
+       whether it can skip EOI apic write and between guest
+       clearing it to signal EOI to the hypervisor,
+       guest must both read the least significant bit in the memory area and
+       clear it using a single CPU instruction, such as test and clear, or
+       compare and exchange.
+
+MSR_KVM_POLL_CONTROL: 0x4b564d05
+       Control host-side polling.
+
+       data: Bit 0 enables (1) or disables (0) host-side HLT polling logic.
+
+       KVM guests can request the host not to poll on HLT, for example if
+       they are performing polling themselves.
+
diff --git a/Documentation/virt/kvm/nested-vmx.txt b/Documentation/virt/kvm/nested-vmx.txt
new file mode 100644 (file)
index 0000000..97eb135
--- /dev/null
@@ -0,0 +1,240 @@
+Nested VMX
+==========
+
+Overview
+---------
+
+On Intel processors, KVM uses Intel's VMX (Virtual-Machine eXtensions)
+to easily and efficiently run guest operating systems. Normally, these guests
+*cannot* themselves be hypervisors running their own guests, because in VMX,
+guests cannot use VMX instructions.
+
+The "Nested VMX" feature adds this missing capability - of running guest
+hypervisors (which use VMX) with their own nested guests. It does so by
+allowing a guest to use VMX instructions, and correctly and efficiently
+emulating them using the single level of VMX available in the hardware.
+
+We describe in much greater detail the theory behind the nested VMX feature,
+its implementation and its performance characteristics, in the OSDI 2010 paper
+"The Turtles Project: Design and Implementation of Nested Virtualization",
+available at:
+
+       http://www.usenix.org/events/osdi10/tech/full_papers/Ben-Yehuda.pdf
+
+
+Terminology
+-----------
+
+Single-level virtualization has two levels - the host (KVM) and the guests.
+In nested virtualization, we have three levels: The host (KVM), which we call
+L0, the guest hypervisor, which we call L1, and its nested guest, which we
+call L2.
+
+
+Running nested VMX
+------------------
+
+The nested VMX feature is disabled by default. It can be enabled by giving
+the "nested=1" option to the kvm-intel module.
+
+No modifications are required to user space (qemu). However, qemu's default
+emulated CPU type (qemu64) does not list the "VMX" CPU feature, so it must be
+explicitly enabled, by giving qemu one of the following options:
+
+     -cpu host              (emulated CPU has all features of the real CPU)
+
+     -cpu qemu64,+vmx       (add just the vmx feature to a named CPU type)
+
+
+ABIs
+----
+
+Nested VMX aims to present a standard and (eventually) fully-functional VMX
+implementation for the a guest hypervisor to use. As such, the official
+specification of the ABI that it provides is Intel's VMX specification,
+namely volume 3B of their "Intel 64 and IA-32 Architectures Software
+Developer's Manual". Not all of VMX's features are currently fully supported,
+but the goal is to eventually support them all, starting with the VMX features
+which are used in practice by popular hypervisors (KVM and others).
+
+As a VMX implementation, nested VMX presents a VMCS structure to L1.
+As mandated by the spec, other than the two fields revision_id and abort,
+this structure is *opaque* to its user, who is not supposed to know or care
+about its internal structure. Rather, the structure is accessed through the
+VMREAD and VMWRITE instructions.
+Still, for debugging purposes, KVM developers might be interested to know the
+internals of this structure; This is struct vmcs12 from arch/x86/kvm/vmx.c.
+
+The name "vmcs12" refers to the VMCS that L1 builds for L2. In the code we
+also have "vmcs01", the VMCS that L0 built for L1, and "vmcs02" is the VMCS
+which L0 builds to actually run L2 - how this is done is explained in the
+aforementioned paper.
+
+For convenience, we repeat the content of struct vmcs12 here. If the internals
+of this structure changes, this can break live migration across KVM versions.
+VMCS12_REVISION (from vmx.c) should be changed if struct vmcs12 or its inner
+struct shadow_vmcs is ever changed.
+
+       typedef u64 natural_width;
+       struct __packed vmcs12 {
+               /* According to the Intel spec, a VMCS region must start with
+                * these two user-visible fields */
+               u32 revision_id;
+               u32 abort;
+
+               u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+               u32 padding[7]; /* room for future expansion */
+
+               u64 io_bitmap_a;
+               u64 io_bitmap_b;
+               u64 msr_bitmap;
+               u64 vm_exit_msr_store_addr;
+               u64 vm_exit_msr_load_addr;
+               u64 vm_entry_msr_load_addr;
+               u64 tsc_offset;
+               u64 virtual_apic_page_addr;
+               u64 apic_access_addr;
+               u64 ept_pointer;
+               u64 guest_physical_address;
+               u64 vmcs_link_pointer;
+               u64 guest_ia32_debugctl;
+               u64 guest_ia32_pat;
+               u64 guest_ia32_efer;
+               u64 guest_pdptr0;
+               u64 guest_pdptr1;
+               u64 guest_pdptr2;
+               u64 guest_pdptr3;
+               u64 host_ia32_pat;
+               u64 host_ia32_efer;
+               u64 padding64[8]; /* room for future expansion */
+               natural_width cr0_guest_host_mask;
+               natural_width cr4_guest_host_mask;
+               natural_width cr0_read_shadow;
+               natural_width cr4_read_shadow;
+               natural_width cr3_target_value0;
+               natural_width cr3_target_value1;
+               natural_width cr3_target_value2;
+               natural_width cr3_target_value3;
+               natural_width exit_qualification;
+               natural_width guest_linear_address;
+               natural_width guest_cr0;
+               natural_width guest_cr3;
+               natural_width guest_cr4;
+               natural_width guest_es_base;
+               natural_width guest_cs_base;
+               natural_width guest_ss_base;
+               natural_width guest_ds_base;
+               natural_width guest_fs_base;
+               natural_width guest_gs_base;
+               natural_width guest_ldtr_base;
+               natural_width guest_tr_base;
+               natural_width guest_gdtr_base;
+               natural_width guest_idtr_base;
+               natural_width guest_dr7;
+               natural_width guest_rsp;
+               natural_width guest_rip;
+               natural_width guest_rflags;
+               natural_width guest_pending_dbg_exceptions;
+               natural_width guest_sysenter_esp;
+               natural_width guest_sysenter_eip;
+               natural_width host_cr0;
+               natural_width host_cr3;
+               natural_width host_cr4;
+               natural_width host_fs_base;
+               natural_width host_gs_base;
+               natural_width host_tr_base;
+               natural_width host_gdtr_base;
+               natural_width host_idtr_base;
+               natural_width host_ia32_sysenter_esp;
+               natural_width host_ia32_sysenter_eip;
+               natural_width host_rsp;
+               natural_width host_rip;
+               natural_width paddingl[8]; /* room for future expansion */
+               u32 pin_based_vm_exec_control;
+               u32 cpu_based_vm_exec_control;
+               u32 exception_bitmap;
+               u32 page_fault_error_code_mask;
+               u32 page_fault_error_code_match;
+               u32 cr3_target_count;
+               u32 vm_exit_controls;
+               u32 vm_exit_msr_store_count;
+               u32 vm_exit_msr_load_count;
+               u32 vm_entry_controls;
+               u32 vm_entry_msr_load_count;
+               u32 vm_entry_intr_info_field;
+               u32 vm_entry_exception_error_code;
+               u32 vm_entry_instruction_len;
+               u32 tpr_threshold;
+               u32 secondary_vm_exec_control;
+               u32 vm_instruction_error;
+               u32 vm_exit_reason;
+               u32 vm_exit_intr_info;
+               u32 vm_exit_intr_error_code;
+               u32 idt_vectoring_info_field;
+               u32 idt_vectoring_error_code;
+               u32 vm_exit_instruction_len;
+               u32 vmx_instruction_info;
+               u32 guest_es_limit;
+               u32 guest_cs_limit;
+               u32 guest_ss_limit;
+               u32 guest_ds_limit;
+               u32 guest_fs_limit;
+               u32 guest_gs_limit;
+               u32 guest_ldtr_limit;
+               u32 guest_tr_limit;
+               u32 guest_gdtr_limit;
+               u32 guest_idtr_limit;
+               u32 guest_es_ar_bytes;
+               u32 guest_cs_ar_bytes;
+               u32 guest_ss_ar_bytes;
+               u32 guest_ds_ar_bytes;
+               u32 guest_fs_ar_bytes;
+               u32 guest_gs_ar_bytes;
+               u32 guest_ldtr_ar_bytes;
+               u32 guest_tr_ar_bytes;
+               u32 guest_interruptibility_info;
+               u32 guest_activity_state;
+               u32 guest_sysenter_cs;
+               u32 host_ia32_sysenter_cs;
+               u32 padding32[8]; /* room for future expansion */
+               u16 virtual_processor_id;
+               u16 guest_es_selector;
+               u16 guest_cs_selector;
+               u16 guest_ss_selector;
+               u16 guest_ds_selector;
+               u16 guest_fs_selector;
+               u16 guest_gs_selector;
+               u16 guest_ldtr_selector;
+               u16 guest_tr_selector;
+               u16 host_es_selector;
+               u16 host_cs_selector;
+               u16 host_ss_selector;
+               u16 host_ds_selector;
+               u16 host_fs_selector;
+               u16 host_gs_selector;
+               u16 host_tr_selector;
+       };
+
+
+Authors
+-------
+
+These patches were written by:
+     Abel Gordon, abelg <at> il.ibm.com
+     Nadav Har'El, nyh <at> il.ibm.com
+     Orit Wasserman, oritw <at> il.ibm.com
+     Ben-Ami Yassor, benami <at> il.ibm.com
+     Muli Ben-Yehuda, muli <at> il.ibm.com
+
+With contributions by:
+     Anthony Liguori, aliguori <at> us.ibm.com
+     Mike Day, mdday <at> us.ibm.com
+     Michael Factor, factor <at> il.ibm.com
+     Zvi Dubitzky, dubi <at> il.ibm.com
+
+And valuable reviews by:
+     Avi Kivity, avi <at> redhat.com
+     Gleb Natapov, gleb <at> redhat.com
+     Marcelo Tosatti, mtosatti <at> redhat.com
+     Kevin Tian, kevin.tian <at> intel.com
+     and others.
diff --git a/Documentation/virt/kvm/ppc-pv.txt b/Documentation/virt/kvm/ppc-pv.txt
new file mode 100644 (file)
index 0000000..e26115c
--- /dev/null
@@ -0,0 +1,212 @@
+The PPC KVM paravirtual interface
+=================================
+
+The basic execution principle by which KVM on PowerPC works is to run all kernel
+space code in PR=1 which is user space. This way we trap all privileged
+instructions and can emulate them accordingly.
+
+Unfortunately that is also the downfall. There are quite some privileged
+instructions that needlessly return us to the hypervisor even though they
+could be handled differently.
+
+This is what the PPC PV interface helps with. It takes privileged instructions
+and transforms them into unprivileged ones with some help from the hypervisor.
+This cuts down virtualization costs by about 50% on some of my benchmarks.
+
+The code for that interface can be found in arch/powerpc/kernel/kvm*
+
+Querying for existence
+======================
+
+To find out if we're running on KVM or not, we leverage the device tree. When
+Linux is running on KVM, a node /hypervisor exists. That node contains a
+compatible property with the value "linux,kvm".
+
+Once you determined you're running under a PV capable KVM, you can now use
+hypercalls as described below.
+
+KVM hypercalls
+==============
+
+Inside the device tree's /hypervisor node there's a property called
+'hypercall-instructions'. This property contains at most 4 opcodes that make
+up the hypercall. To call a hypercall, just call these instructions.
+
+The parameters are as follows:
+
+       Register        IN                      OUT
+
+       r0              -                       volatile
+       r3              1st parameter           Return code
+       r4              2nd parameter           1st output value
+       r5              3rd parameter           2nd output value
+       r6              4th parameter           3rd output value
+       r7              5th parameter           4th output value
+       r8              6th parameter           5th output value
+       r9              7th parameter           6th output value
+       r10             8th parameter           7th output value
+       r11             hypercall number        8th output value
+       r12             -                       volatile
+
+Hypercall definitions are shared in generic code, so the same hypercall numbers
+apply for x86 and powerpc alike with the exception that each KVM hypercall
+also needs to be ORed with the KVM vendor code which is (42 << 16).
+
+Return codes can be as follows:
+
+       Code            Meaning
+
+       0               Success
+       12              Hypercall not implemented
+       <0              Error
+
+The magic page
+==============
+
+To enable communication between the hypervisor and guest there is a new shared
+page that contains parts of supervisor visible register state. The guest can
+map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
+
+With this hypercall issued the guest always gets the magic page mapped at the
+desired location. The first parameter indicates the effective address when the
+MMU is enabled. The second parameter indicates the address in real mode, if
+applicable to the target. For now, we always map the page to -4096. This way we
+can access it using absolute load and store functions. The following
+instruction reads the first field of the magic page:
+
+       ld      rX, -4096(0)
+
+The interface is designed to be extensible should there be need later to add
+additional registers to the magic page. If you add fields to the magic page,
+also define a new hypercall feature to indicate that the host can give you more
+registers. Only if the host supports the additional features, make use of them.
+
+The magic page layout is described by struct kvm_vcpu_arch_shared
+in arch/powerpc/include/asm/kvm_para.h.
+
+Magic page features
+===================
+
+When mapping the magic page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE,
+a second return value is passed to the guest. This second return value contains
+a bitmap of available features inside the magic page.
+
+The following enhancements to the magic page are currently available:
+
+  KVM_MAGIC_FEAT_SR            Maps SR registers r/w in the magic page
+  KVM_MAGIC_FEAT_MAS0_TO_SPRG7 Maps MASn, ESR, PIR and high SPRGs
+
+For enhanced features in the magic page, please check for the existence of the
+feature before using them!
+
+Magic page flags
+================
+
+In addition to features that indicate whether a host is capable of a particular
+feature we also have a channel for a guest to tell the guest whether it's capable
+of something. This is what we call "flags".
+
+Flags are passed to the host in the low 12 bits of the Effective Address.
+
+The following flags are currently available for a guest to expose:
+
+  MAGIC_PAGE_FLAG_NOT_MAPPED_NX Guest handles NX bits correctly wrt magic page
+
+MSR bits
+========
+
+The MSR contains bits that require hypervisor intervention and bits that do
+not require direct hypervisor intervention because they only get interpreted
+when entering the guest or don't have any impact on the hypervisor's behavior.
+
+The following bits are safe to be set inside the guest:
+
+  MSR_EE
+  MSR_RI
+
+If any other bit changes in the MSR, please still use mtmsr(d).
+
+Patched instructions
+====================
+
+The "ld" and "std" instructions are transformed to "lwz" and "stw" instructions
+respectively on 32 bit systems with an added offset of 4 to accommodate for big
+endianness.
+
+The following is a list of mapping the Linux kernel performs when running as
+guest. Implementing any of those mappings is optional, as the instruction traps
+also act on the shared page. So calling privileged instructions still works as
+before.
+
+From                   To
+====                   ==
+
+mfmsr  rX              ld      rX, magic_page->msr
+mfsprg rX, 0           ld      rX, magic_page->sprg0
+mfsprg rX, 1           ld      rX, magic_page->sprg1
+mfsprg rX, 2           ld      rX, magic_page->sprg2
+mfsprg rX, 3           ld      rX, magic_page->sprg3
+mfsrr0 rX              ld      rX, magic_page->srr0
+mfsrr1 rX              ld      rX, magic_page->srr1
+mfdar  rX              ld      rX, magic_page->dar
+mfdsisr        rX              lwz     rX, magic_page->dsisr
+
+mtmsr  rX              std     rX, magic_page->msr
+mtsprg 0, rX           std     rX, magic_page->sprg0
+mtsprg 1, rX           std     rX, magic_page->sprg1
+mtsprg 2, rX           std     rX, magic_page->sprg2
+mtsprg 3, rX           std     rX, magic_page->sprg3
+mtsrr0 rX              std     rX, magic_page->srr0
+mtsrr1 rX              std     rX, magic_page->srr1
+mtdar  rX              std     rX, magic_page->dar
+mtdsisr        rX              stw     rX, magic_page->dsisr
+
+tlbsync                        nop
+
+mtmsrd rX, 0           b       <special mtmsr section>
+mtmsr  rX              b       <special mtmsr section>
+
+mtmsrd rX, 1           b       <special mtmsrd section>
+
+[Book3S only]
+mtsrin rX, rY          b       <special mtsrin section>
+
+[BookE only]
+wrteei [0|1]           b       <special wrteei section>
+
+
+Some instructions require more logic to determine what's going on than a load
+or store instruction can deliver. To enable patching of those, we keep some
+RAM around where we can live translate instructions to. What happens is the
+following:
+
+       1) copy emulation code to memory
+       2) patch that code to fit the emulated instruction
+       3) patch that code to return to the original pc + 4
+       4) patch the original instruction to branch to the new code
+
+That way we can inject an arbitrary amount of code as replacement for a single
+instruction. This allows us to check for pending interrupts when setting EE=1
+for example.
+
+Hypercall ABIs in KVM on PowerPC
+=================================
+1) KVM hypercalls (ePAPR)
+
+These are ePAPR compliant hypercall implementation (mentioned above). Even
+generic hypercalls are implemented here, like the ePAPR idle hcall. These are
+available on all targets.
+
+2) PAPR hypercalls
+
+PAPR hypercalls are needed to run server PowerPC PAPR guests (-M pseries in QEMU).
+These are the same hypercalls that pHyp, the POWER hypervisor implements. Some of
+them are handled in the kernel, some are handled in user space. This is only
+available on book3s_64.
+
+3) OSI hypercalls
+
+Mac-on-Linux is another user of KVM on PowerPC, which has its own hypercall (long
+before KVM). This is supported to maintain compatibility. All these hypercalls get
+forwarded to user space. This is only useful on book3s_32, but can be used with
+book3s_64 as well.
diff --git a/Documentation/virt/kvm/review-checklist.txt b/Documentation/virt/kvm/review-checklist.txt
new file mode 100644 (file)
index 0000000..499af49
--- /dev/null
@@ -0,0 +1,38 @@
+Review checklist for kvm patches
+================================
+
+1.  The patch must follow Documentation/process/coding-style.rst and
+    Documentation/process/submitting-patches.rst.
+
+2.  Patches should be against kvm.git master branch.
+
+3.  If the patch introduces or modifies a new userspace API:
+    - the API must be documented in Documentation/virt/kvm/api.txt
+    - the API must be discoverable using KVM_CHECK_EXTENSION
+
+4.  New state must include support for save/restore.
+
+5.  New features must default to off (userspace should explicitly request them).
+    Performance improvements can and should default to on.
+
+6.  New cpu features should be exposed via KVM_GET_SUPPORTED_CPUID2
+
+7.  Emulator changes should be accompanied by unit tests for qemu-kvm.git
+    kvm/test directory.
+
+8.  Changes should be vendor neutral when possible.  Changes to common code
+    are better than duplicating changes to vendor code.
+
+9.  Similarly, prefer changes to arch independent code than to arch dependent
+    code.
+
+10. User/kernel interfaces and guest/host interfaces must be 64-bit clean
+    (all variables and sizes naturally aligned on 64-bit; use specific types
+    only - u64 rather than ulong).
+
+11. New guest visible features must either be documented in a hardware manual
+    or be accompanied by documentation.
+
+12. Features must be robust against reset and kexec - for example, shared
+    host/guest memory must be unshared to prevent the host from writing to
+    guest memory that the guest has not reserved for this purpose.
diff --git a/Documentation/virt/kvm/s390-diag.txt b/Documentation/virt/kvm/s390-diag.txt
new file mode 100644 (file)
index 0000000..7c52e5f
--- /dev/null
@@ -0,0 +1,83 @@
+The s390 DIAGNOSE call on KVM
+=============================
+
+KVM on s390 supports the DIAGNOSE call for making hypercalls, both for
+native hypercalls and for selected hypercalls found on other s390
+hypervisors.
+
+Note that bits are numbered as by the usual s390 convention (most significant
+bit on the left).
+
+
+General remarks
+---------------
+
+DIAGNOSE calls by the guest cause a mandatory intercept. This implies
+all supported DIAGNOSE calls need to be handled by either KVM or its
+userspace.
+
+All DIAGNOSE calls supported by KVM use the RS-a format:
+
+--------------------------------------
+|  '83'  | R1 | R3 | B2 |     D2     |
+--------------------------------------
+0        8    12   16   20           31
+
+The second-operand address (obtained by the base/displacement calculation)
+is not used to address data. Instead, bits 48-63 of this address specify
+the function code, and bits 0-47 are ignored.
+
+The supported DIAGNOSE function codes vary by the userspace used. For
+DIAGNOSE function codes not specific to KVM, please refer to the
+documentation for the s390 hypervisors defining them.
+
+
+DIAGNOSE function code 'X'500' - KVM virtio functions
+-----------------------------------------------------
+
+If the function code specifies 0x500, various virtio-related functions
+are performed.
+
+General register 1 contains the virtio subfunction code. Supported
+virtio subfunctions depend on KVM's userspace. Generally, userspace
+provides either s390-virtio (subcodes 0-2) or virtio-ccw (subcode 3).
+
+Upon completion of the DIAGNOSE instruction, general register 2 contains
+the function's return code, which is either a return code or a subcode
+specific value.
+
+Subcode 0 - s390-virtio notification and early console printk
+    Handled by userspace.
+
+Subcode 1 - s390-virtio reset
+    Handled by userspace.
+
+Subcode 2 - s390-virtio set status
+    Handled by userspace.
+
+Subcode 3 - virtio-ccw notification
+    Handled by either userspace or KVM (ioeventfd case).
+
+    General register 2 contains a subchannel-identification word denoting
+    the subchannel of the virtio-ccw proxy device to be notified.
+
+    General register 3 contains the number of the virtqueue to be notified.
+
+    General register 4 contains a 64bit identifier for KVM usage (the
+    kvm_io_bus cookie). If general register 4 does not contain a valid
+    identifier, it is ignored.
+
+    After completion of the DIAGNOSE call, general register 2 may contain
+    a 64bit identifier (in the kvm_io_bus cookie case), or a negative
+    error value, if an internal error occurred.
+
+    See also the virtio standard for a discussion of this hypercall.
+
+
+DIAGNOSE function code 'X'501 - KVM breakpoint
+----------------------------------------------
+
+If the function code specifies 0x501, breakpoint functions may be performed.
+This function code is handled by userspace.
+
+This diagnose function code has no subfunctions and uses no parameters.
diff --git a/Documentation/virt/kvm/timekeeping.txt b/Documentation/virt/kvm/timekeeping.txt
new file mode 100644 (file)
index 0000000..76808a1
--- /dev/null
@@ -0,0 +1,612 @@
+
+       Timekeeping Virtualization for X86-Based Architectures
+
+       Zachary Amsden <zamsden@redhat.com>
+       Copyright (c) 2010, Red Hat.  All rights reserved.
+
+1) Overview
+2) Timing Devices
+3) TSC Hardware
+4) Virtualization Problems
+
+=========================================================================
+
+1) Overview
+
+One of the most complicated parts of the X86 platform, and specifically,
+the virtualization of this platform is the plethora of timing devices available
+and the complexity of emulating those devices.  In addition, virtualization of
+time introduces a new set of challenges because it introduces a multiplexed
+division of time beyond the control of the guest CPU.
+
+First, we will describe the various timekeeping hardware available, then
+present some of the problems which arise and solutions available, giving
+specific recommendations for certain classes of KVM guests.
+
+The purpose of this document is to collect data and information relevant to
+timekeeping which may be difficult to find elsewhere, specifically,
+information relevant to KVM and hardware-based virtualization.
+
+=========================================================================
+
+2) Timing Devices
+
+First we discuss the basic hardware devices available.  TSC and the related
+KVM clock are special enough to warrant a full exposition and are described in
+the following section.
+
+2.1) i8254 - PIT
+
+One of the first timer devices available is the programmable interrupt timer,
+or PIT.  The PIT has a fixed frequency 1.193182 MHz base clock and three
+channels which can be programmed to deliver periodic or one-shot interrupts.
+These three channels can be configured in different modes and have individual
+counters.  Channel 1 and 2 were not available for general use in the original
+IBM PC, and historically were connected to control RAM refresh and the PC
+speaker.  Now the PIT is typically integrated as part of an emulated chipset
+and a separate physical PIT is not used.
+
+The PIT uses I/O ports 0x40 - 0x43.  Access to the 16-bit counters is done
+using single or multiple byte access to the I/O ports.  There are 6 modes
+available, but not all modes are available to all timers, as only timer 2
+has a connected gate input, required for modes 1 and 5.  The gate line is
+controlled by port 61h, bit 0, as illustrated in the following diagram.
+
+ --------------             ----------------
+|              |           |                |
+|  1.1932 MHz  |---------->| CLOCK      OUT | ---------> IRQ 0
+|    Clock     |   |       |                |
+ --------------    |    +->| GATE  TIMER 0  |
+                   |        ----------------
+                   |
+                   |        ----------------
+                   |       |                |
+                   |------>| CLOCK      OUT | ---------> 66.3 KHZ DRAM
+                   |       |                |            (aka /dev/null)
+                   |    +->| GATE  TIMER 1  |
+                   |        ----------------
+                   |
+                   |        ----------------
+                   |       |                |
+                   |------>| CLOCK      OUT | ---------> Port 61h, bit 5
+                           |                |      |
+Port 61h, bit 0 ---------->| GATE  TIMER 2  |       \_.----   ____
+                            ----------------         _|    )--|LPF|---Speaker
+                                                    / *----   \___/
+Port 61h, bit 1 -----------------------------------/
+
+The timer modes are now described.
+
+Mode 0: Single Timeout.   This is a one-shot software timeout that counts down
+ when the gate is high (always true for timers 0 and 1).  When the count
+ reaches zero, the output goes high.
+
+Mode 1: Triggered One-shot.  The output is initially set high.  When the gate
+ line is set high, a countdown is initiated (which does not stop if the gate is
+ lowered), during which the output is set low.  When the count reaches zero,
+ the output goes high.
+
+Mode 2: Rate Generator.  The output is initially set high.  When the countdown
+ reaches 1, the output goes low for one count and then returns high.  The value
+ is reloaded and the countdown automatically resumes.  If the gate line goes
+ low, the count is halted.  If the output is low when the gate is lowered, the
+ output automatically goes high (this only affects timer 2).
+
+Mode 3: Square Wave.   This generates a high / low square wave.  The count
+ determines the length of the pulse, which alternates between high and low
+ when zero is reached.  The count only proceeds when gate is high and is
+ automatically reloaded on reaching zero.  The count is decremented twice at
+ each clock to generate a full high / low cycle at the full periodic rate.
+ If the count is even, the clock remains high for N/2 counts and low for N/2
+ counts; if the clock is odd, the clock is high for (N+1)/2 counts and low
+ for (N-1)/2 counts.  Only even values are latched by the counter, so odd
+ values are not observed when reading.  This is the intended mode for timer 2,
+ which generates sine-like tones by low-pass filtering the square wave output.
+
+Mode 4: Software Strobe.  After programming this mode and loading the counter,
+ the output remains high until the counter reaches zero.  Then the output
+ goes low for 1 clock cycle and returns high.  The counter is not reloaded.
+ Counting only occurs when gate is high.
+
+Mode 5: Hardware Strobe.  After programming and loading the counter, the
+ output remains high.  When the gate is raised, a countdown is initiated
+ (which does not stop if the gate is lowered).  When the counter reaches zero,
+ the output goes low for 1 clock cycle and then returns high.  The counter is
+ not reloaded.
+
+In addition to normal binary counting, the PIT supports BCD counting.  The
+command port, 0x43 is used to set the counter and mode for each of the three
+timers.
+
+PIT commands, issued to port 0x43, using the following bit encoding:
+
+Bit 7-4: Command (See table below)
+Bit 3-1: Mode (000 = Mode 0, 101 = Mode 5, 11X = undefined)
+Bit 0  : Binary (0) / BCD (1)
+
+Command table:
+
+0000 - Latch Timer 0 count for port 0x40
+       sample and hold the count to be read in port 0x40;
+       additional commands ignored until counter is read;
+       mode bits ignored.
+
+0001 - Set Timer 0 LSB mode for port 0x40
+       set timer to read LSB only and force MSB to zero;
+       mode bits set timer mode
+
+0010 - Set Timer 0 MSB mode for port 0x40
+       set timer to read MSB only and force LSB to zero;
+       mode bits set timer mode
+
+0011 - Set Timer 0 16-bit mode for port 0x40
+       set timer to read / write LSB first, then MSB;
+       mode bits set timer mode
+
+0100 - Latch Timer 1 count for port 0x41 - as described above
+0101 - Set Timer 1 LSB mode for port 0x41 - as described above
+0110 - Set Timer 1 MSB mode for port 0x41 - as described above
+0111 - Set Timer 1 16-bit mode for port 0x41 - as described above
+
+1000 - Latch Timer 2 count for port 0x42 - as described above
+1001 - Set Timer 2 LSB mode for port 0x42 - as described above
+1010 - Set Timer 2 MSB mode for port 0x42 - as described above
+1011 - Set Timer 2 16-bit mode for port 0x42 as described above
+
+1101 - General counter latch
+       Latch combination of counters into corresponding ports
+       Bit 3 = Counter 2
+       Bit 2 = Counter 1
+       Bit 1 = Counter 0
+       Bit 0 = Unused
+
+1110 - Latch timer status
+       Latch combination of counter mode into corresponding ports
+       Bit 3 = Counter 2
+       Bit 2 = Counter 1
+       Bit 1 = Counter 0
+
+       The output of ports 0x40-0x42 following this command will be:
+
+       Bit 7 = Output pin
+       Bit 6 = Count loaded (0 if timer has expired)
+       Bit 5-4 = Read / Write mode
+           01 = MSB only
+           10 = LSB only
+           11 = LSB / MSB (16-bit)
+       Bit 3-1 = Mode
+       Bit 0 = Binary (0) / BCD mode (1)
+
+2.2) RTC
+
+The second device which was available in the original PC was the MC146818 real
+time clock.  The original device is now obsolete, and usually emulated by the
+system chipset, sometimes by an HPET and some frankenstein IRQ routing.
+
+The RTC is accessed through CMOS variables, which uses an index register to
+control which bytes are read.  Since there is only one index register, read
+of the CMOS and read of the RTC require lock protection (in addition, it is
+dangerous to allow userspace utilities such as hwclock to have direct RTC
+access, as they could corrupt kernel reads and writes of CMOS memory).
+
+The RTC generates an interrupt which is usually routed to IRQ 8.  The interrupt
+can function as a periodic timer, an additional once a day alarm, and can issue
+interrupts after an update of the CMOS registers by the MC146818 is complete.
+The type of interrupt is signalled in the RTC status registers.
+
+The RTC will update the current time fields by battery power even while the
+system is off.  The current time fields should not be read while an update is
+in progress, as indicated in the status register.
+
+The clock uses a 32.768kHz crystal, so bits 6-4 of register A should be
+programmed to a 32kHz divider if the RTC is to count seconds.
+
+This is the RAM map originally used for the RTC/CMOS:
+
+Location    Size    Description
+------------------------------------------
+00h         byte    Current second (BCD)
+01h         byte    Seconds alarm (BCD)
+02h         byte    Current minute (BCD)
+03h         byte    Minutes alarm (BCD)
+04h         byte    Current hour (BCD)
+05h         byte    Hours alarm (BCD)
+06h         byte    Current day of week (BCD)
+07h         byte    Current day of month (BCD)
+08h         byte    Current month (BCD)
+09h         byte    Current year (BCD)
+0Ah         byte    Register A
+                       bit 7   = Update in progress
+                       bit 6-4 = Divider for clock
+                                  000 = 4.194 MHz
+                                  001 = 1.049 MHz
+                                  010 = 32 kHz
+                                  10X = test modes
+                                  110 = reset / disable
+                                  111 = reset / disable
+                       bit 3-0 = Rate selection for periodic interrupt
+                                  000 = periodic timer disabled
+                                  001 = 3.90625 uS
+                                  010 = 7.8125 uS
+                                  011 = .122070 mS
+                                  100 = .244141 mS
+                                     ...
+                                 1101 = 125 mS
+                                 1110 = 250 mS
+                                 1111 = 500 mS
+0Bh         byte    Register B
+                       bit 7   = Run (0) / Halt (1)
+                       bit 6   = Periodic interrupt enable
+                       bit 5   = Alarm interrupt enable
+                       bit 4   = Update-ended interrupt enable
+                       bit 3   = Square wave interrupt enable
+                       bit 2   = BCD calendar (0) / Binary (1)
+                       bit 1   = 12-hour mode (0) / 24-hour mode (1)
+                       bit 0   = 0 (DST off) / 1 (DST enabled)
+OCh         byte    Register C (read only)
+                       bit 7   = interrupt request flag (IRQF)
+                       bit 6   = periodic interrupt flag (PF)
+                       bit 5   = alarm interrupt flag (AF)
+                       bit 4   = update interrupt flag (UF)
+                       bit 3-0 = reserved
+ODh         byte    Register D (read only)
+                       bit 7   = RTC has power
+                       bit 6-0 = reserved
+32h         byte    Current century BCD (*)
+  (*) location vendor specific and now determined from ACPI global tables
+
+2.3) APIC
+
+On Pentium and later processors, an on-board timer is available to each CPU
+as part of the Advanced Programmable Interrupt Controller.  The APIC is
+accessed through memory-mapped registers and provides interrupt service to each
+CPU, used for IPIs and local timer interrupts.
+
+Although in theory the APIC is a safe and stable source for local interrupts,
+in practice, many bugs and glitches have occurred due to the special nature of
+the APIC CPU-local memory-mapped hardware.  Beware that CPU errata may affect
+the use of the APIC and that workarounds may be required.  In addition, some of
+these workarounds pose unique constraints for virtualization - requiring either
+extra overhead incurred from extra reads of memory-mapped I/O or additional
+functionality that may be more computationally expensive to implement.
+
+Since the APIC is documented quite well in the Intel and AMD manuals, we will
+avoid repetition of the detail here.  It should be pointed out that the APIC
+timer is programmed through the LVT (local vector timer) register, is capable
+of one-shot or periodic operation, and is based on the bus clock divided down
+by the programmable divider register.
+
+2.4) HPET
+
+HPET is quite complex, and was originally intended to replace the PIT / RTC
+support of the X86 PC.  It remains to be seen whether that will be the case, as
+the de facto standard of PC hardware is to emulate these older devices.  Some
+systems designated as legacy free may support only the HPET as a hardware timer
+device.
+
+The HPET spec is rather loose and vague, requiring at least 3 hardware timers,
+but allowing implementation freedom to support many more.  It also imposes no
+fixed rate on the timer frequency, but does impose some extremal values on
+frequency, error and slew.
+
+In general, the HPET is recommended as a high precision (compared to PIT /RTC)
+time source which is independent of local variation (as there is only one HPET
+in any given system).  The HPET is also memory-mapped, and its presence is
+indicated through ACPI tables by the BIOS.
+
+Detailed specification of the HPET is beyond the current scope of this
+document, as it is also very well documented elsewhere.
+
+2.5) Offboard Timers
+
+Several cards, both proprietary (watchdog boards) and commonplace (e1000) have
+timing chips built into the cards which may have registers which are accessible
+to kernel or user drivers.  To the author's knowledge, using these to generate
+a clocksource for a Linux or other kernel has not yet been attempted and is in
+general frowned upon as not playing by the agreed rules of the game.  Such a
+timer device would require additional support to be virtualized properly and is
+not considered important at this time as no known operating system does this.
+
+=========================================================================
+
+3) TSC Hardware
+
+The TSC or time stamp counter is relatively simple in theory; it counts
+instruction cycles issued by the processor, which can be used as a measure of
+time.  In practice, due to a number of problems, it is the most complicated
+timekeeping device to use.
+
+The TSC is represented internally as a 64-bit MSR which can be read with the
+RDMSR, RDTSC, or RDTSCP (when available) instructions.  In the past, hardware
+limitations made it possible to write the TSC, but generally on old hardware it
+was only possible to write the low 32-bits of the 64-bit counter, and the upper
+32-bits of the counter were cleared.  Now, however, on Intel processors family
+0Fh, for models 3, 4 and 6, and family 06h, models e and f, this restriction
+has been lifted and all 64-bits are writable.  On AMD systems, the ability to
+write the TSC MSR is not an architectural guarantee.
+
+The TSC is accessible from CPL-0 and conditionally, for CPL > 0 software by
+means of the CR4.TSD bit, which when enabled, disables CPL > 0 TSC access.
+
+Some vendors have implemented an additional instruction, RDTSCP, which returns
+atomically not just the TSC, but an indicator which corresponds to the
+processor number.  This can be used to index into an array of TSC variables to
+determine offset information in SMP systems where TSCs are not synchronized.
+The presence of this instruction must be determined by consulting CPUID feature
+bits.
+
+Both VMX and SVM provide extension fields in the virtualization hardware which
+allows the guest visible TSC to be offset by a constant.  Newer implementations
+promise to allow the TSC to additionally be scaled, but this hardware is not
+yet widely available.
+
+3.1) TSC synchronization
+
+The TSC is a CPU-local clock in most implementations.  This means, on SMP
+platforms, the TSCs of different CPUs may start at different times depending
+on when the CPUs are powered on.  Generally, CPUs on the same die will share
+the same clock, however, this is not always the case.
+
+The BIOS may attempt to resynchronize the TSCs during the poweron process and
+the operating system or other system software may attempt to do this as well.
+Several hardware limitations make the problem worse - if it is not possible to
+write the full 64-bits of the TSC, it may be impossible to match the TSC in
+newly arriving CPUs to that of the rest of the system, resulting in
+unsynchronized TSCs.  This may be done by BIOS or system software, but in
+practice, getting a perfectly synchronized TSC will not be possible unless all
+values are read from the same clock, which generally only is possible on single
+socket systems or those with special hardware support.
+
+3.2) TSC and CPU hotplug
+
+As touched on already, CPUs which arrive later than the boot time of the system
+may not have a TSC value that is synchronized with the rest of the system.
+Either system software, BIOS, or SMM code may actually try to establish the TSC
+to a value matching the rest of the system, but a perfect match is usually not
+a guarantee.  This can have the effect of bringing a system from a state where
+TSC is synchronized back to a state where TSC synchronization flaws, however
+small, may be exposed to the OS and any virtualization environment.
+
+3.3) TSC and multi-socket / NUMA
+
+Multi-socket systems, especially large multi-socket systems are likely to have
+individual clocksources rather than a single, universally distributed clock.
+Since these clocks are driven by different crystals, they will not have
+perfectly matched frequency, and temperature and electrical variations will
+cause the CPU clocks, and thus the TSCs to drift over time.  Depending on the
+exact clock and bus design, the drift may or may not be fixed in absolute
+error, and may accumulate over time.
+
+In addition, very large systems may deliberately slew the clocks of individual
+cores.  This technique, known as spread-spectrum clocking, reduces EMI at the
+clock frequency and harmonics of it, which may be required to pass FCC
+standards for telecommunications and computer equipment.
+
+It is recommended not to trust the TSCs to remain synchronized on NUMA or
+multiple socket systems for these reasons.
+
+3.4) TSC and C-states
+
+C-states, or idling states of the processor, especially C1E and deeper sleep
+states may be problematic for TSC as well.  The TSC may stop advancing in such
+a state, resulting in a TSC which is behind that of other CPUs when execution
+is resumed.  Such CPUs must be detected and flagged by the operating system
+based on CPU and chipset identifications.
+
+The TSC in such a case may be corrected by catching it up to a known external
+clocksource.
+
+3.5) TSC frequency change / P-states
+
+To make things slightly more interesting, some CPUs may change frequency.  They
+may or may not run the TSC at the same rate, and because the frequency change
+may be staggered or slewed, at some points in time, the TSC rate may not be
+known other than falling within a range of values.  In this case, the TSC will
+not be a stable time source, and must be calibrated against a known, stable,
+external clock to be a usable source of time.
+
+Whether the TSC runs at a constant rate or scales with the P-state is model
+dependent and must be determined by inspecting CPUID, chipset or vendor
+specific MSR fields.
+
+In addition, some vendors have known bugs where the P-state is actually
+compensated for properly during normal operation, but when the processor is
+inactive, the P-state may be raised temporarily to service cache misses from
+other processors.  In such cases, the TSC on halted CPUs could advance faster
+than that of non-halted processors.  AMD Turion processors are known to have
+this problem.
+
+3.6) TSC and STPCLK / T-states
+
+External signals given to the processor may also have the effect of stopping
+the TSC.  This is typically done for thermal emergency power control to prevent
+an overheating condition, and typically, there is no way to detect that this
+condition has happened.
+
+3.7) TSC virtualization - VMX
+
+VMX provides conditional trapping of RDTSC, RDMSR, WRMSR and RDTSCP
+instructions, which is enough for full virtualization of TSC in any manner.  In
+addition, VMX allows passing through the host TSC plus an additional TSC_OFFSET
+field specified in the VMCS.  Special instructions must be used to read and
+write the VMCS field.
+
+3.8) TSC virtualization - SVM
+
+SVM provides conditional trapping of RDTSC, RDMSR, WRMSR and RDTSCP
+instructions, which is enough for full virtualization of TSC in any manner.  In
+addition, SVM allows passing through the host TSC plus an additional offset
+field specified in the SVM control block.
+
+3.9) TSC feature bits in Linux
+
+In summary, there is no way to guarantee the TSC remains in perfect
+synchronization unless it is explicitly guaranteed by the architecture.  Even
+if so, the TSCs in multi-sockets or NUMA systems may still run independently
+despite being locally consistent.
+
+The following feature bits are used by Linux to signal various TSC attributes,
+but they can only be taken to be meaningful for UP or single node systems.
+
+X86_FEATURE_TSC                : The TSC is available in hardware
+X86_FEATURE_RDTSCP             : The RDTSCP instruction is available
+X86_FEATURE_CONSTANT_TSC       : The TSC rate is unchanged with P-states
+X86_FEATURE_NONSTOP_TSC                : The TSC does not stop in C-states
+X86_FEATURE_TSC_RELIABLE       : TSC sync checks are skipped (VMware)
+
+4) Virtualization Problems
+
+Timekeeping is especially problematic for virtualization because a number of
+challenges arise.  The most obvious problem is that time is now shared between
+the host and, potentially, a number of virtual machines.  Thus the virtual
+operating system does not run with 100% usage of the CPU, despite the fact that
+it may very well make that assumption.  It may expect it to remain true to very
+exacting bounds when interrupt sources are disabled, but in reality only its
+virtual interrupt sources are disabled, and the machine may still be preempted
+at any time.  This causes problems as the passage of real time, the injection
+of machine interrupts and the associated clock sources are no longer completely
+synchronized with real time.
+
+This same problem can occur on native hardware to a degree, as SMM mode may
+steal cycles from the naturally on X86 systems when SMM mode is used by the
+BIOS, but not in such an extreme fashion.  However, the fact that SMM mode may
+cause similar problems to virtualization makes it a good justification for
+solving many of these problems on bare metal.
+
+4.1) Interrupt clocking
+
+One of the most immediate problems that occurs with legacy operating systems
+is that the system timekeeping routines are often designed to keep track of
+time by counting periodic interrupts.  These interrupts may come from the PIT
+or the RTC, but the problem is the same: the host virtualization engine may not
+be able to deliver the proper number of interrupts per second, and so guest
+time may fall behind.  This is especially problematic if a high interrupt rate
+is selected, such as 1000 HZ, which is unfortunately the default for many Linux
+guests.
+
+There are three approaches to solving this problem; first, it may be possible
+to simply ignore it.  Guests which have a separate time source for tracking
+'wall clock' or 'real time' may not need any adjustment of their interrupts to
+maintain proper time.  If this is not sufficient, it may be necessary to inject
+additional interrupts into the guest in order to increase the effective
+interrupt rate.  This approach leads to complications in extreme conditions,
+where host load or guest lag is too much to compensate for, and thus another
+solution to the problem has risen: the guest may need to become aware of lost
+ticks and compensate for them internally.  Although promising in theory, the
+implementation of this policy in Linux has been extremely error prone, and a
+number of buggy variants of lost tick compensation are distributed across
+commonly used Linux systems.
+
+Windows uses periodic RTC clocking as a means of keeping time internally, and
+thus requires interrupt slewing to keep proper time.  It does use a low enough
+rate (ed: is it 18.2 Hz?) however that it has not yet been a problem in
+practice.
+
+4.2) TSC sampling and serialization
+
+As the highest precision time source available, the cycle counter of the CPU
+has aroused much interest from developers.  As explained above, this timer has
+many problems unique to its nature as a local, potentially unstable and
+potentially unsynchronized source.  One issue which is not unique to the TSC,
+but is highlighted because of its very precise nature is sampling delay.  By
+definition, the counter, once read is already old.  However, it is also
+possible for the counter to be read ahead of the actual use of the result.
+This is a consequence of the superscalar execution of the instruction stream,
+which may execute instructions out of order.  Such execution is called
+non-serialized.  Forcing serialized execution is necessary for precise
+measurement with the TSC, and requires a serializing instruction, such as CPUID
+or an MSR read.
+
+Since CPUID may actually be virtualized by a trap and emulate mechanism, this
+serialization can pose a performance issue for hardware virtualization.  An
+accurate time stamp counter reading may therefore not always be available, and
+it may be necessary for an implementation to guard against "backwards" reads of
+the TSC as seen from other CPUs, even in an otherwise perfectly synchronized
+system.
+
+4.3) Timespec aliasing
+
+Additionally, this lack of serialization from the TSC poses another challenge
+when using results of the TSC when measured against another time source.  As
+the TSC is much higher precision, many possible values of the TSC may be read
+while another clock is still expressing the same value.
+
+That is, you may read (T,T+10) while external clock C maintains the same value.
+Due to non-serialized reads, you may actually end up with a range which
+fluctuates - from (T-1.. T+10).  Thus, any time calculated from a TSC, but
+calibrated against an external value may have a range of valid values.
+Re-calibrating this computation may actually cause time, as computed after the
+calibration, to go backwards, compared with time computed before the
+calibration.
+
+This problem is particularly pronounced with an internal time source in Linux,
+the kernel time, which is expressed in the theoretically high resolution
+timespec - but which advances in much larger granularity intervals, sometimes
+at the rate of jiffies, and possibly in catchup modes, at a much larger step.
+
+This aliasing requires care in the computation and recalibration of kvmclock
+and any other values derived from TSC computation (such as TSC virtualization
+itself).
+
+4.4) Migration
+
+Migration of a virtual machine raises problems for timekeeping in two ways.
+First, the migration itself may take time, during which interrupts cannot be
+delivered, and after which, the guest time may need to be caught up.  NTP may
+be able to help to some degree here, as the clock correction required is
+typically small enough to fall in the NTP-correctable window.
+
+An additional concern is that timers based off the TSC (or HPET, if the raw bus
+clock is exposed) may now be running at different rates, requiring compensation
+in some way in the hypervisor by virtualizing these timers.  In addition,
+migrating to a faster machine may preclude the use of a passthrough TSC, as a
+faster clock cannot be made visible to a guest without the potential of time
+advancing faster than usual.  A slower clock is less of a problem, as it can
+always be caught up to the original rate.  KVM clock avoids these problems by
+simply storing multipliers and offsets against the TSC for the guest to convert
+back into nanosecond resolution values.
+
+4.5) Scheduling
+
+Since scheduling may be based on precise timing and firing of interrupts, the
+scheduling algorithms of an operating system may be adversely affected by
+virtualization.  In theory, the effect is random and should be universally
+distributed, but in contrived as well as real scenarios (guest device access,
+causes of virtualization exits, possible context switch), this may not always
+be the case.  The effect of this has not been well studied.
+
+In an attempt to work around this, several implementations have provided a
+paravirtualized scheduler clock, which reveals the true amount of CPU time for
+which a virtual machine has been running.
+
+4.6) Watchdogs
+
+Watchdog timers, such as the lock detector in Linux may fire accidentally when
+running under hardware virtualization due to timer interrupts being delayed or
+misinterpretation of the passage of real time.  Usually, these warnings are
+spurious and can be ignored, but in some circumstances it may be necessary to
+disable such detection.
+
+4.7) Delays and precision timing
+
+Precise timing and delays may not be possible in a virtualized system.  This
+can happen if the system is controlling physical hardware, or issues delays to
+compensate for slower I/O to and from devices.  The first issue is not solvable
+in general for a virtualized system; hardware control software can't be
+adequately virtualized without a full real-time operating system, which would
+require an RT aware virtualization platform.
+
+The second issue may cause performance problems, but this is unlikely to be a
+significant issue.  In many cases these delays may be eliminated through
+configuration or paravirtualization.
+
+4.8) Covert channels and leaks
+
+In addition to the above problems, time information will inevitably leak to the
+guest about the host in anything but a perfect implementation of virtualized
+time.  This may allow the guest to infer the presence of a hypervisor (as in a
+red-pill type detection), and it may allow information to leak between guests
+by using CPU utilization itself as a signalling channel.  Preventing such
+problems would require completely isolated virtual time which may not track
+real time any longer.  This may be useful in certain security or QA contexts,
+but in general isn't recommended for real-world deployment scenarios.
diff --git a/Documentation/virt/kvm/vcpu-requests.rst b/Documentation/virt/kvm/vcpu-requests.rst
new file mode 100644 (file)
index 0000000..5feb370
--- /dev/null
@@ -0,0 +1,307 @@
+=================
+KVM VCPU Requests
+=================
+
+Overview
+========
+
+KVM supports an internal API enabling threads to request a VCPU thread to
+perform some activity.  For example, a thread may request a VCPU to flush
+its TLB with a VCPU request.  The API consists of the following functions::
+
+  /* Check if any requests are pending for VCPU @vcpu. */
+  bool kvm_request_pending(struct kvm_vcpu *vcpu);
+
+  /* Check if VCPU @vcpu has request @req pending. */
+  bool kvm_test_request(int req, struct kvm_vcpu *vcpu);
+
+  /* Clear request @req for VCPU @vcpu. */
+  void kvm_clear_request(int req, struct kvm_vcpu *vcpu);
+
+  /*
+   * Check if VCPU @vcpu has request @req pending. When the request is
+   * pending it will be cleared and a memory barrier, which pairs with
+   * another in kvm_make_request(), will be issued.
+   */
+  bool kvm_check_request(int req, struct kvm_vcpu *vcpu);
+
+  /*
+   * Make request @req of VCPU @vcpu. Issues a memory barrier, which pairs
+   * with another in kvm_check_request(), prior to setting the request.
+   */
+  void kvm_make_request(int req, struct kvm_vcpu *vcpu);
+
+  /* Make request @req of all VCPUs of the VM with struct kvm @kvm. */
+  bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
+
+Typically a requester wants the VCPU to perform the activity as soon
+as possible after making the request.  This means most requests
+(kvm_make_request() calls) are followed by a call to kvm_vcpu_kick(),
+and kvm_make_all_cpus_request() has the kicking of all VCPUs built
+into it.
+
+VCPU Kicks
+----------
+
+The goal of a VCPU kick is to bring a VCPU thread out of guest mode in
+order to perform some KVM maintenance.  To do so, an IPI is sent, forcing
+a guest mode exit.  However, a VCPU thread may not be in guest mode at the
+time of the kick.  Therefore, depending on the mode and state of the VCPU
+thread, there are two other actions a kick may take.  All three actions
+are listed below:
+
+1) Send an IPI.  This forces a guest mode exit.
+2) Waking a sleeping VCPU.  Sleeping VCPUs are VCPU threads outside guest
+   mode that wait on waitqueues.  Waking them removes the threads from
+   the waitqueues, allowing the threads to run again.  This behavior
+   may be suppressed, see KVM_REQUEST_NO_WAKEUP below.
+3) Nothing.  When the VCPU is not in guest mode and the VCPU thread is not
+   sleeping, then there is nothing to do.
+
+VCPU Mode
+---------
+
+VCPUs have a mode state, ``vcpu->mode``, that is used to track whether the
+guest is running in guest mode or not, as well as some specific
+outside guest mode states.  The architecture may use ``vcpu->mode`` to
+ensure VCPU requests are seen by VCPUs (see "Ensuring Requests Are Seen"),
+as well as to avoid sending unnecessary IPIs (see "IPI Reduction"), and
+even to ensure IPI acknowledgements are waited upon (see "Waiting for
+Acknowledgements").  The following modes are defined:
+
+OUTSIDE_GUEST_MODE
+
+  The VCPU thread is outside guest mode.
+
+IN_GUEST_MODE
+
+  The VCPU thread is in guest mode.
+
+EXITING_GUEST_MODE
+
+  The VCPU thread is transitioning from IN_GUEST_MODE to
+  OUTSIDE_GUEST_MODE.
+
+READING_SHADOW_PAGE_TABLES
+
+  The VCPU thread is outside guest mode, but it wants the sender of
+  certain VCPU requests, namely KVM_REQ_TLB_FLUSH, to wait until the VCPU
+  thread is done reading the page tables.
+
+VCPU Request Internals
+======================
+
+VCPU requests are simply bit indices of the ``vcpu->requests`` bitmap.
+This means general bitops, like those documented in [atomic-ops]_ could
+also be used, e.g. ::
+
+  clear_bit(KVM_REQ_UNHALT & KVM_REQUEST_MASK, &vcpu->requests);
+
+However, VCPU request users should refrain from doing so, as it would
+break the abstraction.  The first 8 bits are reserved for architecture
+independent requests, all additional bits are available for architecture
+dependent requests.
+
+Architecture Independent Requests
+---------------------------------
+
+KVM_REQ_TLB_FLUSH
+
+  KVM's common MMU notifier may need to flush all of a guest's TLB
+  entries, calling kvm_flush_remote_tlbs() to do so.  Architectures that
+  choose to use the common kvm_flush_remote_tlbs() implementation will
+  need to handle this VCPU request.
+
+KVM_REQ_MMU_RELOAD
+
+  When shadow page tables are used and memory slots are removed it's
+  necessary to inform each VCPU to completely refresh the tables.  This
+  request is used for that.
+
+KVM_REQ_PENDING_TIMER
+
+  This request may be made from a timer handler run on the host on behalf
+  of a VCPU.  It informs the VCPU thread to inject a timer interrupt.
+
+KVM_REQ_UNHALT
+
+  This request may be made from the KVM common function kvm_vcpu_block(),
+  which is used to emulate an instruction that causes a CPU to halt until
+  one of an architectural specific set of events and/or interrupts is
+  received (determined by checking kvm_arch_vcpu_runnable()).  When that
+  event or interrupt arrives kvm_vcpu_block() makes the request.  This is
+  in contrast to when kvm_vcpu_block() returns due to any other reason,
+  such as a pending signal, which does not indicate the VCPU's halt
+  emulation should stop, and therefore does not make the request.
+
+KVM_REQUEST_MASK
+----------------
+
+VCPU requests should be masked by KVM_REQUEST_MASK before using them with
+bitops.  This is because only the lower 8 bits are used to represent the
+request's number.  The upper bits are used as flags.  Currently only two
+flags are defined.
+
+VCPU Request Flags
+------------------
+
+KVM_REQUEST_NO_WAKEUP
+
+  This flag is applied to requests that only need immediate attention
+  from VCPUs running in guest mode.  That is, sleeping VCPUs do not need
+  to be awaken for these requests.  Sleeping VCPUs will handle the
+  requests when they are awaken later for some other reason.
+
+KVM_REQUEST_WAIT
+
+  When requests with this flag are made with kvm_make_all_cpus_request(),
+  then the caller will wait for each VCPU to acknowledge its IPI before
+  proceeding.  This flag only applies to VCPUs that would receive IPIs.
+  If, for example, the VCPU is sleeping, so no IPI is necessary, then
+  the requesting thread does not wait.  This means that this flag may be
+  safely combined with KVM_REQUEST_NO_WAKEUP.  See "Waiting for
+  Acknowledgements" for more information about requests with
+  KVM_REQUEST_WAIT.
+
+VCPU Requests with Associated State
+===================================
+
+Requesters that want the receiving VCPU to handle new state need to ensure
+the newly written state is observable to the receiving VCPU thread's CPU
+by the time it observes the request.  This means a write memory barrier
+must be inserted after writing the new state and before setting the VCPU
+request bit.  Additionally, on the receiving VCPU thread's side, a
+corresponding read barrier must be inserted after reading the request bit
+and before proceeding to read the new state associated with it.  See
+scenario 3, Message and Flag, of [lwn-mb]_ and the kernel documentation
+[memory-barriers]_.
+
+The pair of functions, kvm_check_request() and kvm_make_request(), provide
+the memory barriers, allowing this requirement to be handled internally by
+the API.
+
+Ensuring Requests Are Seen
+==========================
+
+When making requests to VCPUs, we want to avoid the receiving VCPU
+executing in guest mode for an arbitrary long time without handling the
+request.  We can be sure this won't happen as long as we ensure the VCPU
+thread checks kvm_request_pending() before entering guest mode and that a
+kick will send an IPI to force an exit from guest mode when necessary.
+Extra care must be taken to cover the period after the VCPU thread's last
+kvm_request_pending() check and before it has entered guest mode, as kick
+IPIs will only trigger guest mode exits for VCPU threads that are in guest
+mode or at least have already disabled interrupts in order to prepare to
+enter guest mode.  This means that an optimized implementation (see "IPI
+Reduction") must be certain when it's safe to not send the IPI.  One
+solution, which all architectures except s390 apply, is to:
+
+- set ``vcpu->mode`` to IN_GUEST_MODE between disabling the interrupts and
+  the last kvm_request_pending() check;
+- enable interrupts atomically when entering the guest.
+
+This solution also requires memory barriers to be placed carefully in both
+the requesting thread and the receiving VCPU.  With the memory barriers we
+can exclude the possibility of a VCPU thread observing
+!kvm_request_pending() on its last check and then not receiving an IPI for
+the next request made of it, even if the request is made immediately after
+the check.  This is done by way of the Dekker memory barrier pattern
+(scenario 10 of [lwn-mb]_).  As the Dekker pattern requires two variables,
+this solution pairs ``vcpu->mode`` with ``vcpu->requests``.  Substituting
+them into the pattern gives::
+
+  CPU1                                    CPU2
+  =================                       =================
+  local_irq_disable();
+  WRITE_ONCE(vcpu->mode, IN_GUEST_MODE);  kvm_make_request(REQ, vcpu);
+  smp_mb();                               smp_mb();
+  if (kvm_request_pending(vcpu)) {        if (READ_ONCE(vcpu->mode) ==
+                                              IN_GUEST_MODE) {
+      ...abort guest entry...                 ...send IPI...
+  }                                       }
+
+As stated above, the IPI is only useful for VCPU threads in guest mode or
+that have already disabled interrupts.  This is why this specific case of
+the Dekker pattern has been extended to disable interrupts before setting
+``vcpu->mode`` to IN_GUEST_MODE.  WRITE_ONCE() and READ_ONCE() are used to
+pedantically implement the memory barrier pattern, guaranteeing the
+compiler doesn't interfere with ``vcpu->mode``'s carefully planned
+accesses.
+
+IPI Reduction
+-------------
+
+As only one IPI is needed to get a VCPU to check for any/all requests,
+then they may be coalesced.  This is easily done by having the first IPI
+sending kick also change the VCPU mode to something !IN_GUEST_MODE.  The
+transitional state, EXITING_GUEST_MODE, is used for this purpose.
+
+Waiting for Acknowledgements
+----------------------------
+
+Some requests, those with the KVM_REQUEST_WAIT flag set, require IPIs to
+be sent, and the acknowledgements to be waited upon, even when the target
+VCPU threads are in modes other than IN_GUEST_MODE.  For example, one case
+is when a target VCPU thread is in READING_SHADOW_PAGE_TABLES mode, which
+is set after disabling interrupts.  To support these cases, the
+KVM_REQUEST_WAIT flag changes the condition for sending an IPI from
+checking that the VCPU is IN_GUEST_MODE to checking that it is not
+OUTSIDE_GUEST_MODE.
+
+Request-less VCPU Kicks
+-----------------------
+
+As the determination of whether or not to send an IPI depends on the
+two-variable Dekker memory barrier pattern, then it's clear that
+request-less VCPU kicks are almost never correct.  Without the assurance
+that a non-IPI generating kick will still result in an action by the
+receiving VCPU, as the final kvm_request_pending() check does for
+request-accompanying kicks, then the kick may not do anything useful at
+all.  If, for instance, a request-less kick was made to a VCPU that was
+just about to set its mode to IN_GUEST_MODE, meaning no IPI is sent, then
+the VCPU thread may continue its entry without actually having done
+whatever it was the kick was meant to initiate.
+
+One exception is x86's posted interrupt mechanism.  In this case, however,
+even the request-less VCPU kick is coupled with the same
+local_irq_disable() + smp_mb() pattern described above; the ON bit
+(Outstanding Notification) in the posted interrupt descriptor takes the
+role of ``vcpu->requests``.  When sending a posted interrupt, PIR.ON is
+set before reading ``vcpu->mode``; dually, in the VCPU thread,
+vmx_sync_pir_to_irr() reads PIR after setting ``vcpu->mode`` to
+IN_GUEST_MODE.
+
+Additional Considerations
+=========================
+
+Sleeping VCPUs
+--------------
+
+VCPU threads may need to consider requests before and/or after calling
+functions that may put them to sleep, e.g. kvm_vcpu_block().  Whether they
+do or not, and, if they do, which requests need consideration, is
+architecture dependent.  kvm_vcpu_block() calls kvm_arch_vcpu_runnable()
+to check if it should awaken.  One reason to do so is to provide
+architectures a function where requests may be checked if necessary.
+
+Clearing Requests
+-----------------
+
+Generally it only makes sense for the receiving VCPU thread to clear a
+request.  However, in some circumstances, such as when the requesting
+thread and the receiving VCPU thread are executed serially, such as when
+they are the same thread, or when they are using some form of concurrency
+control to temporarily execute synchronously, then it's possible to know
+that the request may be cleared immediately, rather than waiting for the
+receiving VCPU thread to handle the request in VCPU RUN.  The only current
+examples of this are kvm_vcpu_block() calls made by VCPUs to block
+themselves.  A possible side-effect of that call is to make the
+KVM_REQ_UNHALT request, which may then be cleared immediately when the
+VCPU returns from the call.
+
+References
+==========
+
+.. [atomic-ops] Documentation/core-api/atomic_ops.rst
+.. [memory-barriers] Documentation/memory-barriers.txt
+.. [lwn-mb] https://lwn.net/Articles/573436/
diff --git a/Documentation/virt/paravirt_ops.rst b/Documentation/virt/paravirt_ops.rst
new file mode 100644 (file)
index 0000000..6b789d2
--- /dev/null
@@ -0,0 +1,35 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+Paravirt_ops
+============
+
+Linux provides support for different hypervisor virtualization technologies.
+Historically different binary kernels would be required in order to support
+different hypervisors, this restriction was removed with pv_ops.
+Linux pv_ops is a virtualization API which enables support for different
+hypervisors. It allows each hypervisor to override critical operations and
+allows a single kernel binary to run on all supported execution environments
+including native machine -- without any hypervisors.
+
+pv_ops provides a set of function pointers which represent operations
+corresponding to low level critical instructions and high level
+functionalities in various areas. pv-ops allows for optimizations at run
+time by enabling binary patching of the low-ops critical operations
+at boot time.
+
+pv_ops operations are classified into three categories:
+
+- simple indirect call
+   These operations correspond to high level functionality where it is
+   known that the overhead of indirect call isn't very important.
+
+- indirect call which allows optimization with binary patch
+   Usually these operations correspond to low level critical instructions. They
+   are called frequently and are performance critical. The overhead is
+   very important.
+
+- a set of macros for hand written assembly code
+   Hand written assembly codes (.S files) also need paravirtualization
+   because they include sensitive instructions or some of code paths in
+   them are very performance critical.
diff --git a/Documentation/virt/uml/UserModeLinux-HOWTO.txt b/Documentation/virt/uml/UserModeLinux-HOWTO.txt
new file mode 100644 (file)
index 0000000..87b80f5
--- /dev/null
@@ -0,0 +1,4589 @@
+  User Mode Linux HOWTO
+  User Mode Linux Core Team
+  Mon Nov 18 14:16:16 EST 2002
+
+  This document describes the use and abuse of Jeff Dike's User Mode
+  Linux: a port of the Linux kernel as a normal Intel Linux process.
+  ______________________________________________________________________
+
+  Table of Contents
+
+  1. Introduction
+
+     1.1 How is User Mode Linux Different?
+     1.2 Why Would I Want User Mode Linux?
+
+  2. Compiling the kernel and modules
+
+     2.1 Compiling the kernel
+     2.2 Compiling and installing kernel modules
+     2.3 Compiling and installing uml_utilities
+
+  3. Running UML and logging in
+
+     3.1 Running UML
+     3.2 Logging in
+     3.3 Examples
+
+  4. UML on 2G/2G hosts
+
+     4.1 Introduction
+     4.2 The problem
+     4.3 The solution
+
+  5. Setting up serial lines and consoles
+
+     5.1 Specifying the device
+     5.2 Specifying the channel
+     5.3 Examples
+
+  6. Setting up the network
+
+     6.1 General setup
+     6.2 Userspace daemons
+     6.3 Specifying ethernet addresses
+     6.4 UML interface setup
+     6.5 Multicast
+     6.6 TUN/TAP with the uml_net helper
+     6.7 TUN/TAP with a preconfigured tap device
+     6.8 Ethertap
+     6.9 The switch daemon
+     6.10 Slip
+     6.11 Slirp
+     6.12 pcap
+     6.13 Setting up the host yourself
+
+  7. Sharing Filesystems between Virtual Machines
+
+     7.1 A warning
+     7.2 Using layered block devices
+     7.3 Note!
+     7.4 Another warning
+     7.5 uml_moo : Merging a COW file with its backing file
+
+  8. Creating filesystems
+
+     8.1 Create the filesystem file
+     8.2 Assign the file to a UML device
+     8.3 Creating and mounting the filesystem
+
+  9. Host file access
+
+     9.1 Using hostfs
+     9.2 hostfs as the root filesystem
+     9.3 Building hostfs
+
+  10. The Management Console
+     10.1 version
+     10.2 halt and reboot
+     10.3 config
+     10.4 remove
+     10.5 sysrq
+     10.6 help
+     10.7 cad
+     10.8 stop
+     10.9 go
+
+  11. Kernel debugging
+
+     11.1 Starting the kernel under gdb
+     11.2 Examining sleeping processes
+     11.3 Running ddd on UML
+     11.4 Debugging modules
+     11.5 Attaching gdb to the kernel
+     11.6 Using alternate debuggers
+
+  12. Kernel debugging examples
+
+     12.1 The case of the hung fsck
+     12.2 Episode 2: The case of the hung fsck
+
+  13. What to do when UML doesn't work
+
+     13.1 Strange compilation errors when you build from source
+     13.2 (obsolete)
+     13.3 A variety of panics and hangs with /tmp on a reiserfs  filesystem
+     13.4 The compile fails with errors about conflicting types for 'open', 'dup', and 'waitpid'
+     13.5 UML doesn't work when /tmp is an NFS filesystem
+     13.6 UML hangs on boot when compiled with gprof support
+     13.7 syslogd dies with a SIGTERM on startup
+     13.8 TUN/TAP networking doesn't work on a 2.4 host
+     13.9 You can network to the host but not to other machines on the net
+     13.10 I have no root and I want to scream
+     13.11 UML build conflict between ptrace.h and ucontext.h
+     13.12 The UML BogoMips is exactly half the host's BogoMips
+     13.13 When you run UML, it immediately segfaults
+     13.14 xterms appear, then immediately disappear
+     13.15 Any other panic, hang, or strange behavior
+
+  14. Diagnosing Problems
+
+     14.1 Case 1 : Normal kernel panics
+     14.2 Case 2 : Tracing thread panics
+     14.3 Case 3 : Tracing thread panics caused by other threads
+     14.4 Case 4 : Hangs
+
+  15. Thanks
+
+     15.1 Code and Documentation
+     15.2 Flushing out bugs
+     15.3 Buglets and clean-ups
+     15.4 Case Studies
+     15.5 Other contributions
+
+
+  ______________________________________________________________________
+
+  1.  Introduction
+
+  Welcome to User Mode Linux.  It's going to be fun.
+
+
+
+  1.1.  How is User Mode Linux Different?
+
+  Normally, the Linux Kernel talks straight to your hardware (video
+  card, keyboard, hard drives, etc), and any programs which run ask the
+  kernel to operate the hardware, like so:
+
+
+
+         +-----------+-----------+----+
+         | Process 1 | Process 2 | ...|
+         +-----------+-----------+----+
+         |       Linux Kernel         |
+         +----------------------------+
+         |         Hardware           |
+         +----------------------------+
+
+
+
+
+  The User Mode Linux Kernel is different; instead of talking to the
+  hardware, it talks to a `real' Linux kernel (called the `host kernel'
+  from now on), like any other program.  Programs can then run inside
+  User-Mode Linux as if they were running under a normal kernel, like
+  so:
+
+
+
+                     +----------------+
+                     | Process 2 | ...|
+         +-----------+----------------+
+         | Process 1 | User-Mode Linux|
+         +----------------------------+
+         |       Linux Kernel         |
+         +----------------------------+
+         |         Hardware           |
+         +----------------------------+
+
+
+
+
+
+  1.2.  Why Would I Want User Mode Linux?
+
+
+  1. If User Mode Linux crashes, your host kernel is still fine.
+
+  2. You can run a usermode kernel as a non-root user.
+
+  3. You can debug the User Mode Linux like any normal process.
+
+  4. You can run gprof (profiling) and gcov (coverage testing).
+
+  5. You can play with your kernel without breaking things.
+
+  6. You can use it as a sandbox for testing new apps.
+
+  7. You can try new development kernels safely.
+
+  8. You can run different distributions simultaneously.
+
+  9. It's extremely fun.
+
+
+
+
+
+  2.  Compiling the kernel and modules
+
+
+
+
+  2.1.  Compiling the kernel
+
+
+  Compiling the user mode kernel is just like compiling any other
+  kernel.  Let's go through the steps, using 2.4.0-prerelease (current
+  as of this writing) as an example:
+
+
+  1. Download the latest UML patch from
+
+     the download page <http://user-mode-linux.sourceforge.net/
+
+     In this example, the file is uml-patch-2.4.0-prerelease.bz2.
+
+
+  2. Download the matching kernel from your favourite kernel mirror,
+     such as:
+
+     ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2
+     <ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2>
+     .
+
+
+  3. Make a directory and unpack the kernel into it.
+
+
+
+       host%
+       mkdir ~/uml
+
+
+
+
+
+
+       host%
+       cd ~/uml
+
+
+
+
+
+
+       host%
+       tar -xzvf linux-2.4.0-prerelease.tar.bz2
+
+
+
+
+
+
+  4. Apply the patch using
+
+
+
+       host%
+       cd ~/uml/linux
+
+
+
+       host%
+       bzcat uml-patch-2.4.0-prerelease.bz2 | patch -p1
+
+
+
+
+
+
+  5. Run your favorite config; `make xconfig ARCH=um' is the most
+     convenient.  `make config ARCH=um' and 'make menuconfig ARCH=um'
+     will work as well.  The defaults will give you a useful kernel.  If
+     you want to change something, go ahead, it probably won't hurt
+     anything.
+
+
+     Note:  If the host is configured with a 2G/2G address space split
+     rather than the usual 3G/1G split, then the packaged UML binaries
+     will not run.  They will immediately segfault.  See ``UML on 2G/2G
+     hosts''  for the scoop on running UML on your system.
+
+
+
+  6. Finish with `make linux ARCH=um': the result is a file called
+     `linux' in the top directory of your source tree.
+
+  Make sure that you don't build this kernel in /usr/src/linux.  On some
+  distributions, /usr/include/asm is a link into this pool.  The user-
+  mode build changes the other end of that link, and things that include
+  <asm/anything.h> stop compiling.
+
+  The sources are also available from cvs at the project's cvs page,
+  which has directions on getting the sources. You can also browse the
+  CVS pool from there.
+
+  If you get the CVS sources, you will have to check them out into an
+  empty directory. You will then have to copy each file into the
+  corresponding directory in the appropriate kernel pool.
+
+  If you don't have the latest kernel pool, you can get the
+  corresponding user-mode sources with
+
+
+       host% cvs co -r v_2_3_x linux
+
+
+
+
+  where 'x' is the version in your pool. Note that you will not get the
+  bug fixes and enhancements that have gone into subsequent releases.
+
+
+  2.2.  Compiling and installing kernel modules
+
+  UML modules are built in the same way as the native kernel (with the
+  exception of the 'ARCH=um' that you always need for UML):
+
+
+       host% make modules ARCH=um
+
+
+
+
+  Any modules that you want to load into this kernel need to be built in
+  the user-mode pool.  Modules from the native kernel won't work.
+
+  You can install them by using ftp or something to copy them into the
+  virtual machine and dropping them into /lib/modules/`uname -r`.
+
+  You can also get the kernel build process to install them as follows:
+
+  1. with the kernel not booted, mount the root filesystem in the top
+     level of the kernel pool:
+
+
+       host% mount root_fs mnt -o loop
+
+
+
+
+
+
+  2. run
+
+
+       host%
+       make modules_install INSTALL_MOD_PATH=`pwd`/mnt ARCH=um
+
+
+
+
+
+
+  3. unmount the filesystem
+
+
+       host% umount mnt
+
+
+
+
+
+
+  4. boot the kernel on it
+
+
+  When the system is booted, you can use insmod as usual to get the
+  modules into the kernel.  A number of things have been loaded into UML
+  as modules, especially filesystems and network protocols and filters,
+  so most symbols which need to be exported probably already are.
+  However, if you do find symbols that need exporting, let  us
+  <http://user-mode-linux.sourceforge.net/>  know, and
+  they'll be "taken care of".
+
+
+
+  2.3.  Compiling and installing uml_utilities
+
+  Many features of the UML kernel require a user-space helper program,
+  so a uml_utilities package is distributed separately from the kernel
+  patch which provides these helpers. Included within this is:
+
+  o  port-helper - Used by consoles which connect to xterms or ports
+
+  o  tunctl - Configuration tool to create and delete tap devices
+
+  o  uml_net - Setuid binary for automatic tap device configuration
+
+  o  uml_switch - User-space virtual switch required for daemon
+     transport
+
+     The uml_utilities tree is compiled with:
+
+
+       host#
+       make && make install
+
+
+
+
+  Note that UML kernel patches may require a specific version of the
+  uml_utilities distribution. If you don't keep up with the mailing
+  lists, ensure that you have the latest release of uml_utilities if you
+  are experiencing problems with your UML kernel, particularly when
+  dealing with consoles or command-line switches to the helper programs
+
+
+
+
+
+
+
+
+  3.  Running UML and logging in
+
+
+
+  3.1.  Running UML
+
+  It runs on 2.2.15 or later, and all 2.4 kernels.
+
+
+  Booting UML is straightforward.  Simply run 'linux': it will try to
+  mount the file `root_fs' in the current directory.  You do not need to
+  run it as root.  If your root filesystem is not named `root_fs', then
+  you need to put a `ubd0=root_fs_whatever' switch on the linux command
+  line.
+
+
+  You will need a filesystem to boot UML from.  There are a number
+  available for download from  here  <http://user-mode-
+  linux.sourceforge.net/> .  There are also  several tools
+  <http://user-mode-linux.sourceforge.net/>  which can be
+  used to generate UML-compatible filesystem images from media.
+  The kernel will boot up and present you with a login prompt.
+
+
+  Note:  If the host is configured with a 2G/2G address space split
+  rather than the usual 3G/1G split, then the packaged UML binaries will
+  not run.  They will immediately segfault.  See ``UML on 2G/2G hosts''
+  for the scoop on running UML on your system.
+
+
+
+  3.2.  Logging in
+
+
+
+  The prepackaged filesystems have a root account with password 'root'
+  and a user account with password 'user'.  The login banner will
+  generally tell you how to log in.  So, you log in and you will find
+  yourself inside a little virtual machine. Our filesystems have a
+  variety of commands and utilities installed (and it is fairly easy to
+  add more), so you will have a lot of tools with which to poke around
+  the system.
+
+  There are a couple of other ways to log in:
+
+  o  On a virtual console
+
+
+
+     Each virtual console that is configured (i.e. the device exists in
+     /dev and /etc/inittab runs a getty on it) will come up in its own
+     xterm.  If you get tired of the xterms, read ``Setting up serial
+     lines and consoles''  to see how to attach the consoles to
+     something else, like host ptys.
+
+
+
+  o  Over the serial line
+
+
+     In the boot output, find a line that looks like:
+
+
+
+       serial line 0 assigned pty /dev/ptyp1
+
+
+
+
+  Attach your favorite terminal program to the corresponding tty.  I.e.
+  for minicom, the command would be
+
+
+       host% minicom -o -p /dev/ttyp1
+
+
+
+
+
+
+  o  Over the net
+
+
+     If the network is running, then you can telnet to the virtual
+     machine and log in to it.  See ``Setting up the network''  to learn
+     about setting up a virtual network.
+
+  When you're done using it, run halt, and the kernel will bring itself
+  down and the process will exit.
+
+
+  3.3.  Examples
+
+  Here are some examples of UML in action:
+
+  o  A login session <http://user-mode-linux.sourceforge.net/login.html>
+
+  o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
+
+
+
+
+
+
+
+  4.  UML on 2G/2G hosts
+
+
+
+
+  4.1.  Introduction
+
+
+  Most Linux machines are configured so that the kernel occupies the
+  upper 1G (0xc0000000 - 0xffffffff) of the 4G address space and
+  processes use the lower 3G (0x00000000 - 0xbfffffff).  However, some
+  machine are configured with a 2G/2G split, with the kernel occupying
+  the upper 2G (0x80000000 - 0xffffffff) and processes using the lower
+  2G (0x00000000 - 0x7fffffff).
+
+
+
+
+  4.2.  The problem
+
+
+  The prebuilt UML binaries on this site will not run on 2G/2G hosts
+  because UML occupies the upper .5G of the 3G process address space
+  (0xa0000000 - 0xbfffffff).  Obviously, on 2G/2G hosts, this is right
+  in the middle of the kernel address space, so UML won't even load - it
+  will immediately segfault.
+
+
+
+
+  4.3.  The solution
+
+
+  The fix for this is to rebuild UML from source after enabling
+  CONFIG_HOST_2G_2G (under 'General Setup').  This will cause UML to
+  load itself in the top .5G of that smaller process address space,
+  where it will run fine.  See ``Compiling the kernel and modules''  if
+  you need help building UML from source.
+
+
+
+
+
+
+
+
+
+
+  5.  Setting up serial lines and consoles
+
+
+  It is possible to attach UML serial lines and consoles to many types
+  of host I/O channels by specifying them on the command line.
+
+
+  You can attach them to host ptys, ttys, file descriptors, and ports.
+  This allows you to do things like
+
+  o  have a UML console appear on an unused host console,
+
+  o  hook two virtual machines together by having one attach to a pty
+     and having the other attach to the corresponding tty
+
+  o  make a virtual machine accessible from the net by attaching a
+     console to a port on the host.
+
+
+  The general format of the command line option is device=channel.
+
+
+
+  5.1.  Specifying the device
+
+  Devices are specified with "con" or "ssl" (console or serial line,
+  respectively), optionally with a device number if you are talking
+  about a specific device.
+
+
+  Using just "con" or "ssl" describes all of the consoles or serial
+  lines.  If you want to talk about console #3 or serial line #10, they
+  would be "con3" and "ssl10", respectively.
+
+
+  A specific device name will override a less general "con=" or "ssl=".
+  So, for example, you can assign a pty to each of the serial lines
+  except for the first two like this:
+
+
+        ssl=pty ssl0=tty:/dev/tty0 ssl1=tty:/dev/tty1
+
+
+
+
+  The specificity of the device name is all that matters; order on the
+  command line is irrelevant.
+
+
+
+  5.2.  Specifying the channel
+
+  There are a number of different types of channels to attach a UML
+  device to, each with a different way of specifying exactly what to
+  attach to.
+
+  o  pseudo-terminals - device=pty pts terminals - device=pts
+
+
+     This will cause UML to allocate a free host pseudo-terminal for the
+     device.  The terminal that it got will be announced in the boot
+     log.  You access it by attaching a terminal program to the
+     corresponding tty:
+
+  o  screen /dev/pts/n
+
+  o  screen /dev/ttyxx
+
+  o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
+     devices
+
+  o  kermit - start it up, 'open' the device, then 'connect'
+
+
+
+
+
+  o  terminals - device=tty:tty device file
+
+
+     This will make UML attach the device to the specified tty (i.e
+
+
+        con1=tty:/dev/tty3
+
+
+
+
+  will attach UML's console 1 to the host's /dev/tty3).  If the tty that
+  you specify is the slave end of a tty/pty pair, something else must
+  have already opened the corresponding pty in order for this to work.
+
+
+
+
+
+  o  xterms - device=xterm
+
+
+     UML will run an xterm and the device will be attached to it.
+
+
+
+
+
+  o  Port - device=port:port number
+
+
+     This will attach the UML devices to the specified host port.
+     Attaching console 1 to the host's port 9000 would be done like
+     this:
+
+
+        con1=port:9000
+
+
+
+
+  Attaching all the serial lines to that port would be done similarly:
+
+
+        ssl=port:9000
+
+
+
+
+  You access these devices by telnetting to that port.  Each active tel-
+  net session gets a different device.  If there are more telnets to a
+  port than UML devices attached to it, then the extra telnet sessions
+  will block until an existing telnet detaches, or until another device
+  becomes active (i.e. by being activated in /etc/inittab).
+
+  This channel has the advantage that you can both attach multiple UML
+  devices to it and know how to access them without reading the UML boot
+  log.  It is also unique in allowing access to a UML from remote
+  machines without requiring that the UML be networked.  This could be
+  useful in allowing public access to UMLs because they would be
+  accessible from the net, but wouldn't need any kind of network
+  filtering or access control because they would have no network access.
+
+
+  If you attach the main console to a portal, then the UML boot will
+  appear to hang.  In reality, it's waiting for a telnet to connect, at
+  which point the boot will proceed.
+
+
+
+
+
+  o  already-existing file descriptors - device=file descriptor
+
+
+     If you set up a file descriptor on the UML command line, you can
+     attach a UML device to it.  This is most commonly used to put the
+     main console back on stdin and stdout after assigning all the other
+     consoles to something else:
+
+
+        con0=fd:0,fd:1 con=pts
+
+
+
+
+
+
+
+
+  o  Nothing - device=null
+
+
+     This allows the device to be opened, in contrast to 'none', but
+     reads will block, and writes will succeed and the data will be
+     thrown out.
+
+
+
+
+
+  o  None - device=none
+
+
+     This causes the device to disappear.
+
+
+
+  You can also specify different input and output channels for a device
+  by putting a comma between them:
+
+
+        ssl3=tty:/dev/tty2,xterm
+
+
+
+
+  will cause serial line 3 to accept input on the host's /dev/tty2 and
+  display output on an xterm.  That's a silly example - the most common
+  use of this syntax is to reattach the main console to stdin and stdout
+  as shown above.
+
+
+  If you decide to move the main console away from stdin/stdout, the
+  initial boot output will appear in the terminal that you're running
+  UML in.  However, once the console driver has been officially
+  initialized, then the boot output will start appearing wherever you
+  specified that console 0 should be.  That device will receive all
+  subsequent output.
+
+
+
+  5.3.  Examples
+
+  There are a number of interesting things you can do with this
+  capability.
+
+
+  First, this is how you get rid of those bleeding console xterms by
+  attaching them to host ptys:
+
+
+        con=pty con0=fd:0,fd:1
+
+
+
+
+  This will make a UML console take over an unused host virtual console,
+  so that when you switch to it, you will see the UML login prompt
+  rather than the host login prompt:
+
+
+        con1=tty:/dev/tty6
+
+
+
+
+  You can attach two virtual machines together with what amounts to a
+  serial line as follows:
+
+  Run one UML with a serial line attached to a pty -
+
+
+        ssl1=pty
+
+
+
+
+  Look at the boot log to see what pty it got (this example will assume
+  that it got /dev/ptyp1).
+
+  Boot the other UML with a serial line attached to the corresponding
+  tty -
+
+
+        ssl1=tty:/dev/ttyp1
+
+
+
+
+  Log in, make sure that it has no getty on that serial line, attach a
+  terminal program like minicom to it, and you should see the login
+  prompt of the other virtual machine.
+
+
+  6.  Setting up the network
+
+
+
+  This page describes how to set up the various transports and to
+  provide a UML instance with network access to the host, other machines
+  on the local net, and the rest of the net.
+
+
+  As of 2.4.5, UML networking has been completely redone to make it much
+  easier to set up, fix bugs, and add new features.
+
+
+  There is a new helper, uml_net, which does the host setup that
+  requires root privileges.
+
+
+  There are currently five transport types available for a UML virtual
+  machine to exchange packets with other hosts:
+
+  o  ethertap
+
+  o  TUN/TAP
+
+  o  Multicast
+
+  o  a switch daemon
+
+  o  slip
+
+  o  slirp
+
+  o  pcap
+
+     The TUN/TAP, ethertap, slip, and slirp transports allow a UML
+     instance to exchange packets with the host.  They may be directed
+     to the host or the host may just act as a router to provide access
+     to other physical or virtual machines.
+
+
+  The pcap transport is a synthetic read-only interface, using the
+  libpcap binary to collect packets from interfaces on the host and
+  filter them.  This is useful for building preconfigured traffic
+  monitors or sniffers.
+
+
+  The daemon and multicast transports provide a completely virtual
+  network to other virtual machines.  This network is completely
+  disconnected from the physical network unless one of the virtual
+  machines on it is acting as a gateway.
+
+
+  With so many host transports, which one should you use?  Here's when
+  you should use each one:
+
+  o  ethertap - if you want access to the host networking and it is
+     running 2.2
+
+  o  TUN/TAP - if you want access to the host networking and it is
+     running 2.4.  Also, the TUN/TAP transport is able to use a
+     preconfigured device, allowing it to avoid using the setuid uml_net
+     helper, which is a security advantage.
+
+  o  Multicast - if you want a purely virtual network and you don't want
+     to set up anything but the UML
+
+  o  a switch daemon - if you want a purely virtual network and you
+     don't mind running the daemon in order to get somewhat better
+     performance
+
+  o  slip - there is no particular reason to run the slip backend unless
+     ethertap and TUN/TAP are just not available for some reason
+
+  o  slirp - if you don't have root access on the host to setup
+     networking, or if you don't want to allocate an IP to your UML
+
+  o  pcap - not much use for actual network connectivity, but great for
+     monitoring traffic on the host
+
+     Ethertap is available on 2.4 and works fine.  TUN/TAP is preferred
+     to it because it has better performance and ethertap is officially
+     considered obsolete in 2.4.  Also, the root helper only needs to
+     run occasionally for TUN/TAP, rather than handling every packet, as
+     it does with ethertap.  This is a slight security advantage since
+     it provides fewer opportunities for a nasty UML user to somehow
+     exploit the helper's root privileges.
+
+
+  6.1.  General setup
+
+  First, you must have the virtual network enabled in your UML.  If are
+  running a prebuilt kernel from this site, everything is already
+  enabled.  If you build the kernel yourself, under the "Network device
+  support" menu, enable "Network device support", and then the three
+  transports.
+
+
+  The next step is to provide a network device to the virtual machine.
+  This is done by describing it on the kernel command line.
+
+  The general format is
+
+
+       eth <n> = <transport> , <transport args>
+
+
+
+
+  For example, a virtual ethernet device may be attached to a host
+  ethertap device as follows:
+
+
+       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
+
+
+
+
+  This sets up eth0 inside the virtual machine to attach itself to the
+  host /dev/tap0, assigns it an ethernet address, and assigns the host
+  tap0 interface an IP address.
+
+
+
+  Note that the IP address you assign to the host end of the tap device
+  must be different than the IP you assign to the eth device inside UML.
+  If you are short on IPs and don't want to consume two per UML, then
+  you can reuse the host's eth IP address for the host ends of the tap
+  devices.  Internally, the UMLs must still get unique IPs for their eth
+  devices.  You can also give the UMLs non-routable IPs (192.168.x.x or
+  10.x.x.x) and have the host masquerade them.  This will let outgoing
+  connections work, but incoming connections won't without more work,
+  such as port forwarding from the host.
+  Also note that when you configure the host side of an interface, it is
+  only acting as a gateway.  It will respond to pings sent to it
+  locally, but is not useful to do that since it's a host interface.
+  You are not talking to the UML when you ping that interface and get a
+  response.
+
+
+  You can also add devices to a UML and remove them at runtime.  See the
+  ``The Management Console''  page for details.
+
+
+  The sections below describe this in more detail.
+
+
+  Once you've decided how you're going to set up the devices, you boot
+  UML, log in, configure the UML side of the devices, and set up routes
+  to the outside world.  At that point, you will be able to talk to any
+  other machines, physical or virtual, on the net.
+
+
+  If ifconfig inside UML fails and the network refuses to come up, run
+  tell you what went wrong.
+
+
+
+  6.2.  Userspace daemons
+
+  You will likely need the setuid helper, or the switch daemon, or both.
+  They are both installed with the RPM and deb, so if you've installed
+  either, you can skip the rest of this section.
+
+
+  If not, then you need to check them out of CVS, build them, and
+  install them.  The helper is uml_net, in CVS /tools/uml_net, and the
+  daemon is uml_switch, in CVS /tools/uml_router.  They are both built
+  with a plain 'make'.  Both need to be installed in a directory that's
+  in your path - /usr/bin is recommend.  On top of that, uml_net needs
+  to be setuid root.
+
+
+
+  6.3.  Specifying ethernet addresses
+
+  Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
+  allow you to specify hardware addresses for the virtual ethernet
+  devices.  This is generally not necessary.  If you don't have a
+  specific reason to do it, you probably shouldn't.  If one is not
+  specified on the command line, the driver will assign one based on the
+  device IP address.  It will provide the address fe:fd:nn:nn:nn:nn
+  where nn.nn.nn.nn is the device IP address.  This is nearly always
+  sufficient to guarantee a unique hardware address for the device.  A
+  couple of exceptions are:
+
+  o  Another set of virtual ethernet devices are on the same network and
+     they are assigned hardware addresses using a different scheme which
+     may conflict with the UML IP address-based scheme
+
+  o  You aren't going to use the device for IP networking, so you don't
+     assign the device an IP address
+
+     If you let the driver provide the hardware address, you should make
+     sure that the device IP address is known before the interface is
+     brought up.  So, inside UML, this will guarantee that:
+
+
+
+  UML#
+  ifconfig eth0 192.168.0.250 up
+
+
+
+
+  If you decide to assign the hardware address yourself, make sure that
+  the first byte of the address is even.  Addresses with an odd first
+  byte are broadcast addresses, which you don't want assigned to a
+  device.
+
+
+
+  6.4.  UML interface setup
+
+  Once the network devices have been described on the command line, you
+  should boot UML and log in.
+
+
+  The first thing to do is bring the interface up:
+
+
+       UML# ifconfig ethn ip-address up
+
+
+
+
+  You should be able to ping the host at this point.
+
+
+  To reach the rest of the world, you should set a default route to the
+  host:
+
+
+       UML# route add default gw host ip
+
+
+
+
+  Again, with host ip of 192.168.0.4:
+
+
+       UML# route add default gw 192.168.0.4
+
+
+
+
+  This page used to recommend setting a network route to your local net.
+  This is wrong, because it will cause UML to try to figure out hardware
+  addresses of the local machines by arping on the interface to the
+  host.  Since that interface is basically a single strand of ethernet
+  with two nodes on it (UML and the host) and arp requests don't cross
+  networks, they will fail to elicit any responses.  So, what you want
+  is for UML to just blindly throw all packets at the host and let it
+  figure out what to do with them, which is what leaving out the network
+  route and adding the default route does.
+
+
+  Note: If you can't communicate with other hosts on your physical
+  ethernet, it's probably because of a network route that's
+  automatically set up.  If you run 'route -n' and see a route that
+  looks like this:
+
+
+
+
+  Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
+  192.168.0.0     0.0.0.0         255.255.255.0   U     0      0      0   eth0
+
+
+
+
+  with a mask that's not 255.255.255.255, then replace it with a route
+  to your host:
+
+
+       UML#
+       route del -net 192.168.0.0 dev eth0 netmask 255.255.255.0
+
+
+
+
+
+
+       UML#
+       route add -host 192.168.0.4 dev eth0
+
+
+
+
+  This, plus the default route to the host, will allow UML to exchange
+  packets with any machine on your ethernet.
+
+
+
+  6.5.  Multicast
+
+  The simplest way to set up a virtual network between multiple UMLs is
+  to use the mcast transport.  This was written by Harald Welte and is
+  present in UML version 2.4.5-5um and later.  Your system must have
+  multicast enabled in the kernel and there must be a multicast-capable
+  network device on the host.  Normally, this is eth0, but if there is
+  no ethernet card on the host, then you will likely get strange error
+  messages when you bring the device up inside UML.
+
+
+  To use it, run two UMLs with
+
+
+        eth0=mcast
+
+
+
+
+  on their command lines.  Log in, configure the ethernet device in each
+  machine with different IP addresses:
+
+
+       UML1# ifconfig eth0 192.168.0.254
+
+
+
+
+
+
+       UML2# ifconfig eth0 192.168.0.253
+
+
+
+
+  and they should be able to talk to each other.
+
+  The full set of command line options for this transport are
+
+
+
+       ethn=mcast,ethernet address,multicast
+       address,multicast port,ttl
+
+
+
+
+  Harald's original README is here <http://user-mode-linux.source-
+  forge.net/>  and explains these in detail, as well as
+  some other issues.
+
+  There is also a related point-to-point only "ucast" transport.
+  This is useful when your network does not support multicast, and
+  all network connections are simple point to point links.
+
+  The full set of command line options for this transport are
+
+
+       ethn=ucast,ethernet address,remote address,listen port,remote port
+
+
+
+
+  6.6.  TUN/TAP with the uml_net helper
+
+  TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
+  host.  The TUN/TAP backend has been in UML since 2.4.9-3um.
+
+
+  The easiest way to get up and running is to let the setuid uml_net
+  helper do the host setup for you.  This involves insmod-ing the tun.o
+  module if necessary, configuring the device, and setting up IP
+  forwarding, routing, and proxy arp.  If you are new to UML networking,
+  do this first.  If you're concerned about the security implications of
+  the setuid helper, use it to get up and running, then read the next
+  section to see how to have UML use a preconfigured tap device, which
+  avoids the use of uml_net.
+
+
+  If you specify an IP address for the host side of the device, the
+  uml_net helper will do all necessary setup on the host - the only
+  requirement is that TUN/TAP be available, either built in to the host
+  kernel or as the tun.o module.
+
+  The format of the command line switch to attach a device to a TUN/TAP
+  device is
+
+
+       eth <n> =tuntap,,, <IP address>
+
+
+
+
+  For example, this argument will attach the UML's eth0 to the next
+  available tap device and assign an ethernet address to it based on its
+  IP address
+
+
+       eth0=tuntap,,,192.168.0.254
+
+
+
+
+
+
+  Note that the IP address that must be used for the eth device inside
+  UML is fixed by the routing and proxy arp that is set up on the
+  TUN/TAP device on the host.  You can use a different one, but it won't
+  work because reply packets won't reach the UML.  This is a feature.
+  It prevents a nasty UML user from doing things like setting the UML IP
+  to the same as the network's nameserver or mail server.
+
+
+  There are a couple potential problems with running the TUN/TAP
+  transport on a 2.4 host kernel
+
+  o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
+     kernel or use the ethertap transport.
+
+  o  With an upgraded kernel, TUN/TAP may fail with
+
+
+       File descriptor in bad state
+
+
+
+
+  This is due to a header mismatch between the upgraded kernel and the
+  kernel that was originally installed on the machine.  The fix is to
+  make sure that /usr/src/linux points to the headers for the running
+  kernel.
+
+  These were pointed out by Tim Robinson <timro at trkr dot net> in
+  <http://www.geocrawler.com/> name="this uml-
+  user post"> .
+
+
+
+  6.7.  TUN/TAP with a preconfigured tap device
+
+  If you prefer not to have UML use uml_net (which is somewhat
+  insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
+  beforehand.  The setup needs to be done as root, but once that's done,
+  there is no need for root assistance.  Setting up the device is done
+  as follows:
+
+  o  Create the device with tunctl (available from the UML utilities
+     tarball)
+
+
+
+
+       host#  tunctl -u uid
+
+
+
+
+  where uid is the user id or username that UML will be run as.  This
+  will tell you what device was created.
+
+  o  Configure the device IP (change IP addresses and device name to
+     suit)
+
+
+
+
+       host#  ifconfig tap0 192.168.0.254 up
+
+
+
+
+
+  o  Set up routing and arping if desired - this is my recipe, there are
+     other ways of doing the same thing
+
+
+       host#
+       bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
+
+       host#
+       route add -host 192.168.0.253 dev tap0
+
+
+
+
+
+
+       host#
+       bash -c 'echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp'
+
+
+
+
+
+
+       host#
+       arp -Ds 192.168.0.253 eth0 pub
+
+
+
+
+  Note that this must be done every time the host boots - this configu-
+  ration is not stored across host reboots.  So, it's probably a good
+  idea to stick it in an rc file.  An even better idea would be a little
+  utility which reads the information from a config file and sets up
+  devices at boot time.
+
+  o  Rather than using up two IPs and ARPing for one of them, you can
+     also provide direct access to your LAN by the UML by using a
+     bridge.
+
+
+       host#
+       brctl addbr br0
+
+
+
+
+
+
+       host#
+       ifconfig eth0 0.0.0.0 promisc up
+
+
+
+
+
+
+       host#
+       ifconfig tap0 0.0.0.0 promisc up
+
+
+
+
+
+
+       host#
+       ifconfig br0 192.168.0.1 netmask 255.255.255.0 up
+
+
+
+
+
+
+
+  host#
+  brctl stp br0 off
+
+
+
+
+
+
+       host#
+       brctl setfd br0 1
+
+
+
+
+
+
+       host#
+       brctl sethello br0 1
+
+
+
+
+
+
+       host#
+       brctl addif br0 eth0
+
+
+
+
+
+
+       host#
+       brctl addif br0 tap0
+
+
+
+
+  Note that 'br0' should be setup using ifconfig with the existing IP
+  address of eth0, as eth0 no longer has its own IP.
+
+  o
+
+
+     Also, the /dev/net/tun device must be writable by the user running
+     UML in order for the UML to use the device that's been configured
+     for it.  The simplest thing to do is
+
+
+       host#  chmod 666 /dev/net/tun
+
+
+
+
+  Making it world-writable looks bad, but it seems not to be
+  exploitable as a security hole.  However, it does allow anyone to cre-
+  ate useless tap devices (useless because they can't configure them),
+  which is a DOS attack.  A somewhat more secure alternative would to be
+  to create a group containing all the users who have preconfigured tap
+  devices and chgrp /dev/net/tun to that group with mode 664 or 660.
+
+
+  o  Once the device is set up, run UML with 'eth0=tuntap,device name'
+     (i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
+     mconsole config command).
+
+  o  Bring the eth device up in UML and you're in business.
+
+     If you don't want that tap device any more, you can make it non-
+     persistent with
+
+
+       host#  tunctl -d tap device
+
+
+
+
+  Finally, tunctl has a -b (for brief mode) switch which causes it to
+  output only the name of the tap device it created.  This makes it
+  suitable for capture by a script:
+
+
+       host#  TAP=`tunctl -u 1000 -b`
+
+
+
+
+
+
+  6.8.  Ethertap
+
+  Ethertap is the general mechanism on 2.2 for userspace processes to
+  exchange packets with the kernel.
+
+
+
+  To use this transport, you need to describe the virtual network device
+  on the UML command line.  The general format for this is
+
+
+       eth <n> =ethertap, <device> , <ethernet address> , <tap IP address>
+
+
+
+
+  So, the previous example
+
+
+       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
+
+
+
+
+  attaches the UML eth0 device to the host /dev/tap0, assigns it the
+  ethernet address fe:fd:0:0:0:1, and assigns the IP address
+  192.168.0.254 to the tap device.
+
+
+
+  The tap device is mandatory, but the others are optional.  If the
+  ethernet address is omitted, one will be assigned to it.
+
+
+  The presence of the tap IP address will cause the helper to run and do
+  whatever host setup is needed to allow the virtual machine to
+  communicate with the outside world.  If you're not sure you know what
+  you're doing, this is the way to go.
+
+
+  If it is absent, then you must configure the tap device and whatever
+  arping and routing you will need on the host.  However, even in this
+  case, the uml_net helper still needs to be in your path and it must be
+  setuid root if you're not running UML as root.  This is because the
+  tap device doesn't support SIGIO, which UML needs in order to use
+  something as a source of input.  So, the helper is used as a
+  convenient asynchronous IO thread.
+
+  If you're using the uml_net helper, you can ignore the following host
+  setup - uml_net will do it for you.  You just need to make sure you
+  have ethertap available, either built in to the host kernel or
+  available as a module.
+
+
+  If you want to set things up yourself, you need to make sure that the
+  appropriate /dev entry exists.  If it doesn't, become root and create
+  it as follows:
+
+
+       mknod /dev/tap <minor>  c 36  <minor>  + 16
+
+
+
+
+  For example, this is how to create /dev/tap0:
+
+
+       mknod /dev/tap0 c 36 0 + 16
+
+
+
+
+  You also need to make sure that the host kernel has ethertap support.
+  If ethertap is enabled as a module, you apparently need to insmod
+  ethertap once for each ethertap device you want to enable.  So,
+
+
+       host#
+       insmod ethertap
+
+
+
+
+  will give you the tap0 interface.  To get the tap1 interface, you need
+  to run
+
+
+       host#
+       insmod ethertap unit=1 -o ethertap1
+
+
+
+
+
+
+
+  6.9.  The switch daemon
+
+  Note: This is the daemon formerly known as uml_router, but which was
+  renamed so the network weenies of the world would stop growling at me.
+
+
+  The switch daemon, uml_switch, provides a mechanism for creating a
+  totally virtual network.  By default, it provides no connection to the
+  host network (but see -tap, below).
+
+
+  The first thing you need to do is run the daemon.  Running it with no
+  arguments will make it listen on a default pair of unix domain
+  sockets.
+
+
+  If you want it to listen on a different pair of sockets, use
+
+
+        -unix control socket data socket
+
+
+
+
+
+  If you want it to act as a hub rather than a switch, use
+
+
+        -hub
+
+
+
+
+
+  If you want the switch to be connected to host networking (allowing
+  the umls to get access to the outside world through the host), use
+
+
+        -tap tap0
+
+
+
+
+
+  Note that the tap device must be preconfigured (see "TUN/TAP with a
+  preconfigured tap device", above).  If you're using a different tap
+  device than tap0, specify that instead of tap0.
+
+
+  uml_switch can be backgrounded as follows
+
+
+       host%
+       uml_switch [ options ] < /dev/null > /dev/null
+
+
+
+
+  The reason it doesn't background by default is that it listens to
+  stdin for EOF.  When it sees that, it exits.
+
+
+  The general format of the kernel command line switch is
+
+
+
+       ethn=daemon,ethernet address,socket
+       type,control socket,data socket
+
+
+
+
+  You can leave off everything except the 'daemon'.  You only need to
+  specify the ethernet address if the one that will be assigned to it
+  isn't acceptable for some reason.  The rest of the arguments describe
+  how to communicate with the daemon.  You should only specify them if
+  you told the daemon to use different sockets than the default.  So, if
+  you ran the daemon with no arguments, running the UML on the same
+  machine with
+       eth0=daemon
+
+
+
+
+  will cause the eth0 driver to attach itself to the daemon correctly.
+
+
+
+  6.10.  Slip
+
+  Slip is another, less general, mechanism for a process to communicate
+  with the host networking.  In contrast to the ethertap interface,
+  which exchanges ethernet frames with the host and can be used to
+  transport any higher-level protocol, it can only be used to transport
+  IP.
+
+
+  The general format of the command line switch is
+
+
+
+       ethn=slip,slip IP
+
+
+
+
+  The slip IP argument is the IP address that will be assigned to the
+  host end of the slip device.  If it is specified, the helper will run
+  and will set up the host so that the virtual machine can reach it and
+  the rest of the network.
+
+
+  There are some oddities with this interface that you should be aware
+  of.  You should only specify one slip device on a given virtual
+  machine, and its name inside UML will be 'umn', not 'eth0' or whatever
+  you specified on the command line.  These problems will be fixed at
+  some point.
+
+
+
+  6.11.  Slirp
+
+  slirp uses an external program, usually /usr/bin/slirp, to provide IP
+  only networking connectivity through the host. This is similar to IP
+  masquerading with a firewall, although the translation is performed in
+  user-space, rather than by the kernel.  As slirp does not set up any
+  interfaces on the host, or changes routing, slirp does not require
+  root access or setuid binaries on the host.
+
+
+  The general format of the command line switch for slirp is:
+
+
+
+       ethn=slirp,ethernet address,slirp path
+
+
+
+
+  The ethernet address is optional, as UML will set up the interface
+  with an ethernet address based upon the initial IP address of the
+  interface.  The slirp path is generally /usr/bin/slirp, although it
+  will depend on distribution.
+
+
+  The slirp program can have a number of options passed to the command
+  line and we can't add them to the UML command line, as they will be
+  parsed incorrectly.  Instead, a wrapper shell script can be written or
+  the options inserted into the  /.slirprc file.  More information on
+  all of the slirp options can be found in its man pages.
+
+
+  The eth0 interface on UML should be set up with the IP 10.2.0.15,
+  although you can use anything as long as it is not used by a network
+  you will be connecting to. The default route on UML should be set to
+  use
+
+
+       UML#
+       route add default dev eth0
+
+
+
+
+  slirp provides a number of useful IP addresses which can be used by
+  UML, such as 10.0.2.3 which is an alias for the DNS server specified
+  in /etc/resolv.conf on the host or the IP given in the 'dns' option
+  for slirp.
+
+
+  Even with a baudrate setting higher than 115200, the slirp connection
+  is limited to 115200. If you need it to go faster, the slirp binary
+  needs to be compiled with FULL_BOLT defined in config.h.
+
+
+
+  6.12.  pcap
+
+  The pcap transport is attached to a UML ethernet device on the command
+  line or with uml_mconsole with the following syntax:
+
+
+
+       ethn=pcap,host interface,filter
+       expression,option1,option2
+
+
+
+
+  The expression and options are optional.
+
+
+  The interface is whatever network device on the host you want to
+  sniff.  The expression is a pcap filter expression, which is also what
+  tcpdump uses, so if you know how to specify tcpdump filters, you will
+  use the same expressions here.  The options are up to two of
+  'promisc', control whether pcap puts the host interface into
+  promiscuous mode. 'optimize' and 'nooptimize' control whether the pcap
+  expression optimizer is used.
+
+
+  Example:
+
+
+
+       eth0=pcap,eth0,tcp
+
+       eth1=pcap,eth0,!tcp
+
+
+
+  will cause the UML eth0 to emit all tcp packets on the host eth0 and
+  the UML eth1 to emit all non-tcp packets on the host eth0.
+
+
+
+  6.13.  Setting up the host yourself
+
+  If you don't specify an address for the host side of the ethertap or
+  slip device, UML won't do any setup on the host.  So this is what is
+  needed to get things working (the examples use a host-side IP of
+  192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
+  own network):
+
+  o  The device needs to be configured with its IP address.  Tap devices
+     are also configured with an mtu of 1484.  Slip devices are
+     configured with a point-to-point address pointing at the UML ip
+     address.
+
+
+       host#  ifconfig tap0 arp mtu 1484 192.168.0.251 up
+
+
+
+
+
+
+       host#
+       ifconfig sl0 192.168.0.251 pointopoint 192.168.0.250 up
+
+
+
+
+
+  o  If a tap device is being set up, a route is set to the UML IP.
+
+
+       UML# route add -host 192.168.0.250 gw 192.168.0.251
+
+
+
+
+
+  o  To allow other hosts on your network to see the virtual machine,
+     proxy arp is set up for it.
+
+
+       host#  arp -Ds 192.168.0.250 eth0 pub
+
+
+
+
+
+  o  Finally, the host is set up to route packets.
+
+
+       host#  echo 1 > /proc/sys/net/ipv4/ip_forward
+
+
+
+
+
+
+
+
+
+
+  7.  Sharing Filesystems between Virtual Machines
+
+
+
+
+  7.1.  A warning
+
+  Don't attempt to share filesystems simply by booting two UMLs from the
+  same file.  That's the same thing as booting two physical machines
+  from a shared disk.  It will result in filesystem corruption.
+
+
+
+  7.2.  Using layered block devices
+
+  The way to share a filesystem between two virtual machines is to use
+  the copy-on-write (COW) layering capability of the ubd block driver.
+  As of 2.4.6-2um, the driver supports layering a read-write private
+  device over a read-only shared device.  A machine's writes are stored
+  in the private device, while reads come from either device - the
+  private one if the requested block is valid in it, the shared one if
+  not.  Using this scheme, the majority of data which is unchanged is
+  shared between an arbitrary number of virtual machines, each of which
+  has a much smaller file containing the changes that it has made.  With
+  a large number of UMLs booting from a large root filesystem, this
+  leads to a huge disk space saving.  It will also help performance,
+  since the host will be able to cache the shared data using a much
+  smaller amount of memory, so UML disk requests will be served from the
+  host's memory rather than its disks.
+
+
+
+
+  To add a copy-on-write layer to an existing block device file, simply
+  add the name of the COW file to the appropriate ubd switch:
+
+
+        ubd0=root_fs_cow,root_fs_debian_22
+
+
+
+
+  where 'root_fs_cow' is the private COW file and 'root_fs_debian_22' is
+  the existing shared filesystem.  The COW file need not exist.  If it
+  doesn't, the driver will create and initialize it.  Once the COW file
+  has been initialized, it can be used on its own on the command line:
+
+
+        ubd0=root_fs_cow
+
+
+
+
+  The name of the backing file is stored in the COW file header, so it
+  would be redundant to continue specifying it on the command line.
+
+
+
+  7.3.  Note!
+
+  When checking the size of the COW file in order to see the gobs of
+  space that you're saving, make sure you use 'ls -ls' to see the actual
+  disk consumption rather than the length of the file.  The COW file is
+  sparse, so the length will be very different from the disk usage.
+  Here is a 'ls -l' of a COW file and backing file from one boot and
+  shutdown:
+       host% ls -l cow.debian debian2.2
+       -rw-r--r--    1 jdike    jdike    492504064 Aug  6 21:16 cow.debian
+       -rwxrw-rw-    1 jdike    jdike    537919488 Aug  6 20:42 debian2.2
+
+
+
+
+  Doesn't look like much saved space, does it?  Well, here's 'ls -ls':
+
+
+       host% ls -ls cow.debian debian2.2
+          880 -rw-r--r--    1 jdike    jdike    492504064 Aug  6 21:16 cow.debian
+       525832 -rwxrw-rw-    1 jdike    jdike    537919488 Aug  6 20:42 debian2.2
+
+
+
+
+  Now, you can see that the COW file has less than a meg of disk, rather
+  than 492 meg.
+
+
+
+  7.4.  Another warning
+
+  Once a filesystem is being used as a readonly backing file for a COW
+  file, do not boot directly from it or modify it in any way.  Doing so
+  will invalidate any COW files that are using it.  The mtime and size
+  of the backing file are stored in the COW file header at its creation,
+  and they must continue to match.  If they don't, the driver will
+  refuse to use the COW file.
+
+
+
+
+  If you attempt to evade this restriction by changing either the
+  backing file or the COW header by hand, you will get a corrupted
+  filesystem.
+
+
+
+
+  Among other things, this means that upgrading the distribution in a
+  backing file and expecting that all of the COW files using it will see
+  the upgrade will not work.
+
+
+
+
+  7.5.  uml_moo : Merging a COW file with its backing file
+
+  Depending on how you use UML and COW devices, it may be advisable to
+  merge the changes in the COW file into the backing file every once in
+  a while.
+
+
+
+
+  The utility that does this is uml_moo.  Its usage is
+
+
+       host% uml_moo COW file new backing file
+
+
+
+
+  There's no need to specify the backing file since that information is
+  already in the COW file header.  If you're paranoid, boot the new
+  merged file, and if you're happy with it, move it over the old backing
+  file.
+
+
+
+
+  uml_moo creates a new backing file by default as a safety measure.  It
+  also has a destructive merge option which will merge the COW file
+  directly into its current backing file.  This is really only usable
+  when the backing file only has one COW file associated with it.  If
+  there are multiple COWs associated with a backing file, a -d merge of
+  one of them will invalidate all of the others.  However, it is
+  convenient if you're short of disk space, and it should also be
+  noticeably faster than a non-destructive merge.
+
+
+
+
+  uml_moo is installed with the UML deb and RPM.  If you didn't install
+  UML from one of those packages, you can also get it from the UML
+  utilities <http://user-mode-linux.sourceforge.net/
+  utilities>  tar file in tools/moo.
+
+
+
+
+
+
+
+
+  8.  Creating filesystems
+
+
+  You may want to create and mount new UML filesystems, either because
+  your root filesystem isn't large enough or because you want to use a
+  filesystem other than ext2.
+
+
+  This was written on the occasion of reiserfs being included in the
+  2.4.1 kernel pool, and therefore the 2.4.1 UML, so the examples will
+  talk about reiserfs.  This information is generic, and the examples
+  should be easy to translate to the filesystem of your choice.
+
+
+  8.1.  Create the filesystem file
+
+  dd is your friend.  All you need to do is tell dd to create an empty
+  file of the appropriate size.  I usually make it sparse to save time
+  and to avoid allocating disk space until it's actually used.  For
+  example, the following command will create a sparse 100 meg file full
+  of zeroes.
+
+
+       host%
+       dd if=/dev/zero of=new_filesystem seek=100 count=1 bs=1M
+
+
+
+
+
+
+  8.2.  Assign the file to a UML device
+
+  Add an argument like the following to the UML command line:
+
+  ubd4=new_filesystem
+
+
+
+
+  making sure that you use an unassigned ubd device number.
+
+
+
+  8.3.  Creating and mounting the filesystem
+
+  Make sure that the filesystem is available, either by being built into
+  the kernel, or available as a module, then boot up UML and log in.  If
+  the root filesystem doesn't have the filesystem utilities (mkfs, fsck,
+  etc), then get them into UML by way of the net or hostfs.
+
+
+  Make the new filesystem on the device assigned to the new file:
+
+
+       host#  mkreiserfs /dev/ubd/4
+
+
+       <----------- MKREISERFSv2 ----------->
+
+       ReiserFS version 3.6.25
+       Block size 4096 bytes
+       Block count 25856
+       Used blocks 8212
+               Journal - 8192 blocks (18-8209), journal header is in block 8210
+               Bitmaps: 17
+               Root block 8211
+       Hash function "r5"
+       ATTENTION: ALL DATA WILL BE LOST ON '/dev/ubd/4'! (y/n)y
+       journal size 8192 (from 18)
+       Initializing journal - 0%....20%....40%....60%....80%....100%
+       Syncing..done.
+
+
+
+
+  Now, mount it:
+
+
+       UML#
+       mount /dev/ubd/4 /mnt
+
+
+
+
+  and you're in business.
+
+
+
+
+
+
+
+
+
+  9.  Host file access
+
+
+  If you want to access files on the host machine from inside UML, you
+  can treat it as a separate machine and either nfs mount directories
+  from the host or copy files into the virtual machine with scp or rcp.
+  However, since UML is running on the host, it can access those
+  files just like any other process and make them available inside the
+  virtual machine without needing to use the network.
+
+
+  This is now possible with the hostfs virtual filesystem.  With it, you
+  can mount a host directory into the UML filesystem and access the
+  files contained in it just as you would on the host.
+
+
+  9.1.  Using hostfs
+
+  To begin with, make sure that hostfs is available inside the virtual
+  machine with
+
+
+       UML# cat /proc/filesystems
+
+
+
+  .  hostfs should be listed.  If it's not, either rebuild the kernel
+  with hostfs configured into it or make sure that hostfs is built as a
+  module and available inside the virtual machine, and insmod it.
+
+
+  Now all you need to do is run mount:
+
+
+       UML# mount none /mnt/host -t hostfs
+
+
+
+
+  will mount the host's / on the virtual machine's /mnt/host.
+
+
+  If you don't want to mount the host root directory, then you can
+  specify a subdirectory to mount with the -o switch to mount:
+
+
+       UML# mount none /mnt/home -t hostfs -o /home
+
+
+
+
+  will mount the hosts's /home on the virtual machine's /mnt/home.
+
+
+
+  9.2.  hostfs as the root filesystem
+
+  It's possible to boot from a directory hierarchy on the host using
+  hostfs rather than using the standard filesystem in a file.
+
+  To start, you need that hierarchy.  The easiest way is to loop mount
+  an existing root_fs file:
+
+
+       host#  mount root_fs uml_root_dir -o loop
+
+
+
+
+  You need to change the filesystem type of / in etc/fstab to be
+  'hostfs', so that line looks like this:
+
+  /dev/ubd/0       /        hostfs      defaults          1   1
+
+
+
+
+  Then you need to chown to yourself all the files in that directory
+  that are owned by root.  This worked for me:
+
+
+       host#  find . -uid 0 -exec chown jdike {} \;
+
+
+
+
+  Next, make sure that your UML kernel has hostfs compiled in, not as a
+  module.  Then run UML with the boot device pointing at that directory:
+
+
+        ubd0=/path/to/uml/root/directory
+
+
+
+
+  UML should then boot as it does normally.
+
+
+  9.3.  Building hostfs
+
+  If you need to build hostfs because it's not in your kernel, you have
+  two choices:
+
+
+
+  o  Compiling hostfs into the kernel:
+
+
+     Reconfigure the kernel and set the 'Host filesystem' option under
+
+
+  o  Compiling hostfs as a module:
+
+
+     Reconfigure the kernel and set the 'Host filesystem' option under
+     be in arch/um/fs/hostfs/hostfs.o.  Install that in
+     /lib/modules/`uname -r`/fs in the virtual machine, boot it up, and
+
+
+       UML# insmod hostfs
+
+
+
+
+
+
+
+
+
+
+
+
+  10.  The Management Console
+
+
+
+  The UML management console is a low-level interface to the kernel,
+  somewhat like the i386 SysRq interface.  Since there is a full-blown
+  operating system under UML, there is much greater flexibility possible
+  than with the SysRq mechanism.
+
+
+  There are a number of things you can do with the mconsole interface:
+
+  o  get the kernel version
+
+  o  add and remove devices
+
+  o  halt or reboot the machine
+
+  o  Send SysRq commands
+
+  o  Pause and resume the UML
+
+
+  You need the mconsole client (uml_mconsole) which is present in CVS
+  (/tools/mconsole) in 2.4.5-9um and later, and will be in the RPM in
+  2.4.6.
+
+
+  You also need CONFIG_MCONSOLE (under 'General Setup') enabled in UML.
+  When you boot UML, you'll see a line like:
+
+
+       mconsole initialized on /home/jdike/.uml/umlNJ32yL/mconsole
+
+
+
+
+  If you specify a unique machine id one the UML command line, i.e.
+
+
+        umid=debian
+
+
+
+
+  you'll see this
+
+
+       mconsole initialized on /home/jdike/.uml/debian/mconsole
+
+
+
+
+  That file is the socket that uml_mconsole will use to communicate with
+  UML.  Run it with either the umid or the full path as its argument:
+
+
+       host% uml_mconsole debian
+
+
+
+
+  or
+
+
+       host% uml_mconsole /home/jdike/.uml/debian/mconsole
+
+
+
+
+  You'll get a prompt, at which you can run one of these commands:
+
+  o  version
+
+  o  halt
+
+  o  reboot
+
+  o  config
+
+  o  remove
+
+  o  sysrq
+
+  o  help
+
+  o  cad
+
+  o  stop
+
+  o  go
+
+
+  10.1.  version
+
+  This takes no arguments.  It prints the UML version.
+
+
+       (mconsole)  version
+       OK Linux usermode 2.4.5-9um #1 Wed Jun 20 22:47:08 EDT 2001 i686
+
+
+
+
+  There are a couple actual uses for this.  It's a simple no-op which
+  can be used to check that a UML is running.  It's also a way of
+  sending an interrupt to the UML.  This is sometimes useful on SMP
+  hosts, where there's a bug which causes signals to UML to be lost,
+  often causing it to appear to hang.  Sending such a UML the mconsole
+  version command is a good way to 'wake it up' before networking has
+  been enabled, as it does not do anything to the function of the UML.
+
+
+
+  10.2.  halt and reboot
+
+  These take no arguments.  They shut the machine down immediately, with
+  no syncing of disks and no clean shutdown of userspace.  So, they are
+  pretty close to crashing the machine.
+
+
+       (mconsole)  halt
+       OK
+
+
+
+
+
+
+  10.3.  config
+
+  "config" adds a new device to the virtual machine.  Currently the ubd
+  and network drivers support this.  It takes one argument, which is the
+  device to add, with the same syntax as the kernel command line.
+
+
+
+
+  (mconsole)
+  config ubd3=/home/jdike/incoming/roots/root_fs_debian22
+
+  OK
+  (mconsole)  config eth1=mcast
+  OK
+
+
+
+
+
+
+  10.4.  remove
+
+  "remove" deletes a device from the system.  Its argument is just the
+  name of the device to be removed. The device must be idle in whatever
+  sense the driver considers necessary.  In the case of the ubd driver,
+  the removed block device must not be mounted, swapped on, or otherwise
+  open, and in the case of the network driver, the device must be down.
+
+
+       (mconsole)  remove ubd3
+       OK
+       (mconsole)  remove eth1
+       OK
+
+
+
+
+
+
+  10.5.  sysrq
+
+  This takes one argument, which is a single letter.  It calls the
+  generic kernel's SysRq driver, which does whatever is called for by
+  that argument.  See the SysRq documentation in
+  Documentation/admin-guide/sysrq.rst in your favorite kernel tree to
+  see what letters are valid and what they do.
+
+
+
+  10.6.  help
+
+  "help" returns a string listing the valid commands and what each one
+  does.
+
+
+
+  10.7.  cad
+
+  This invokes the Ctl-Alt-Del action on init.  What exactly this ends
+  up doing is up to /etc/inittab.  Normally, it reboots the machine.
+  With UML, this is usually not desired, so if a halt would be better,
+  then find the section of inittab that looks like this
+
+
+       # What to do when CTRL-ALT-DEL is pressed.
+       ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
+
+
+
+
+  and change the command to halt.
+
+
+
+  10.8.  stop
+
+  This puts the UML in a loop reading mconsole requests until a 'go'
+  mconsole command is received. This is very useful for making backups
+  of UML filesystems, as the UML can be stopped, then synced via 'sysrq
+  s', so that everything is written to the filesystem. You can then copy
+  the filesystem and then send the UML 'go' via mconsole.
+
+
+  Note that a UML running with more than one CPU will have problems
+  after you send the 'stop' command, as only one CPU will be held in a
+  mconsole loop and all others will continue as normal.  This is a bug,
+  and will be fixed.
+
+
+
+  10.9.  go
+
+  This resumes a UML after being paused by a 'stop' command. Note that
+  when the UML has resumed, TCP connections may have timed out and if
+  the UML is paused for a long period of time, crond might go a little
+  crazy, running all the jobs it didn't do earlier.
+
+
+
+
+
+
+
+
+  11.  Kernel debugging
+
+
+  Note: The interface that makes debugging, as described here, possible
+  is present in 2.4.0-test6 kernels and later.
+
+
+  Since the user-mode kernel runs as a normal Linux process, it is
+  possible to debug it with gdb almost like any other process.  It is
+  slightly different because the kernel's threads are already being
+  ptraced for system call interception, so gdb can't ptrace them.
+  However, a mechanism has been added to work around that problem.
+
+
+  In order to debug the kernel, you need build it from source.  See
+  ``Compiling the kernel and modules''  for information on doing that.
+  Make sure that you enable CONFIG_DEBUGSYM and CONFIG_PT_PROXY during
+  the config.  These will compile the kernel with -g, and enable the
+  ptrace proxy so that gdb works with UML, respectively.
+
+
+
+
+  11.1.  Starting the kernel under gdb
+
+  You can have the kernel running under the control of gdb from the
+  beginning by putting 'debug' on the command line.  You will get an
+  xterm with gdb running inside it.  The kernel will send some commands
+  to gdb which will leave it stopped at the beginning of start_kernel.
+  At this point, you can get things going with 'next', 'step', or
+  'cont'.
+
+
+  There is a transcript of a debugging session  here <debug-
+  session.html> , with breakpoints being set in the scheduler and in an
+  interrupt handler.
+  11.2.  Examining sleeping processes
+
+  Not every bug is evident in the currently running process.  Sometimes,
+  processes hang in the kernel when they shouldn't because they've
+  deadlocked on a semaphore or something similar.  In this case, when
+  you ^C gdb and get a backtrace, you will see the idle thread, which
+  isn't very relevant.
+
+
+  What you want is the stack of whatever process is sleeping when it
+  shouldn't be.  You need to figure out which process that is, which is
+  generally fairly easy.  Then you need to get its host process id,
+  which you can do either by looking at ps on the host or at
+  task.thread.extern_pid in gdb.
+
+
+  Now what you do is this:
+
+  o  detach from the current thread
+
+
+       (UML gdb)  det
+
+
+
+
+
+  o  attach to the thread you are interested in
+
+
+       (UML gdb)  att <host pid>
+
+
+
+
+
+  o  look at its stack and anything else of interest
+
+
+       (UML gdb)  bt
+
+
+
+
+  Note that you can't do anything at this point that requires that a
+  process execute, e.g. calling a function
+
+  o  when you're done looking at that process, reattach to the current
+     thread and continue it
+
+
+       (UML gdb)
+       att 1
+
+
+
+
+
+
+       (UML gdb)
+       c
+
+
+
+
+  Here, specifying any pid which is not the process id of a UML thread
+  will cause gdb to reattach to the current thread.  I commonly use 1,
+  but any other invalid pid would work.
+
+
+
+  11.3.  Running ddd on UML
+
+  ddd works on UML, but requires a special kludge.  The process goes
+  like this:
+
+  o  Start ddd
+
+
+       host% ddd linux
+
+
+
+
+
+  o  With ps, get the pid of the gdb that ddd started.  You can ask the
+     gdb to tell you, but for some reason that confuses things and
+     causes a hang.
+
+  o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
+     - it will just sit there after you hit return
+
+  o  type 'att 1' to the ddd gdb and you will see something like
+
+
+       0xa013dc51 in __kill ()
+
+
+       (gdb)
+
+
+
+
+
+  o  At this point, type 'c', UML will boot up, and you can use ddd just
+     as you do on any other process.
+
+
+
+  11.4.  Debugging modules
+
+  gdb has support for debugging code which is dynamically loaded into
+  the process.  This support is what is needed to debug kernel modules
+  under UML.
+
+
+  Using that support is somewhat complicated.  You have to tell gdb what
+  object file you just loaded into UML and where in memory it is.  Then,
+  it can read the symbol table, and figure out where all the symbols are
+  from the load address that you provided.  It gets more interesting
+  when you load the module again (i.e. after an rmmod).  You have to
+  tell gdb to forget about all its symbols, including the main UML ones
+  for some reason, then load then all back in again.
+
+
+  There's an easy way and a hard way to do this.  The easy way is to use
+  the umlgdb expect script written by Chandan Kudige.  It basically
+  automates the process for you.
+
+
+  First, you must tell it where your modules are.  There is a list in
+  the script that looks like this:
+       set MODULE_PATHS {
+       "fat" "/usr/src/uml/linux-2.4.18/fs/fat/fat.o"
+       "isofs" "/usr/src/uml/linux-2.4.18/fs/isofs/isofs.o"
+       "minix" "/usr/src/uml/linux-2.4.18/fs/minix/minix.o"
+       }
+
+
+
+
+  You change that to list the names and paths of the modules that you
+  are going to debug.  Then you run it from the toplevel directory of
+  your UML pool and it basically tells you what to do:
+
+
+
+
+                   ******** GDB pid is 21903 ********
+       Start UML as: ./linux <kernel switches> debug gdb-pid=21903
+
+
+
+       GNU gdb 5.0rh-5 Red Hat Linux 7.1
+       Copyright 2001 Free Software Foundation, Inc.
+       GDB is free software, covered by the GNU General Public License, and you are
+       welcome to change it and/or distribute copies of it under certain conditions.
+       Type "show copying" to see the conditions.
+       There is absolutely no warranty for GDB.  Type "show warranty" for details.
+       This GDB was configured as "i386-redhat-linux"...
+       (gdb) b sys_init_module
+       Breakpoint 1 at 0xa0011923: file module.c, line 349.
+       (gdb) att 1
+
+
+
+
+  After you run UML and it sits there doing nothing, you hit return at
+  the 'att 1' and continue it:
+
+
+       Attaching to program: /home/jdike/linux/2.4/um/./linux, process 1
+       0xa00f4221 in __kill ()
+       (UML gdb)  c
+       Continuing.
+
+
+
+
+  At this point, you debug normally.  When you insmod something, the
+  expect magic will kick in and you'll see something like:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+   *** Module hostfs loaded ***
+  Breakpoint 1, sys_init_module (name_user=0x805abb0 "hostfs",
+      mod_user=0x8070e00) at module.c:349
+  349             char *name, *n_name, *name_tmp = NULL;
+  (UML gdb)  finish
+  Run till exit from #0  sys_init_module (name_user=0x805abb0 "hostfs",
+      mod_user=0x8070e00) at module.c:349
+  0xa00e2e23 in execute_syscall (r=0xa8140284) at syscall_kern.c:411
+  411             else res = EXECUTE_SYSCALL(syscall, regs);
+  Value returned is $1 = 0
+  (UML gdb)
+  p/x (int)module_list + module_list->size_of_struct
+
+  $2 = 0xa9021054
+  (UML gdb)  symbol-file ./linux
+  Load new symbol table from "./linux"? (y or n) y
+  Reading symbols from ./linux...
+  done.
+  (UML gdb)
+  add-symbol-file /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o 0xa9021054
+
+  add symbol table from file "/home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o" at
+          .text_addr = 0xa9021054
+   (y or n) y
+
+  Reading symbols from /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o...
+  done.
+  (UML gdb)  p *module_list
+  $1 = {size_of_struct = 84, next = 0xa0178720, name = 0xa9022de0 "hostfs",
+    size = 9016, uc = {usecount = {counter = 0}, pad = 0}, flags = 1,
+    nsyms = 57, ndeps = 0, syms = 0xa9023170, deps = 0x0, refs = 0x0,
+    init = 0xa90221f0 <init_hostfs>, cleanup = 0xa902222c <exit_hostfs>,
+    ex_table_start = 0x0, ex_table_end = 0x0, persist_start = 0x0,
+    persist_end = 0x0, can_unload = 0, runsize = 0, kallsyms_start = 0x0,
+    kallsyms_end = 0x0,
+    archdata_start = 0x1b855 <Address 0x1b855 out of bounds>,
+    archdata_end = 0xe5890000 <Address 0xe5890000 out of bounds>,
+    kernel_data = 0xf689c35d <Address 0xf689c35d out of bounds>}
+  >> Finished loading symbols for hostfs ...
+
+
+
+
+  That's the easy way.  It's highly recommended.  The hard way is
+  described below in case you're interested in what's going on.
+
+
+  Boot the kernel under the debugger and load the module with insmod or
+  modprobe.  With gdb, do:
+
+
+       (UML gdb)  p module_list
+
+
+
+
+  This is a list of modules that have been loaded into the kernel, with
+  the most recently loaded module first.  Normally, the module you want
+  is at module_list.  If it's not, walk down the next links, looking at
+  the name fields until find the module you want to debug.  Take the
+  address of that structure, and add module.size_of_struct (which in
+  2.4.10 kernels is 96 (0x60)) to it.  Gdb can make this hard addition
+  for you :-):
+
+
+
+  (UML gdb)
+  printf "%#x\n", (int)module_list module_list->size_of_struct
+
+
+
+
+  The offset from the module start occasionally changes (before 2.4.0,
+  it was module.size_of_struct + 4), so it's a good idea to check the
+  init and cleanup addresses once in a while, as describe below.  Now
+  do:
+
+
+       (UML gdb)
+       add-symbol-file /path/to/module/on/host that_address
+
+
+
+
+  Tell gdb you really want to do it, and you're in business.
+
+
+  If there's any doubt that you got the offset right, like breakpoints
+  appear not to work, or they're appearing in the wrong place, you can
+  check it by looking at the module structure.  The init and cleanup
+  fields should look like:
+
+
+       init = 0x588066b0 <init_hostfs>, cleanup = 0x588066c0 <exit_hostfs>
+
+
+
+
+  with no offsets on the symbol names.  If the names are right, but they
+  are offset, then the offset tells you how much you need to add to the
+  address you gave to add-symbol-file.
+
+
+  When you want to load in a new version of the module, you need to get
+  gdb to forget about the old one.  The only way I've found to do that
+  is to tell gdb to forget about all symbols that it knows about:
+
+
+       (UML gdb)  symbol-file
+
+
+
+
+  Then reload the symbols from the kernel binary:
+
+
+       (UML gdb)  symbol-file /path/to/kernel
+
+
+
+
+  and repeat the process above.  You'll also need to re-enable break-
+  points.  They were disabled when you dumped all the symbols because
+  gdb couldn't figure out where they should go.
+
+
+
+  11.5.  Attaching gdb to the kernel
+
+  If you don't have the kernel running under gdb, you can attach gdb to
+  it later by sending the tracing thread a SIGUSR1.  The first line of
+  the console output identifies its pid:
+       tracing thread pid = 20093
+
+
+
+
+  When you send it the signal:
+
+
+       host% kill -USR1 20093
+
+
+
+
+  you will get an xterm with gdb running in it.
+
+
+  If you have the mconsole compiled into UML, then the mconsole client
+  can be used to start gdb:
+
+
+       (mconsole)  (mconsole) config gdb=xterm
+
+
+
+
+  will fire up an xterm with gdb running in it.
+
+
+
+  11.6.  Using alternate debuggers
+
+  UML has support for attaching to an already running debugger rather
+  than starting gdb itself.  This is present in CVS as of 17 Apr 2001.
+  I sent it to Alan for inclusion in the ac tree, and it will be in my
+  2.4.4 release.
+
+
+  This is useful when gdb is a subprocess of some UI, such as emacs or
+  ddd.  It can also be used to run debuggers other than gdb on UML.
+  Below is an example of using strace as an alternate debugger.
+
+
+  To do this, you need to get the pid of the debugger and pass it in
+  with the
+
+
+  If you are using gdb under some UI, then tell it to 'att 1', and
+  you'll find yourself attached to UML.
+
+
+  If you are using something other than gdb as your debugger, then
+  you'll need to get it to do the equivalent of 'att 1' if it doesn't do
+  it automatically.
+
+
+  An example of an alternate debugger is strace.  You can strace the
+  actual kernel as follows:
+
+  o  Run the following in a shell
+
+
+       host%
+       sh -c 'echo pid=$$; echo -n hit return; read x; exec strace -p 1 -o strace.out'
+
+
+
+  o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
+     by the previous command
+
+  o  Hit return in the shell, and UML will start running, and strace
+     output will start accumulating in the output file.
+
+     Note that this is different from running
+
+
+       host% strace ./linux
+
+
+
+
+  That will strace only the main UML thread, the tracing thread, which
+  doesn't do any of the actual kernel work.  It just oversees the vir-
+  tual machine.  In contrast, using strace as described above will show
+  you the low-level activity of the virtual machine.
+
+
+
+
+
+  12.  Kernel debugging examples
+
+  12.1.  The case of the hung fsck
+
+  When booting up the kernel, fsck failed, and dropped me into a shell
+  to fix things up.  I ran fsck -y, which hung:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  Setting hostname uml                    [ OK ]
+  Checking root filesystem
+  /dev/fhd0 was not cleanly unmounted, check forced.
+  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
+
+  /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
+          (i.e., without -a or -p options)
+  [ FAILED ]
+
+  *** An error occurred during the file system check.
+  *** Dropping you to a shell; the system will reboot
+  *** when you leave the shell.
+  Give root password for maintenance
+  (or type Control-D for normal startup):
+
+  [root@uml /root]# fsck -y /dev/fhd0
+  fsck -y /dev/fhd0
+  Parallelizing fsck version 1.14 (9-Jan-1999)
+  e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
+  /dev/fhd0 contains a file system with errors, check forced.
+  Pass 1: Checking inodes, blocks, and sizes
+  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.  Ignore error? yes
+
+  Inode 19780, i_blocks is 1548, should be 540.  Fix? yes
+
+  Pass 2: Checking directory structure
+  Error reading block 49405 (Attempt to read block from filesystem resulted in short read).  Ignore error? yes
+
+  Directory inode 11858, block 0, offset 0: directory corrupted
+  Salvage? yes
+
+  Missing '.' in directory inode 11858.
+  Fix? yes
+
+  Missing '..' in directory inode 11858.
+  Fix? yes
+
+
+
+
+
+  The standard drill in this sort of situation is to fire up gdb on the
+  signal thread, which, in this case, was pid 1935.  In another window,
+  I run gdb and attach pid 1935.
+
+
+
+
+       ~/linux/2.3.26/um 1016: gdb linux
+       GNU gdb 4.17.0.11 with Linux support
+       Copyright 1998 Free Software Foundation, Inc.
+       GDB is free software, covered by the GNU General Public License, and you are
+       welcome to change it and/or distribute copies of it under certain conditions.
+       Type "show copying" to see the conditions.
+       There is absolutely no warranty for GDB.  Type "show warranty" for details.
+       This GDB was configured as "i386-redhat-linux"...
+
+       (gdb) att 1935
+       Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1935
+       0x100756d9 in __wait4 ()
+
+
+
+
+
+
+  Let's see what's currently running:
+
+
+
+       (gdb) p current_task.pid
+       $1 = 0
+
+
+
+
+
+  It's the idle thread, which means that fsck went to sleep for some
+  reason and never woke up.
+
+
+  Let's guess that the last process in the process list is fsck:
+
+
+
+       (gdb) p current_task.prev_task.comm
+       $13 = "fsck.ext2\000\000\000\000\000\000"
+
+
+
+
+
+  It is, so let's see what it thinks it's up to:
+
+
+
+       (gdb) p current_task.prev_task.thread
+       $14 = {extern_pid = 1980, tracing = 0, want_tracing = 0, forking = 0,
+         kernel_stack_page = 0, signal_stack = 1342627840, syscall = {id = 4, args = {
+             3, 134973440, 1024, 0, 1024}, have_result = 0, result = 50590720},
+         request = {op = 2, u = {exec = {ip = 1350467584, sp = 2952789424}, fork = {
+               regs = {1350467584, 2952789424, 0 <repeats 15 times>}, sigstack = 0,
+               pid = 0}, switch_to = 0x507e8000, thread = {proc = 0x507e8000,
+               arg = 0xaffffdb0, flags = 0, new_pid = 0}, input_request = {
+               op = 1350467584, fd = -1342177872, proc = 0, pid = 0}}}}
+
+
+
+
+
+  The interesting things here are the fact that its .thread.syscall.id
+  is __NR_write (see the big switch in arch/um/kernel/syscall_kern.c or
+  the defines in include/asm-um/arch/unistd.h), and that it never
+  returned.  Also, its .request.op is OP_SWITCH (see
+  arch/um/include/user_util.h).  These mean that it went into a write,
+  and, for some reason, called schedule().
+
+
+  The fact that it never returned from write means that its stack should
+  be fairly interesting.  Its pid is 1980 (.thread.extern_pid).  That
+  process is being ptraced by the signal thread, so it must be detached
+  before gdb can attach it:
+
+
+
+
+
+
+
+
+
+
+  (gdb) call detach(1980)
+
+  Program received signal SIGSEGV, Segmentation fault.
+  <function called from gdb>
+  The program being debugged stopped while in a function called from GDB.
+  When the function (detach) is done executing, GDB will silently
+  stop (instead of continuing to evaluate the expression containing
+  the function call).
+  (gdb) call detach(1980)
+  $15 = 0
+
+
+
+
+
+  The first detach segfaults for some reason, and the second one
+  succeeds.
+
+
+  Now I detach from the signal thread, attach to the fsck thread, and
+  look at its stack:
+
+
+       (gdb) det
+       Detaching from program: /home/dike/linux/2.3.26/um/linux Pid 1935
+       (gdb) att 1980
+       Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1980
+       0x10070451 in __kill ()
+       (gdb) bt
+       #0  0x10070451 in __kill ()
+       #1  0x10068ccd in usr1_pid (pid=1980) at process.c:30
+       #2  0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
+           at process_kern.c:156
+       #3  0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
+           at process_kern.c:161
+       #4  0x10001d12 in schedule () at core.c:777
+       #5  0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
+       #6  0x1006aa10 in __down_failed () at semaphore.c:157
+       #7  0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
+       #8  0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+       #9  <signal handler called>
+       #10 0x10155404 in errno ()
+       #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
+       #12 0x1006c5d8 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+       #13 0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+       #14 <signal handler called>
+       #15 0xc0fd in ?? ()
+       #16 0x10016647 in sys_write (fd=3,
+           buf=0x80b8800 <Address 0x80b8800 out of bounds>, count=1024)
+           at read_write.c:159
+       #17 0x1006d5b3 in execute_syscall (syscall=4, args=0x5006ef08)
+           at syscall_kern.c:254
+       #18 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
+       #19 <signal handler called>
+       #20 0x400dc8b0 in ?? ()
+
+
+
+
+
+  The interesting things here are :
+
+  o  There are two segfaults on this stack (frames 9 and 14)
+
+  o  The first faulting address (frame 11) is 0x50000800
+
+  (gdb) p (void *)1342179328
+  $16 = (void *) 0x50000800
+
+
+
+
+
+  The initial faulting address is interesting because it is on the idle
+  thread's stack.  I had been seeing the idle thread segfault for no
+  apparent reason, and the cause looked like stack corruption.  In hopes
+  of catching the culprit in the act, I had turned off all protections
+  to that stack while the idle thread wasn't running.  This apparently
+  tripped that trap.
+
+
+  However, the more immediate problem is that second segfault and I'm
+  going to concentrate on that.  First, I want to see where the fault
+  happened, so I have to go look at the sigcontent struct in frame 8:
+
+
+
+       (gdb) up
+       #1  0x10068ccd in usr1_pid (pid=1980) at process.c:30
+       30        kill(pid, SIGUSR1);
+       (gdb)
+       #2  0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
+           at process_kern.c:156
+       156       usr1_pid(getpid());
+       (gdb)
+       #3  0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
+           at process_kern.c:161
+       161       _switch_to(prev, next);
+       (gdb)
+       #4  0x10001d12 in schedule () at core.c:777
+       777             switch_to(prev, next, prev);
+       (gdb)
+       #5  0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
+       71                      schedule();
+       (gdb)
+       #6  0x1006aa10 in __down_failed () at semaphore.c:157
+       157     }
+       (gdb)
+       #7  0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
+       174       segv(sc->cr2, sc->err & 2);
+       (gdb)
+       #8  0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+       182       segv_handler(sc);
+       (gdb) p *sc
+       Cannot access memory at address 0x0.
+
+
+
+
+  That's not very useful, so I'll try a more manual method:
+
+
+       (gdb) p *((struct sigcontext *) (&sig + 1))
+       $19 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
+         __dsh = 0, edi = 1342179328, esi = 1350378548, ebp = 1342630440,
+         esp = 1342630420, ebx = 1348150624, edx = 1280, ecx = 0, eax = 0,
+         trapno = 14, err = 4, eip = 268480945, cs = 35, __csh = 0, eflags = 66118,
+         esp_at_signal = 1342630420, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
+         cr2 = 1280}
+
+
+
+  The ip is in handle_mm_fault:
+
+
+       (gdb) p (void *)268480945
+       $20 = (void *) 0x1000b1b1
+       (gdb) i sym $20
+       handle_mm_fault + 57 in section .text
+
+
+
+
+
+  Specifically, it's in pte_alloc:
+
+
+       (gdb) i line *$20
+       Line 124 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1b1 <handle_mm_fault+57>
+          and ends at 0x1000b1b7 <handle_mm_fault+63>.
+
+
+
+
+
+  To find where in handle_mm_fault this is, I'll jump forward in the
+  code until I see an address in that procedure:
+
+
+
+       (gdb) i line *0x1000b1c0
+       Line 126 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1b7 <handle_mm_fault+63>
+          and ends at 0x1000b1c3 <handle_mm_fault+75>.
+       (gdb) i line *0x1000b1d0
+       Line 131 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1d0 <handle_mm_fault+88>
+          and ends at 0x1000b1da <handle_mm_fault+98>.
+       (gdb) i line *0x1000b1e0
+       Line 61 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1da <handle_mm_fault+98>
+          and ends at 0x1000b1e1 <handle_mm_fault+105>.
+       (gdb) i line *0x1000b1f0
+       Line 134 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1f0 <handle_mm_fault+120>
+          and ends at 0x1000b200 <handle_mm_fault+136>.
+       (gdb) i line *0x1000b200
+       Line 135 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b200 <handle_mm_fault+136>
+          and ends at 0x1000b208 <handle_mm_fault+144>.
+       (gdb) i line *0x1000b210
+       Line 139 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b210 <handle_mm_fault+152>
+          and ends at 0x1000b219 <handle_mm_fault+161>.
+       (gdb) i line *0x1000b220
+       Line 1168 of "memory.c" starts at address 0x1000b21e <handle_mm_fault+166>
+          and ends at 0x1000b222 <handle_mm_fault+170>.
+
+
+
+
+
+  Something is apparently wrong with the page tables or vma_structs, so
+  lets go back to frame 11 and have a look at them:
+
+
+
+  #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
+  50        handle_mm_fault(current, vma, address, is_write);
+  (gdb) call pgd_offset_proc(vma->vm_mm, address)
+  $22 = (pgd_t *) 0x80a548c
+
+
+
+
+
+  That's pretty bogus.  Page tables aren't supposed to be in process
+  text or data areas.  Let's see what's in the vma:
+
+
+       (gdb) p *vma
+       $23 = {vm_mm = 0x507d2434, vm_start = 0, vm_end = 134512640,
+         vm_next = 0x80a4f8c, vm_page_prot = {pgprot = 0}, vm_flags = 31200,
+         vm_avl_height = 2058, vm_avl_left = 0x80a8c94, vm_avl_right = 0x80d1000,
+         vm_next_share = 0xaffffdb0, vm_pprev_share = 0xaffffe63,
+         vm_ops = 0xaffffe7a, vm_pgoff = 2952789626, vm_file = 0xafffffec,
+         vm_private_data = 0x62}
+       (gdb) p *vma.vm_mm
+       $24 = {mmap = 0x507d2434, mmap_avl = 0x0, mmap_cache = 0x8048000,
+         pgd = 0x80a4f8c, mm_users = {counter = 0}, mm_count = {counter = 134904288},
+         map_count = 134909076, mmap_sem = {count = {counter = 135073792},
+           sleepers = -1342177872, wait = {lock = <optimized out or zero length>,
+             task_list = {next = 0xaffffe63, prev = 0xaffffe7a},
+             __magic = -1342177670, __creator = -1342177300}, __magic = 98},
+         page_table_lock = {}, context = 138, start_code = 0, end_code = 0,
+         start_data = 0, end_data = 0, start_brk = 0, brk = 0, start_stack = 0,
+         arg_start = 0, arg_end = 0, env_start = 0, env_end = 0, rss = 1350381536,
+         total_vm = 0, locked_vm = 0, def_flags = 0, cpu_vm_mask = 0, swap_cnt = 0,
+         swap_address = 0, segments = 0x0}
+
+
+
+
+
+  This also pretty bogus.  With all of the 0x80xxxxx and 0xaffffxxx
+  addresses, this is looking like a stack was plonked down on top of
+  these structures.  Maybe it's a stack overflow from the next page:
+
+
+
+       (gdb) p vma
+       $25 = (struct vm_area_struct *) 0x507d2434
+
+
+
+
+
+  That's towards the lower quarter of the page, so that would have to
+  have been pretty heavy stack overflow:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  (gdb) x/100x $25
+  0x507d2434:     0x507d2434      0x00000000      0x08048000      0x080a4f8c
+  0x507d2444:     0x00000000      0x080a79e0      0x080a8c94      0x080d1000
+  0x507d2454:     0xaffffdb0      0xaffffe63      0xaffffe7a      0xaffffe7a
+  0x507d2464:     0xafffffec      0x00000062      0x0000008a      0x00000000
+  0x507d2474:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2484:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2494:     0x00000000      0x00000000      0x507d2fe0      0x00000000
+  0x507d24a4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24b4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24c4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24d4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24e4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24f4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2504:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2514:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2524:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2534:     0x00000000      0x00000000      0x507d25dc      0x00000000
+  0x507d2544:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2554:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2564:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2574:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2584:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2594:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d25a4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d25b4:     0x00000000      0x00000000      0x00000000      0x00000000
+
+
+
+
+
+  It's not stack overflow.  The only "stack-like" piece of this data is
+  the vma_struct itself.
+
+
+  At this point, I don't see any avenues to pursue, so I just have to
+  admit that I have no idea what's going on.  What I will do, though, is
+  stick a trap on the segfault handler which will stop if it sees any
+  writes to the idle thread's stack.  That was the thing that happened
+  first, and it may be that if I can catch it immediately, what's going
+  on will be somewhat clearer.
+
+
+  12.2.  Episode 2: The case of the hung fsck
+
+  After setting a trap in the SEGV handler for accesses to the signal
+  thread's stack, I reran the kernel.
+
+
+  fsck hung again, this time by hitting the trap:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  Setting hostname uml                            [ OK ]
+  Checking root filesystem
+  /dev/fhd0 contains a file system with errors, check forced.
+  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
+
+  /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
+          (i.e., without -a or -p options)
+  [ FAILED ]
+
+  *** An error occurred during the file system check.
+  *** Dropping you to a shell; the system will reboot
+  *** when you leave the shell.
+  Give root password for maintenance
+  (or type Control-D for normal startup):
+
+  [root@uml /root]# fsck -y /dev/fhd0
+  fsck -y /dev/fhd0
+  Parallelizing fsck version 1.14 (9-Jan-1999)
+  e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
+  /dev/fhd0 contains a file system with errors, check forced.
+  Pass 1: Checking inodes, blocks, and sizes
+  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.  Ignore error? yes
+
+  Pass 2: Checking directory structure
+  Error reading block 49405 (Attempt to read block from filesystem resulted in short read).  Ignore error? yes
+
+  Directory inode 11858, block 0, offset 0: directory corrupted
+  Salvage? yes
+
+  Missing '.' in directory inode 11858.
+  Fix? yes
+
+  Missing '..' in directory inode 11858.
+  Fix? yes
+
+  Untested (4127) [100fe44c]: trap_kern.c line 31
+
+
+
+
+
+  I need to get the signal thread to detach from pid 4127 so that I can
+  attach to it with gdb.  This is done by sending it a SIGUSR1, which is
+  caught by the signal thread, which detaches the process:
+
+
+       kill -USR1 4127
+
+
+
+
+
+  Now I can run gdb on it:
+
+
+
+
+
+
+
+
+
+
+
+
+
+  ~/linux/2.3.26/um 1034: gdb linux
+  GNU gdb 4.17.0.11 with Linux support
+  Copyright 1998 Free Software Foundation, Inc.
+  GDB is free software, covered by the GNU General Public License, and you are
+  welcome to change it and/or distribute copies of it under certain conditions.
+  Type "show copying" to see the conditions.
+  There is absolutely no warranty for GDB.  Type "show warranty" for details.
+  This GDB was configured as "i386-redhat-linux"...
+  (gdb) att 4127
+  Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 4127
+  0x10075891 in __libc_nanosleep ()
+
+
+
+
+
+  The backtrace shows that it was in a write and that the fault address
+  (address in frame 3) is 0x50000800, which is right in the middle of
+  the signal thread's stack page:
+
+
+       (gdb) bt
+       #0  0x10075891 in __libc_nanosleep ()
+       #1  0x1007584d in __sleep (seconds=1000000)
+           at ../sysdeps/unix/sysv/linux/sleep.c:78
+       #2  0x1006ce9a in stop () at user_util.c:191
+       #3  0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
+       #4  0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+       #5  0x1006c63c in kern_segv_handler (sig=11) at trap_user.c:182
+       #6  <signal handler called>
+       #7  0xc0fd in ?? ()
+       #8  0x10016647 in sys_write (fd=3, buf=0x80b8800 "R.", count=1024)
+           at read_write.c:159
+       #9  0x1006d603 in execute_syscall (syscall=4, args=0x5006ef08)
+           at syscall_kern.c:254
+       #10 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
+       #11 <signal handler called>
+       #12 0x400dc8b0 in ?? ()
+       #13 <signal handler called>
+       #14 0x400dc8b0 in ?? ()
+       #15 0x80545fd in ?? ()
+       #16 0x804daae in ?? ()
+       #17 0x8054334 in ?? ()
+       #18 0x804d23e in ?? ()
+       #19 0x8049632 in ?? ()
+       #20 0x80491d2 in ?? ()
+       #21 0x80596b5 in ?? ()
+       (gdb) p (void *)1342179328
+       $3 = (void *) 0x50000800
+
+
+
+
+
+  Going up the stack to the segv_handler frame and looking at where in
+  the code the access happened shows that it happened near line 110 of
+  block_dev.c:
+
+
+
+
+
+
+
+
+
+  (gdb) up
+  #1  0x1007584d in __sleep (seconds=1000000)
+      at ../sysdeps/unix/sysv/linux/sleep.c:78
+  ../sysdeps/unix/sysv/linux/sleep.c:78: No such file or directory.
+  (gdb)
+  #2  0x1006ce9a in stop () at user_util.c:191
+  191       while(1) sleep(1000000);
+  (gdb)
+  #3  0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
+  31          KERN_UNTESTED();
+  (gdb)
+  #4  0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+  174       segv(sc->cr2, sc->err & 2);
+  (gdb) p *sc
+  $1 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
+    __dsh = 0, edi = 1342179328, esi = 134973440, ebp = 1342631484,
+    esp = 1342630864, ebx = 256, edx = 0, ecx = 256, eax = 1024, trapno = 14,
+    err = 6, eip = 268550834, cs = 35, __csh = 0, eflags = 66070,
+    esp_at_signal = 1342630864, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
+    cr2 = 1342179328}
+  (gdb) p (void *)268550834
+  $2 = (void *) 0x1001c2b2
+  (gdb) i sym $2
+  block_write + 1090 in section .text
+  (gdb) i line *$2
+  Line 209 of "/home/dike/linux/2.3.26/um/include/asm/arch/string.h"
+     starts at address 0x1001c2a1 <block_write+1073>
+     and ends at 0x1001c2bf <block_write+1103>.
+  (gdb) i line *0x1001c2c0
+  Line 110 of "block_dev.c" starts at address 0x1001c2bf <block_write+1103>
+     and ends at 0x1001c2e3 <block_write+1139>.
+
+
+
+
+
+  Looking at the source shows that the fault happened during a call to
+  copy_from_user to copy the data into the kernel:
+
+
+       107             count -= chars;
+       108             copy_from_user(p,buf,chars);
+       109             p += chars;
+       110             buf += chars;
+
+
+
+
+
+  p is the pointer which must contain 0x50000800, since buf contains
+  0x80b8800 (frame 8 above).  It is defined as:
+
+
+                       p = offset + bh->b_data;
+
+
+
+
+
+  I need to figure out what bh is, and it just so happens that bh is
+  passed as an argument to mark_buffer_uptodate and mark_buffer_dirty a
+  few lines later, so I do a little disassembly:
+
+
+
+
+  (gdb) disas 0x1001c2bf 0x1001c2e0
+  Dump of assembler code from 0x1001c2bf to 0x1001c2d0:
+  0x1001c2bf <block_write+1103>:  addl   %eax,0xc(%ebp)
+  0x1001c2c2 <block_write+1106>:  movl   0xfffffdd4(%ebp),%edx
+  0x1001c2c8 <block_write+1112>:  btsl   $0x0,0x18(%edx)
+  0x1001c2cd <block_write+1117>:  btsl   $0x1,0x18(%edx)
+  0x1001c2d2 <block_write+1122>:  sbbl   %ecx,%ecx
+  0x1001c2d4 <block_write+1124>:  testl  %ecx,%ecx
+  0x1001c2d6 <block_write+1126>:  jne    0x1001c2e3 <block_write+1139>
+  0x1001c2d8 <block_write+1128>:  pushl  $0x0
+  0x1001c2da <block_write+1130>:  pushl  %edx
+  0x1001c2db <block_write+1131>:  call   0x1001819c <__mark_buffer_dirty>
+  End of assembler dump.
+
+
+
+
+
+  At that point, bh is in %edx (address 0x1001c2da), which is calculated
+  at 0x1001c2c2 as %ebp + 0xfffffdd4, so I figure exactly what that is,
+  taking %ebp from the sigcontext_struct above:
+
+
+       (gdb) p (void *)1342631484
+       $5 = (void *) 0x5006ee3c
+       (gdb) p 0x5006ee3c+0xfffffdd4
+       $6 = 1342630928
+       (gdb) p (void *)$6
+       $7 = (void *) 0x5006ec10
+       (gdb) p *((void **)$7)
+       $8 = (void *) 0x50100200
+
+
+
+
+
+  Now, I look at the structure to see what's in it, and particularly,
+  what its b_data field contains:
+
+
+       (gdb) p *((struct buffer_head *)0x50100200)
+       $13 = {b_next = 0x50289380, b_blocknr = 49405, b_size = 1024, b_list = 0,
+         b_dev = 15872, b_count = {counter = 1}, b_rdev = 15872, b_state = 24,
+         b_flushtime = 0, b_next_free = 0x501001a0, b_prev_free = 0x50100260,
+         b_this_page = 0x501001a0, b_reqnext = 0x0, b_pprev = 0x507fcf58,
+         b_data = 0x50000800 "", b_page = 0x50004000,
+         b_end_io = 0x10017f60 <end_buffer_io_sync>, b_dev_id = 0x0,
+         b_rsector = 98810, b_wait = {lock = <optimized out or zero length>,
+           task_list = {next = 0x50100248, prev = 0x50100248}, __magic = 1343226448,
+           __creator = 0}, b_kiobuf = 0x0}
+
+
+
+
+
+  The b_data field is indeed 0x50000800, so the question becomes how
+  that happened.  The rest of the structure looks fine, so this probably
+  is not a case of data corruption.  It happened on purpose somehow.
+
+
+  The b_page field is a pointer to the page_struct representing the
+  0x50000000 page.  Looking at it shows the kernel's idea of the state
+  of that page:
+
+
+
+  (gdb) p *$13.b_page
+  $17 = {list = {next = 0x50004a5c, prev = 0x100c5174}, mapping = 0x0,
+    index = 0, next_hash = 0x0, count = {counter = 1}, flags = 132, lru = {
+      next = 0x50008460, prev = 0x50019350}, wait = {
+      lock = <optimized out or zero length>, task_list = {next = 0x50004024,
+        prev = 0x50004024}, __magic = 1342193708, __creator = 0},
+    pprev_hash = 0x0, buffers = 0x501002c0, virtual = 1342177280,
+    zone = 0x100c5160}
+
+
+
+
+
+  Some sanity-checking: the virtual field shows the "virtual" address of
+  this page, which in this kernel is the same as its "physical" address,
+  and the page_struct itself should be mem_map[0], since it represents
+  the first page of memory:
+
+
+
+       (gdb) p (void *)1342177280
+       $18 = (void *) 0x50000000
+       (gdb) p mem_map
+       $19 = (mem_map_t *) 0x50004000
+
+
+
+
+
+  These check out fine.
+
+
+  Now to check out the page_struct itself.  In particular, the flags
+  field shows whether the page is considered free or not:
+
+
+       (gdb) p (void *)132
+       $21 = (void *) 0x84
+
+
+
+
+
+  The "reserved" bit is the high bit, which is definitely not set, so
+  the kernel considers the signal stack page to be free and available to
+  be used.
+
+
+  At this point, I jump to conclusions and start looking at my early
+  boot code, because that's where that page is supposed to be reserved.
+
+
+  In my setup_arch procedure, I have the following code which looks just
+  fine:
+
+
+
+       bootmap_size = init_bootmem(start_pfn, end_pfn - start_pfn);
+       free_bootmem(__pa(low_physmem) + bootmap_size, high_physmem - low_physmem);
+
+
+
+
+
+  Two stack pages have already been allocated, and low_physmem points to
+  the third page, which is the beginning of free memory.
+  The init_bootmem call declares the entire memory to the boot memory
+  manager, which marks it all reserved.  The free_bootmem call frees up
+  all of it, except for the first two pages.  This looks correct to me.
+
+
+  So, I decide to see init_bootmem run and make sure that it is marking
+  those first two pages as reserved.  I never get that far.
+
+
+  Stepping into init_bootmem, and looking at bootmem_map before looking
+  at what it contains shows the following:
+
+
+
+       (gdb) p bootmem_map
+       $3 = (void *) 0x50000000
+
+
+
+
+
+  Aha!  The light dawns.  That first page is doing double duty as a
+  stack and as the boot memory map.  The last thing that the boot memory
+  manager does is to free the pages used by its memory map, so this page
+  is getting freed even its marked as reserved.
+
+
+  The fix was to initialize the boot memory manager before allocating
+  those two stack pages, and then allocate them through the boot memory
+  manager.  After doing this, and fixing a couple of subsequent buglets,
+  the stack corruption problem disappeared.
+
+
+
+
+
+  13.  What to do when UML doesn't work
+
+
+
+
+  13.1.  Strange compilation errors when you build from source
+
+  As of test11, it is necessary to have "ARCH=um" in the environment or
+  on the make command line for all steps in building UML, including
+  clean, distclean, or mrproper, config, menuconfig, or xconfig, dep,
+  and linux.  If you forget for any of them, the i386 build seems to
+  contaminate the UML build.  If this happens, start from scratch with
+
+
+       host%
+       make mrproper ARCH=um
+
+
+
+
+  and repeat the build process with ARCH=um on all the steps.
+
+
+  See ``Compiling the kernel and modules''  for more details.
+
+
+  Another cause of strange compilation errors is building UML in
+  /usr/src/linux.  If you do this, the first thing you need to do is
+  clean up the mess you made.  The /usr/src/linux/asm link will now
+  point to /usr/src/linux/asm-um.  Make it point back to
+  /usr/src/linux/asm-i386.  Then, move your UML pool someplace else and
+  build it there.  Also see below, where a more specific set of symptoms
+  is described.
+
+
+
+  13.3.  A variety of panics and hangs with /tmp on a reiserfs  filesys-
+  tem
+
+  I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
+  Panics preceded by
+
+
+       Detaching pid nnnn
+
+
+
+  are diagnostic of this problem.  This is a reiserfs bug which causes a
+  thread to occasionally read stale data from a mmapped page shared with
+  another thread.  The fix is to upgrade the filesystem or to have /tmp
+  be an ext2 filesystem.
+
+
+
+  13.4.  The compile fails with errors about conflicting types for
+  'open', 'dup', and 'waitpid'
+
+  This happens when you build in /usr/src/linux.  The UML build makes
+  the include/asm link point to include/asm-um.  /usr/include/asm points
+  to /usr/src/linux/include/asm, so when that link gets moved, files
+  which need to include the asm-i386 versions of headers get the
+  incompatible asm-um versions.  The fix is to move the include/asm link
+  back to include/asm-i386 and to do UML builds someplace else.
+
+
+
+  13.5.  UML doesn't work when /tmp is an NFS filesystem
+
+  This seems to be a similar situation with the ReiserFS problem above.
+  Some versions of NFS seems not to handle mmap correctly, which UML
+  depends on.  The workaround is have /tmp be a non-NFS directory.
+
+
+  13.6.  UML hangs on boot when compiled with gprof support
+
+  If you build UML with gprof support and, early in the boot, it does
+  this
+
+
+       kernel BUG at page_alloc.c:100!
+
+
+
+
+  you have a buggy gcc.  You can work around the problem by removing
+  UM_FASTCALL from CFLAGS in arch/um/Makefile-i386.  This will open up
+  another bug, but that one is fairly hard to reproduce.
+
+
+
+  13.7.  syslogd dies with a SIGTERM on startup
+
+  The exact boot error depends on the distribution that you're booting,
+  but Debian produces this:
+
+
+       /etc/rc2.d/S10sysklogd: line 49:    93 Terminated
+       start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD
+
+
+
+
+  This is a syslogd bug.  There's a race between a parent process
+  installing a signal handler and its child sending the signal.  See
+  this uml-devel post <http://www.geocrawler.com/lists/3/Source-
+  Forge/709/0/6612801>  for the details.
+
+
+
+  13.8.  TUN/TAP networking doesn't work on a 2.4 host
+
+  There are a couple of problems which were
+  <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
+  out">  by Tim Robinson <timro at trkr dot net>
+
+  o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
+     The fix is to upgrade to something more recent and then read the
+     next item.
+
+  o  If you see
+
+
+       File descriptor in bad state
+
+
+
+  when you bring up the device inside UML, you have a header mismatch
+  between the original kernel and the upgraded one.  Make /usr/src/linux
+  point at the new headers.  This will only be a problem if you build
+  uml_net yourself.
+
+
+
+  13.9.  You can network to the host but not to other machines on the
+  net
+
+  If you can connect to the host, and the host can connect to UML, but
+  you cannot connect to any other machines, then you may need to enable
+  IP Masquerading on the host.  Usually this is only experienced when
+  using private IP addresses (192.168.x.x or 10.x.x.x) for host/UML
+  networking, rather than the public address space that your host is
+  connected to.  UML does not enable IP Masquerading, so you will need
+  to create a static rule to enable it:
+
+
+       host%
+       iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
+
+
+
+
+  Replace eth0 with the interface that you use to talk to the rest of
+  the world.
+
+
+  Documentation on IP Masquerading, and SNAT, can be found at
+  www.netfilter.org  <http://www.netfilter.org> .
+
+
+  If you can reach the local net, but not the outside Internet, then
+  that is usually a routing problem.  The UML needs a default route:
+
+
+       UML#
+       route add default gw gateway IP
+
+
+
+
+  The gateway IP can be any machine on the local net that knows how to
+  reach the outside world.  Usually, this is the host or the local net-
+  work's gateway.
+
+
+  Occasionally, we hear from someone who can reach some machines, but
+  not others on the same net, or who can reach some ports on other
+  machines, but not others.  These are usually caused by strange
+  firewalling somewhere between the UML and the other box.  You track
+  this down by running tcpdump on every interface the packets travel
+  over and see where they disappear.  When you find a machine that takes
+  the packets in, but does not send them onward, that's the culprit.
+
+
+
+  13.10.  I have no root and I want to scream
+
+  Thanks to Birgit Wahlich for telling me about this strange one.  It
+  turns out that there's a limit of six environment variables on the
+  kernel command line.  When that limit is reached or exceeded, argument
+  processing stops, which means that the 'root=' argument that UML
+  usually adds is not seen.  So, the filesystem has no idea what the
+  root device is, so it panics.
+
+
+  The fix is to put less stuff on the command line.  Glomming all your
+  setup variables into one is probably the best way to go.
+
+
+
+  13.11.  UML build conflict between ptrace.h and ucontext.h
+
+  On some older systems, /usr/include/asm/ptrace.h and
+  /usr/include/sys/ucontext.h define the same names.  So, when they're
+  included together, the defines from one completely mess up the parsing
+  of the other, producing errors like:
+       /usr/include/sys/ucontext.h:47: parse error before
+       `10'
+
+
+
+
+  plus a pile of warnings.
+
+
+  This is a libc botch, which has since been fixed, and I don't see any
+  way around it besides upgrading.
+
+
+
+  13.12.  The UML BogoMips is exactly half the host's BogoMips
+
+  On i386 kernels, there are two ways of running the loop that is used
+  to calculate the BogoMips rating, using the TSC if it's there or using
+  a one-instruction loop.  The TSC produces twice the BogoMips as the
+  loop.  UML uses the loop, since it has nothing resembling a TSC, and
+  will get almost exactly the same BogoMips as a host using the loop.
+  However, on a host with a TSC, its BogoMips will be double the loop
+  BogoMips, and therefore double the UML BogoMips.
+
+
+
+  13.13.  When you run UML, it immediately segfaults
+
+  If the host is configured with the 2G/2G address space split, that's
+  why.  See ``UML on 2G/2G hosts''  for the details on getting UML to
+  run on your host.
+
+
+
+  13.14.  xterms appear, then immediately disappear
+
+  If you're running an up to date kernel with an old release of
+  uml_utilities, the port-helper program will not work properly, so
+  xterms will exit straight after they appear. The solution is to
+  upgrade to the latest release of uml_utilities.  Usually this problem
+  occurs when you have installed a packaged release of UML then compiled
+  your own development kernel without upgrading the uml_utilities from
+  the source distribution.
+
+
+
+  13.15.  Any other panic, hang, or strange behavior
+
+  If you're seeing truly strange behavior, such as hangs or panics that
+  happen in random places, or you try running the debugger to see what's
+  happening and it acts strangely, then it could be a problem in the
+  host kernel.  If you're not running a stock Linus or -ac kernel, then
+  try that.  An early version of the preemption patch and a 2.4.10 SuSE
+  kernel have caused very strange problems in UML.
+
+
+  Otherwise, let me know about it.  Send a message to one of the UML
+  mailing lists - either the developer list - user-mode-linux-devel at
+  lists dot sourceforge dot net (subscription info) or the user list -
+  user-mode-linux-user at lists dot sourceforge do net (subscription
+  info), whichever you prefer.  Don't assume that everyone knows about
+  it and that a fix is imminent.
+
+
+  If you want to be super-helpful, read ``Diagnosing Problems'' and
+  follow the instructions contained therein.
+  14.  Diagnosing Problems
+
+
+  If you get UML to crash, hang, or otherwise misbehave, you should
+  report this on one of the project mailing lists, either the developer
+  list - user-mode-linux-devel at lists dot sourceforge dot net
+  (subscription info) or the user list - user-mode-linux-user at lists
+  dot sourceforge dot net (subscription info).  When you do, it is
+  likely that I will want more information.  So, it would be helpful to
+  read the stuff below, do whatever is applicable in your case, and
+  report the results to the list.
+
+
+  For any diagnosis, you're going to need to build a debugging kernel.
+  The binaries from this site aren't debuggable.  If you haven't done
+  this before, read about ``Compiling the kernel and modules''  and
+  ``Kernel debugging''  UML first.
+
+
+  14.1.  Case 1 : Normal kernel panics
+
+  The most common case is for a normal thread to panic.  To debug this,
+  you will need to run it under the debugger (add 'debug' to the command
+  line).  An xterm will start up with gdb running inside it.  Continue
+  it when it stops in start_kernel and make it crash.  Now ^C gdb and
+
+
+  If the panic was a "Kernel mode fault", then there will be a segv
+  frame on the stack and I'm going to want some more information.  The
+  stack might look something like this:
+
+
+       (UML gdb)  backtrace
+       #0  0x1009bf76 in __sigprocmask (how=1, set=0x5f347940, oset=0x0)
+           at ../sysdeps/unix/sysv/linux/sigprocmask.c:49
+       #1  0x10091411 in change_sig (signal=10, on=1) at process.c:218
+       #2  0x10094785 in timer_handler (sig=26) at time_kern.c:32
+       #3  0x1009bf38 in __restore ()
+           at ../sysdeps/unix/sysv/linux/i386/sigaction.c:125
+       #4  0x1009534c in segv (address=8, ip=268849158, is_write=2, is_user=0)
+           at trap_kern.c:66
+       #5  0x10095c04 in segv_handler (sig=11) at trap_user.c:285
+       #6  0x1009bf38 in __restore ()
+
+
+
+
+  I'm going to want to see the symbol and line information for the value
+  of ip in the segv frame.  In this case, you would do the following:
+
+
+       (UML gdb)  i sym 268849158
+
+
+
+
+  and
+
+
+       (UML gdb)  i line *268849158
+
+
+
+
+  The reason for this is the __restore frame right above the segv_han-
+  dler frame is hiding the frame that actually segfaulted.  So, I have
+  to get that information from the faulting ip.
+
+
+  14.2.  Case 2 : Tracing thread panics
+
+  The less common and more painful case is when the tracing thread
+  panics.  In this case, the kernel debugger will be useless because it
+  needs a healthy tracing thread in order to work.  The first thing to
+  do is get a backtrace from the tracing thread.  This is done by
+  figuring out what its pid is, firing up gdb, and attaching it to that
+  pid.  You can figure out the tracing thread pid by looking at the
+  first line of the console output, which will look like this:
+
+
+       tracing thread pid = 15851
+
+
+
+
+  or by running ps on the host and finding the line that looks like
+  this:
+
+
+       jdike 15851 4.5 0.4 132568 1104 pts/0 S 21:34 0:05 ./linux [(tracing thread)]
+
+
+
+
+  If the panic was 'segfault in signals', then follow the instructions
+  above for collecting information about the location of the seg fault.
+
+
+  If the tracing thread flaked out all by itself, then send that
+  backtrace in and wait for our crack debugging team to fix the problem.
+
+
+  14.3.  Case 3 : Tracing thread panics caused by other threads
+
+  However, there are cases where the misbehavior of another thread
+  caused the problem.  The most common panic of this type is:
+
+
+       wait_for_stop failed to wait for  <pid>  to stop with  <signal number>
+
+
+
+
+  In this case, you'll need to get a backtrace from the process men-
+  tioned in the panic, which is complicated by the fact that the kernel
+  debugger is defunct and without some fancy footwork, another gdb can't
+  attach to it.  So, this is how the fancy footwork goes:
+
+  In a shell:
+
+
+       host% kill -STOP pid
+
+
+
+
+  Run gdb on the tracing thread as described in case 2 and do:
+
+
+       (host gdb)  call detach(pid)
+
+
+  If you get a segfault, do it again.  It always works the second time.
+
+  Detach from the tracing thread and attach to that other thread:
+
+
+       (host gdb)  detach
+
+
+
+
+
+
+       (host gdb)  attach pid
+
+
+
+
+  If gdb hangs when attaching to that process, go back to a shell and
+  do:
+
+
+       host%
+       kill -CONT pid
+
+
+
+
+  And then get the backtrace:
+
+
+       (host gdb)  backtrace
+
+
+
+
+
+  14.4.  Case 4 : Hangs
+
+  Hangs seem to be fairly rare, but they sometimes happen.  When a hang
+  happens, we need a backtrace from the offending process.  Run the
+  kernel debugger as described in case 1 and get a backtrace.  If the
+  current process is not the idle thread, then send in the backtrace.
+  You can tell that it's the idle thread if the stack looks like this:
+
+
+       #0  0x100b1401 in __libc_nanosleep ()
+       #1  0x100a2885 in idle_sleep (secs=10) at time.c:122
+       #2  0x100a546f in do_idle () at process_kern.c:445
+       #3  0x100a5508 in cpu_idle () at process_kern.c:471
+       #4  0x100ec18f in start_kernel () at init/main.c:592
+       #5  0x100a3e10 in start_kernel_proc (unused=0x0) at um_arch.c:71
+       #6  0x100a383f in signal_tramp (arg=0x100a3dd8) at trap_user.c:50
+
+
+
+
+  If this is the case, then some other process is at fault, and went to
+  sleep when it shouldn't have.  Run ps on the host and figure out which
+  process should not have gone to sleep and stayed asleep.  Then attach
+  to it with gdb and get a backtrace as described in case 3.
+
+
+
+
+
+
+  15.  Thanks
+
+
+  A number of people have helped this project in various ways, and this
+  page gives recognition where recognition is due.
+
+
+  If you're listed here and you would prefer a real link on your name,
+  or no link at all, instead of the despammed email address pseudo-link,
+  let me know.
+
+
+  If you're not listed here and you think maybe you should be, please
+  let me know that as well.  I try to get everyone, but sometimes my
+  bookkeeping lapses and I forget about contributions.
+
+
+  15.1.  Code and Documentation
+
+  Rusty Russell <rusty at linuxcare.com.au>  -
+
+  o  wrote the  HOWTO <http://user-mode-
+     linux.sourceforge.net/UserModeLinux-HOWTO.html>
+
+  o  prodded me into making this project official and putting it on
+     SourceForge
+
+  o  came up with the way cool UML logo <http://user-mode-
+     linux.sourceforge.net/uml-small.png>
+
+  o  redid the config process
+
+
+  Peter Moulder <reiter at netspace.net.au>  - Fixed my config and build
+  processes, and added some useful code to the block driver
+
+
+  Bill Stearns <wstearns at pobox.com>  -
+
+  o  HOWTO updates
+
+  o  lots of bug reports
+
+  o  lots of testing
+
+  o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
+
+  o  wrote the mkrootfs script, which allows bootable filesystems of
+     RPM-based distributions to be cranked out
+
+  o  cranked out a large number of filesystems with said script
+
+
+  Jim Leu <jleu at mindspring.com>  - Wrote the virtual ethernet driver
+  and associated usermode tools
+
+  Lars Brinkhoff <http://lars.nocrew.org/>  - Contributed the ptrace
+  proxy from his own  project <http://a386.nocrew.org/> to allow easier
+  kernel debugging
+
+
+  Andrea Arcangeli <andrea at suse.de>  - Redid some of the early boot
+  code so that it would work on machines with Large File Support
+
+
+  Chris Emerson <http://www.chiark.greenend.org.uk/~cemerson/>  - Did
+  the first UML port to Linux/ppc
+
+
+  Harald Welte <laforge at gnumonks.org>  - Wrote the multicast
+  transport for the network driver
+
+
+  Jorgen Cederlof - Added special file support to hostfs
+
+
+  Greg Lonnon  <glonnon at ridgerun dot com>  - Changed the ubd driver
+  to allow it to layer a COW file on a shared read-only filesystem and
+  wrote the iomem emulation support
+
+
+  Henrik Nordstrom <http://hem.passagen.se/hno/>  - Provided a variety
+  of patches, fixes, and clues
+
+
+  Lennert Buytenhek - Contributed various patches, a rewrite of the
+  network driver, the first implementation of the mconsole driver, and
+  did the bulk of the work needed to get SMP working again.
+
+
+  Yon Uriarte - Fixed the TUN/TAP network backend while I slept.
+
+
+  Adam Heath - Made a bunch of nice cleanups to the initialization code,
+  plus various other small patches.
+
+
+  Matt Zimmerman - Matt volunteered to be the UML Debian maintainer and
+  is doing a real nice job of it.  He also noticed and fixed a number of
+  actually and potentially exploitable security holes in uml_net.  Plus
+  the occasional patch.  I like patches.
+
+
+  James McMechan - James seems to have taken over maintenance of the ubd
+  driver and is doing a nice job of it.
+
+
+  Chandan Kudige - wrote the umlgdb script which automates the reloading
+  of module symbols.
+
+
+  Steve Schmidtke - wrote the UML slirp transport and hostaudio drivers,
+  enabling UML processes to access audio devices on the host. He also
+  submitted patches for the slip transport and lots of other things.
+
+
+  David Coulson <http://davidcoulson.net>  -
+
+  o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
+     which is a great way of keeping the UML user community on top of
+     UML goings-on.
+
+  o  Site documentation and updates
+
+  o  Nifty little UML management daemon  UMLd
+     <http://uml.openconsultancy.com/umld/>
+
+  o  Lots of testing and bug reports
+
+
+
+
+  15.2.  Flushing out bugs
+
+
+
+  o  Yuri Pudgorodsky
+
+  o  Gerald Britton
+
+  o  Ian Wehrman
+
+  o  Gord Lamb
+
+  o  Eugene Koontz
+
+  o  John H. Hartman
+
+  o  Anders Karlsson
+
+  o  Daniel Phillips
+
+  o  John Fremlin
+
+  o  Rainer Burgstaller
+
+  o  James Stevenson
+
+  o  Matt Clay
+
+  o  Cliff Jefferies
+
+  o  Geoff Hoff
+
+  o  Lennert Buytenhek
+
+  o  Al Viro
+
+  o  Frank Klingenhoefer
+
+  o  Livio Baldini Soares
+
+  o  Jon Burgess
+
+  o  Petru Paler
+
+  o  Paul
+
+  o  Chris Reahard
+
+  o  Sverker Nilsson
+
+  o  Gong Su
+
+  o  johan verrept
+
+  o  Bjorn Eriksson
+
+  o  Lorenzo Allegrucci
+
+  o  Muli Ben-Yehuda
+
+  o  David Mansfield
+
+  o  Howard Goff
+
+  o  Mike Anderson
+
+  o  John Byrne
+
+  o  Sapan J. Batia
+
+  o  Iris Huang
+
+  o  Jan Hudec
+
+  o  Voluspa
+
+
+
+
+  15.3.  Buglets and clean-ups
+
+
+
+  o  Dave Zarzycki
+
+  o  Adam Lazur
+
+  o  Boria Feigin
+
+  o  Brian J. Murrell
+
+  o  JS
+
+  o  Roman Zippel
+
+  o  Wil Cooley
+
+  o  Ayelet Shemesh
+
+  o  Will Dyson
+
+  o  Sverker Nilsson
+
+  o  dvorak
+
+  o  v.naga srinivas
+
+  o  Shlomi Fish
+
+  o  Roger Binns
+
+  o  johan verrept
+
+  o  MrChuoi
+
+  o  Peter Cleve
+
+  o  Vincent Guffens
+
+  o  Nathan Scott
+
+  o  Patrick Caulfield
+
+  o  jbearce
+
+  o  Catalin Marinas
+
+  o  Shane Spencer
+
+  o  Zou Min
+
+
+  o  Ryan Boder
+
+  o  Lorenzo Colitti
+
+  o  Gwendal Grignou
+
+  o  Andre' Breiler
+
+  o  Tsutomu Yasuda
+
+
+
+  15.4.  Case Studies
+
+
+  o  Jon Wright
+
+  o  William McEwan
+
+  o  Michael Richardson
+
+
+
+  15.5.  Other contributions
+
+
+  Bill Carr <Bill.Carr at compaq.com>  made the Red Hat mkrootfs script
+  work with RH 6.2.
+
+  Michael Jennings <mikejen at hevanet.com>  sent in some material which
+  is now gracing the top of the  index  page <http://user-mode-
+  linux.sourceforge.net/>  of this site.
+
+  SGI <http://www.sgi.com>  (and more specifically Ralf Baechle <ralf at
+  uni-koblenz.de> ) gave me an account on oss.sgi.com
+  <http://www.oss.sgi.com> .  The bandwidth there made it possible to
+  produce most of the filesystems available on the project download
+  page.
+
+  Laurent Bonnaud <Laurent.Bonnaud at inpg.fr>  took the old grotty
+  Debian filesystem that I've been distributing and updated it to 2.2.
+  It is now available by itself here.
+
+  Rik van Riel gave me some ftp space on ftp.nl.linux.org so I can make
+  releases even when Sourceforge is broken.
+
+  Rodrigo de Castro looked at my broken pte code and told me what was
+  wrong with it, letting me fix a long-standing (several weeks) and
+  serious set of bugs.
+
+  Chris Reahard built a specialized root filesystem for running a DNS
+  server jailed inside UML.  It's available from the download
+  <http://user-mode-linux.sourceforge.net/dl-sf.html>  page in the Jail
+  Filesystems section.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Documentation/virtual/index.rst b/Documentation/virtual/index.rst
deleted file mode 100644 (file)
index 062ffb5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============================
-Linux Virtualization Support
-============================
-
-.. toctree::
-   :maxdepth: 2
-
-   kvm/index
-   paravirt_ops
-
-.. only:: html and subproject
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/virtual/kvm/amd-memory-encryption.rst b/Documentation/virtual/kvm/amd-memory-encryption.rst
deleted file mode 100644 (file)
index d18c97b..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-======================================
-Secure Encrypted Virtualization (SEV)
-======================================
-
-Overview
-========
-
-Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
-
-SEV is an extension to the AMD-V architecture which supports running
-virtual machines (VMs) under the control of a hypervisor. When enabled,
-the memory contents of a VM will be transparently encrypted with a key
-unique to that VM.
-
-The hypervisor can determine the SEV support through the CPUID
-instruction. The CPUID function 0x8000001f reports information related
-to SEV::
-
-       0x8000001f[eax]:
-                       Bit[1]  indicates support for SEV
-           ...
-                 [ecx]:
-                       Bits[31:0]  Number of encrypted guests supported simultaneously
-
-If support for SEV is present, MSR 0xc001_0010 (MSR_K8_SYSCFG) and MSR 0xc001_0015
-(MSR_K7_HWCR) can be used to determine if it can be enabled::
-
-       0xc001_0010:
-               Bit[23]    1 = memory encryption can be enabled
-                          0 = memory encryption can not be enabled
-
-       0xc001_0015:
-               Bit[0]     1 = memory encryption can be enabled
-                          0 = memory encryption can not be enabled
-
-When SEV support is available, it can be enabled in a specific VM by
-setting the SEV bit before executing VMRUN.::
-
-       VMCB[0x90]:
-               Bit[1]      1 = SEV is enabled
-                           0 = SEV is disabled
-
-SEV hardware uses ASIDs to associate a memory encryption key with a VM.
-Hence, the ASID for the SEV-enabled guests must be from 1 to a maximum value
-defined in the CPUID 0x8000001f[ecx] field.
-
-SEV Key Management
-==================
-
-The SEV guest key management is handled by a separate processor called the AMD
-Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a secure
-key management interface to perform common hypervisor activities such as
-encrypting bootstrap code, snapshot, migrating and debugging the guest. For more
-information, see the SEV Key Management spec [api-spec]_
-
-KVM implements the following commands to support common lifecycle events of SEV
-guests, such as launching, running, snapshotting, migrating and decommissioning.
-
-1. KVM_SEV_INIT
----------------
-
-The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform
-context. In a typical workflow, this command should be the first command issued.
-
-Returns: 0 on success, -negative on error
-
-2. KVM_SEV_LAUNCH_START
------------------------
-
-The KVM_SEV_LAUNCH_START command is used for creating the memory encryption
-context. To create the encryption context, user must provide a guest policy,
-the owner's public Diffie-Hellman (PDH) key and session information.
-
-Parameters: struct  kvm_sev_launch_start (in/out)
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_launch_start {
-                __u32 handle;           /* if zero then firmware creates a new handle */
-                __u32 policy;           /* guest's policy */
-
-                __u64 dh_uaddr;         /* userspace address pointing to the guest owner's PDH key */
-                __u32 dh_len;
-
-                __u64 session_addr;     /* userspace address which points to the guest session information */
-                __u32 session_len;
-        };
-
-On success, the 'handle' field contains a new handle and on error, a negative value.
-
-For more details, see SEV spec Section 6.2.
-
-3. KVM_SEV_LAUNCH_UPDATE_DATA
------------------------------
-
-The KVM_SEV_LAUNCH_UPDATE_DATA is used for encrypting a memory region. It also
-calculates a measurement of the memory contents. The measurement is a signature
-of the memory contents that can be sent to the guest owner as an attestation
-that the memory was encrypted correctly by the firmware.
-
-Parameters (in): struct  kvm_sev_launch_update_data
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_launch_update {
-                __u64 uaddr;    /* userspace address to be encrypted (must be 16-byte aligned) */
-                __u32 len;      /* length of the data to be encrypted (must be 16-byte aligned) */
-        };
-
-For more details, see SEV spec Section 6.3.
-
-4. KVM_SEV_LAUNCH_MEASURE
--------------------------
-
-The KVM_SEV_LAUNCH_MEASURE command is used to retrieve the measurement of the
-data encrypted by the KVM_SEV_LAUNCH_UPDATE_DATA command. The guest owner may
-wait to provide the guest with confidential information until it can verify the
-measurement. Since the guest owner knows the initial contents of the guest at
-boot, the measurement can be verified by comparing it to what the guest owner
-expects.
-
-Parameters (in): struct  kvm_sev_launch_measure
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_launch_measure {
-                __u64 uaddr;    /* where to copy the measurement */
-                __u32 len;      /* length of measurement blob */
-        };
-
-For more details on the measurement verification flow, see SEV spec Section 6.4.
-
-5. KVM_SEV_LAUNCH_FINISH
-------------------------
-
-After completion of the launch flow, the KVM_SEV_LAUNCH_FINISH command can be
-issued to make the guest ready for the execution.
-
-Returns: 0 on success, -negative on error
-
-6. KVM_SEV_GUEST_STATUS
------------------------
-
-The KVM_SEV_GUEST_STATUS command is used to retrieve status information about a
-SEV-enabled guest.
-
-Parameters (out): struct kvm_sev_guest_status
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_guest_status {
-                __u32 handle;   /* guest handle */
-                __u32 policy;   /* guest policy */
-                __u8 state;     /* guest state (see enum below) */
-        };
-
-SEV guest state:
-
-::
-
-        enum {
-        SEV_STATE_INVALID = 0;
-        SEV_STATE_LAUNCHING,    /* guest is currently being launched */
-        SEV_STATE_SECRET,       /* guest is being launched and ready to accept the ciphertext data */
-        SEV_STATE_RUNNING,      /* guest is fully launched and running */
-        SEV_STATE_RECEIVING,    /* guest is being migrated in from another SEV machine */
-        SEV_STATE_SENDING       /* guest is getting migrated out to another SEV machine */
-        };
-
-7. KVM_SEV_DBG_DECRYPT
-----------------------
-
-The KVM_SEV_DEBUG_DECRYPT command can be used by the hypervisor to request the
-firmware to decrypt the data at the given memory region.
-
-Parameters (in): struct kvm_sev_dbg
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_dbg {
-                __u64 src_uaddr;        /* userspace address of data to decrypt */
-                __u64 dst_uaddr;        /* userspace address of destination */
-                __u32 len;              /* length of memory region to decrypt */
-        };
-
-The command returns an error if the guest policy does not allow debugging.
-
-8. KVM_SEV_DBG_ENCRYPT
-----------------------
-
-The KVM_SEV_DEBUG_ENCRYPT command can be used by the hypervisor to request the
-firmware to encrypt the data at the given memory region.
-
-Parameters (in): struct kvm_sev_dbg
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_dbg {
-                __u64 src_uaddr;        /* userspace address of data to encrypt */
-                __u64 dst_uaddr;        /* userspace address of destination */
-                __u32 len;              /* length of memory region to encrypt */
-        };
-
-The command returns an error if the guest policy does not allow debugging.
-
-9. KVM_SEV_LAUNCH_SECRET
-------------------------
-
-The KVM_SEV_LAUNCH_SECRET command can be used by the hypervisor to inject secret
-data after the measurement has been validated by the guest owner.
-
-Parameters (in): struct kvm_sev_launch_secret
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_launch_secret {
-                __u64 hdr_uaddr;        /* userspace address containing the packet header */
-                __u32 hdr_len;
-
-                __u64 guest_uaddr;      /* the guest memory region where the secret should be injected */
-                __u32 guest_len;
-
-                __u64 trans_uaddr;      /* the hypervisor memory region which contains the secret */
-                __u32 trans_len;
-        };
-
-References
-==========
-
-
-See [white-paper]_, [api-spec]_, [amd-apm]_ and [kvm-forum]_ for more info.
-
-.. [white-paper] http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
-.. [api-spec] http://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
-.. [amd-apm] http://support.amd.com/TechDocs/24593.pdf (section 15.34)
-.. [kvm-forum]  http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
deleted file mode 100644 (file)
index e54a3f5..0000000
+++ /dev/null
@@ -1,5296 +0,0 @@
-The Definitive KVM (Kernel-based Virtual Machine) API Documentation
-===================================================================
-
-1. General description
-----------------------
-
-The kvm API is a set of ioctls that are issued to control various aspects
-of a virtual machine.  The ioctls belong to three classes:
-
- - System ioctls: These query and set global attributes which affect the
-   whole kvm subsystem.  In addition a system ioctl is used to create
-   virtual machines.
-
- - VM ioctls: These query and set attributes that affect an entire virtual
-   machine, for example memory layout.  In addition a VM ioctl is used to
-   create virtual cpus (vcpus) and devices.
-
-   VM ioctls must be issued from the same process (address space) that was
-   used to create the VM.
-
- - vcpu ioctls: These query and set attributes that control the operation
-   of a single virtual cpu.
-
-   vcpu ioctls should be issued from the same thread that was used to create
-   the vcpu, except for asynchronous vcpu ioctl that are marked as such in
-   the documentation.  Otherwise, the first ioctl after switching threads
-   could see a performance impact.
-
- - device ioctls: These query and set attributes that control the operation
-   of a single device.
-
-   device ioctls must be issued from the same process (address space) that
-   was used to create the VM.
-
-2. File descriptors
--------------------
-
-The kvm API is centered around file descriptors.  An initial
-open("/dev/kvm") obtains a handle to the kvm subsystem; this handle
-can be used to issue system ioctls.  A KVM_CREATE_VM ioctl on this
-handle will create a VM file descriptor which can be used to issue VM
-ioctls.  A KVM_CREATE_VCPU or KVM_CREATE_DEVICE ioctl on a VM fd will
-create a virtual cpu or device and return a file descriptor pointing to
-the new resource.  Finally, ioctls on a vcpu or device fd can be used
-to control the vcpu or device.  For vcpus, this includes the important
-task of actually running guest code.
-
-In general file descriptors can be migrated among processes by means
-of fork() and the SCM_RIGHTS facility of unix domain socket.  These
-kinds of tricks are explicitly not supported by kvm.  While they will
-not cause harm to the host, their actual behavior is not guaranteed by
-the API.  See "General description" for details on the ioctl usage
-model that is supported by KVM.
-
-It is important to note that althought VM ioctls may only be issued from
-the process that created the VM, a VM's lifecycle is associated with its
-file descriptor, not its creator (process).  In other words, the VM and
-its resources, *including the associated address space*, are not freed
-until the last reference to the VM's file descriptor has been released.
-For example, if fork() is issued after ioctl(KVM_CREATE_VM), the VM will
-not be freed until both the parent (original) process and its child have
-put their references to the VM's file descriptor.
-
-Because a VM's resources are not freed until the last reference to its
-file descriptor is released, creating additional references to a VM via
-via fork(), dup(), etc... without careful consideration is strongly
-discouraged and may have unwanted side effects, e.g. memory allocated
-by and on behalf of the VM's process may not be freed/unaccounted when
-the VM is shut down.
-
-
-3. Extensions
--------------
-
-As of Linux 2.6.22, the KVM ABI has been stabilized: no backward
-incompatible change are allowed.  However, there is an extension
-facility that allows backward-compatible extensions to the API to be
-queried and used.
-
-The extension mechanism is not based on the Linux version number.
-Instead, kvm defines extension identifiers and a facility to query
-whether a particular extension identifier is available.  If it is, a
-set of ioctls is available for application use.
-
-
-4. API description
-------------------
-
-This section describes ioctls that can be used to control kvm guests.
-For each ioctl, the following information is provided along with a
-description:
-
-  Capability: which KVM extension provides this ioctl.  Can be 'basic',
-      which means that is will be provided by any kernel that supports
-      API version 12 (see section 4.1), a KVM_CAP_xyz constant, which
-      means availability needs to be checked with KVM_CHECK_EXTENSION
-      (see section 4.4), or 'none' which means that while not all kernels
-      support this ioctl, there's no capability bit to check its
-      availability: for kernels that don't support the ioctl,
-      the ioctl returns -ENOTTY.
-
-  Architectures: which instruction set architectures provide this ioctl.
-      x86 includes both i386 and x86_64.
-
-  Type: system, vm, or vcpu.
-
-  Parameters: what parameters are accepted by the ioctl.
-
-  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
-      are not detailed, but errors with specific meanings are.
-
-
-4.1 KVM_GET_API_VERSION
-
-Capability: basic
-Architectures: all
-Type: system ioctl
-Parameters: none
-Returns: the constant KVM_API_VERSION (=12)
-
-This identifies the API version as the stable kvm API. It is not
-expected that this number will change.  However, Linux 2.6.20 and
-2.6.21 report earlier versions; these are not documented and not
-supported.  Applications should refuse to run if KVM_GET_API_VERSION
-returns a value other than 12.  If this check passes, all ioctls
-described as 'basic' will be available.
-
-
-4.2 KVM_CREATE_VM
-
-Capability: basic
-Architectures: all
-Type: system ioctl
-Parameters: machine type identifier (KVM_VM_*)
-Returns: a VM fd that can be used to control the new virtual machine.
-
-The new VM has no virtual cpus and no memory.
-You probably want to use 0 as machine type.
-
-In order to create user controlled virtual machines on S390, check
-KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
-privileged user (CAP_SYS_ADMIN).
-
-To use hardware assisted virtualization on MIPS (VZ ASE) rather than
-the default trap & emulate implementation (which changes the virtual
-memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
-flag KVM_VM_MIPS_VZ.
-
-
-On arm64, the physical address size for a VM (IPA Size limit) is limited
-to 40bits by default. The limit can be configured if the host supports the
-extension KVM_CAP_ARM_VM_IPA_SIZE. When supported, use
-KVM_VM_TYPE_ARM_IPA_SIZE(IPA_Bits) to set the size in the machine type
-identifier, where IPA_Bits is the maximum width of any physical
-address used by the VM. The IPA_Bits is encoded in bits[7-0] of the
-machine type identifier.
-
-e.g, to configure a guest to use 48bit physical address size :
-
-    vm_fd = ioctl(dev_fd, KVM_CREATE_VM, KVM_VM_TYPE_ARM_IPA_SIZE(48));
-
-The requested size (IPA_Bits) must be :
-  0 - Implies default size, 40bits (for backward compatibility)
-
-  or
-
-  N - Implies N bits, where N is a positive integer such that,
-      32 <= N <= Host_IPA_Limit
-
-Host_IPA_Limit is the maximum possible value for IPA_Bits on the host and
-is dependent on the CPU capability and the kernel configuration. The limit can
-be retrieved using KVM_CAP_ARM_VM_IPA_SIZE of the KVM_CHECK_EXTENSION
-ioctl() at run-time.
-
-Please note that configuring the IPA size does not affect the capability
-exposed by the guest CPUs in ID_AA64MMFR0_EL1[PARange]. It only affects
-size of the address translated by the stage2 level (guest physical to
-host physical address translations).
-
-
-4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST
-
-Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST
-Architectures: x86
-Type: system ioctl
-Parameters: struct kvm_msr_list (in/out)
-Returns: 0 on success; -1 on error
-Errors:
-  EFAULT:    the msr index list cannot be read from or written to
-  E2BIG:     the msr index list is to be to fit in the array specified by
-             the user.
-
-struct kvm_msr_list {
-       __u32 nmsrs; /* number of msrs in entries */
-       __u32 indices[0];
-};
-
-The user fills in the size of the indices array in nmsrs, and in return
-kvm adjusts nmsrs to reflect the actual number of msrs and fills in the
-indices array with their numbers.
-
-KVM_GET_MSR_INDEX_LIST returns the guest msrs that are supported.  The list
-varies by kvm version and host processor, but does not change otherwise.
-
-Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are
-not returned in the MSR list, as different vcpus can have a different number
-of banks, as set via the KVM_X86_SETUP_MCE ioctl.
-
-KVM_GET_MSR_FEATURE_INDEX_LIST returns the list of MSRs that can be passed
-to the KVM_GET_MSRS system ioctl.  This lets userspace probe host capabilities
-and processor features that are exposed via MSRs (e.g., VMX capabilities).
-This list also varies by kvm version and host processor, but does not change
-otherwise.
-
-
-4.4 KVM_CHECK_EXTENSION
-
-Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl
-Architectures: all
-Type: system ioctl, vm ioctl
-Parameters: extension identifier (KVM_CAP_*)
-Returns: 0 if unsupported; 1 (or some other positive integer) if supported
-
-The API allows the application to query about extensions to the core
-kvm API.  Userspace passes an extension identifier (an integer) and
-receives an integer that describes the extension availability.
-Generally 0 means no and 1 means yes, but some extensions may report
-additional information in the integer return value.
-
-Based on their initialization different VMs may have different capabilities.
-It is thus encouraged to use the vm ioctl to query for capabilities (available
-with KVM_CAP_CHECK_EXTENSION_VM on the vm fd)
-
-4.5 KVM_GET_VCPU_MMAP_SIZE
-
-Capability: basic
-Architectures: all
-Type: system ioctl
-Parameters: none
-Returns: size of vcpu mmap area, in bytes
-
-The KVM_RUN ioctl (cf.) communicates with userspace via a shared
-memory region.  This ioctl returns the size of that region.  See the
-KVM_RUN documentation for details.
-
-
-4.6 KVM_SET_MEMORY_REGION
-
-Capability: basic
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_memory_region (in)
-Returns: 0 on success, -1 on error
-
-This ioctl is obsolete and has been removed.
-
-
-4.7 KVM_CREATE_VCPU
-
-Capability: basic
-Architectures: all
-Type: vm ioctl
-Parameters: vcpu id (apic id on x86)
-Returns: vcpu fd on success, -1 on error
-
-This API adds a vcpu to a virtual machine. No more than max_vcpus may be added.
-The vcpu id is an integer in the range [0, max_vcpu_id).
-
-The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of
-the KVM_CHECK_EXTENSION ioctl() at run-time.
-The maximum possible value for max_vcpus can be retrieved using the
-KVM_CAP_MAX_VCPUS of the KVM_CHECK_EXTENSION ioctl() at run-time.
-
-If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
-cpus max.
-If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is
-same as the value returned from KVM_CAP_NR_VCPUS.
-
-The maximum possible value for max_vcpu_id can be retrieved using the
-KVM_CAP_MAX_VCPU_ID of the KVM_CHECK_EXTENSION ioctl() at run-time.
-
-If the KVM_CAP_MAX_VCPU_ID does not exist, you should assume that max_vcpu_id
-is the same as the value returned from KVM_CAP_MAX_VCPUS.
-
-On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
-threads in one or more virtual CPU cores.  (This is because the
-hardware requires all the hardware threads in a CPU core to be in the
-same partition.)  The KVM_CAP_PPC_SMT capability indicates the number
-of vcpus per virtual core (vcore).  The vcore id is obtained by
-dividing the vcpu id by the number of vcpus per vcore.  The vcpus in a
-given vcore will always be in the same physical core as each other
-(though that might be a different physical core from time to time).
-Userspace can control the threading (SMT) mode of the guest by its
-allocation of vcpu ids.  For example, if userspace wants
-single-threaded guest vcpus, it should make all vcpu ids be a multiple
-of the number of vcpus per vcore.
-
-For virtual cpus that have been created with S390 user controlled virtual
-machines, the resulting vcpu fd can be memory mapped at page offset
-KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
-cpu's hardware control block.
-
-
-4.8 KVM_GET_DIRTY_LOG (vm ioctl)
-
-Capability: basic
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_dirty_log (in/out)
-Returns: 0 on success, -1 on error
-
-/* for KVM_GET_DIRTY_LOG */
-struct kvm_dirty_log {
-       __u32 slot;
-       __u32 padding;
-       union {
-               void __user *dirty_bitmap; /* one bit per page */
-               __u64 padding;
-       };
-};
-
-Given a memory slot, return a bitmap containing any pages dirtied
-since the last call to this ioctl.  Bit 0 is the first page in the
-memory slot.  Ensure the entire structure is cleared to avoid padding
-issues.
-
-If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 specifies
-the address space for which you want to return the dirty bitmap.
-They must be less than the value that KVM_CHECK_EXTENSION returns for
-the KVM_CAP_MULTI_ADDRESS_SPACE capability.
-
-The bits in the dirty bitmap are cleared before the ioctl returns, unless
-KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is enabled.  For more information,
-see the description of the capability.
-
-4.9 KVM_SET_MEMORY_ALIAS
-
-Capability: basic
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_memory_alias (in)
-Returns: 0 (success), -1 (error)
-
-This ioctl is obsolete and has been removed.
-
-
-4.10 KVM_RUN
-
-Capability: basic
-Architectures: all
-Type: vcpu ioctl
-Parameters: none
-Returns: 0 on success, -1 on error
-Errors:
-  EINTR:     an unmasked signal is pending
-
-This ioctl is used to run a guest virtual cpu.  While there are no
-explicit parameters, there is an implicit parameter block that can be
-obtained by mmap()ing the vcpu fd at offset 0, with the size given by
-KVM_GET_VCPU_MMAP_SIZE.  The parameter block is formatted as a 'struct
-kvm_run' (see below).
-
-
-4.11 KVM_GET_REGS
-
-Capability: basic
-Architectures: all except ARM, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_regs (out)
-Returns: 0 on success, -1 on error
-
-Reads the general purpose registers from the vcpu.
-
-/* x86 */
-struct kvm_regs {
-       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
-       __u64 rax, rbx, rcx, rdx;
-       __u64 rsi, rdi, rsp, rbp;
-       __u64 r8,  r9,  r10, r11;
-       __u64 r12, r13, r14, r15;
-       __u64 rip, rflags;
-};
-
-/* mips */
-struct kvm_regs {
-       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
-       __u64 gpr[32];
-       __u64 hi;
-       __u64 lo;
-       __u64 pc;
-};
-
-
-4.12 KVM_SET_REGS
-
-Capability: basic
-Architectures: all except ARM, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_regs (in)
-Returns: 0 on success, -1 on error
-
-Writes the general purpose registers into the vcpu.
-
-See KVM_GET_REGS for the data structure.
-
-
-4.13 KVM_GET_SREGS
-
-Capability: basic
-Architectures: x86, ppc
-Type: vcpu ioctl
-Parameters: struct kvm_sregs (out)
-Returns: 0 on success, -1 on error
-
-Reads special registers from the vcpu.
-
-/* x86 */
-struct kvm_sregs {
-       struct kvm_segment cs, ds, es, fs, gs, ss;
-       struct kvm_segment tr, ldt;
-       struct kvm_dtable gdt, idt;
-       __u64 cr0, cr2, cr3, cr4, cr8;
-       __u64 efer;
-       __u64 apic_base;
-       __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
-};
-
-/* ppc -- see arch/powerpc/include/uapi/asm/kvm.h */
-
-interrupt_bitmap is a bitmap of pending external interrupts.  At most
-one bit may be set.  This interrupt has been acknowledged by the APIC
-but not yet injected into the cpu core.
-
-
-4.14 KVM_SET_SREGS
-
-Capability: basic
-Architectures: x86, ppc
-Type: vcpu ioctl
-Parameters: struct kvm_sregs (in)
-Returns: 0 on success, -1 on error
-
-Writes special registers into the vcpu.  See KVM_GET_SREGS for the
-data structures.
-
-
-4.15 KVM_TRANSLATE
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_translation (in/out)
-Returns: 0 on success, -1 on error
-
-Translates a virtual address according to the vcpu's current address
-translation mode.
-
-struct kvm_translation {
-       /* in */
-       __u64 linear_address;
-
-       /* out */
-       __u64 physical_address;
-       __u8  valid;
-       __u8  writeable;
-       __u8  usermode;
-       __u8  pad[5];
-};
-
-
-4.16 KVM_INTERRUPT
-
-Capability: basic
-Architectures: x86, ppc, mips
-Type: vcpu ioctl
-Parameters: struct kvm_interrupt (in)
-Returns: 0 on success, negative on failure.
-
-Queues a hardware interrupt vector to be injected.
-
-/* for KVM_INTERRUPT */
-struct kvm_interrupt {
-       /* in */
-       __u32 irq;
-};
-
-X86:
-
-Returns: 0 on success,
-        -EEXIST if an interrupt is already enqueued
-        -EINVAL the the irq number is invalid
-        -ENXIO if the PIC is in the kernel
-        -EFAULT if the pointer is invalid
-
-Note 'irq' is an interrupt vector, not an interrupt pin or line. This
-ioctl is useful if the in-kernel PIC is not used.
-
-PPC:
-
-Queues an external interrupt to be injected. This ioctl is overleaded
-with 3 different irq values:
-
-a) KVM_INTERRUPT_SET
-
-  This injects an edge type external interrupt into the guest once it's ready
-  to receive interrupts. When injected, the interrupt is done.
-
-b) KVM_INTERRUPT_UNSET
-
-  This unsets any pending interrupt.
-
-  Only available with KVM_CAP_PPC_UNSET_IRQ.
-
-c) KVM_INTERRUPT_SET_LEVEL
-
-  This injects a level type external interrupt into the guest context. The
-  interrupt stays pending until a specific ioctl with KVM_INTERRUPT_UNSET
-  is triggered.
-
-  Only available with KVM_CAP_PPC_IRQ_LEVEL.
-
-Note that any value for 'irq' other than the ones stated above is invalid
-and incurs unexpected behavior.
-
-This is an asynchronous vcpu ioctl and can be invoked from any thread.
-
-MIPS:
-
-Queues an external interrupt to be injected into the virtual CPU. A negative
-interrupt number dequeues the interrupt.
-
-This is an asynchronous vcpu ioctl and can be invoked from any thread.
-
-
-4.17 KVM_DEBUG_GUEST
-
-Capability: basic
-Architectures: none
-Type: vcpu ioctl
-Parameters: none)
-Returns: -1 on error
-
-Support for this has been removed.  Use KVM_SET_GUEST_DEBUG instead.
-
-
-4.18 KVM_GET_MSRS
-
-Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system)
-Architectures: x86
-Type: system ioctl, vcpu ioctl
-Parameters: struct kvm_msrs (in/out)
-Returns: number of msrs successfully returned;
-        -1 on error
-
-When used as a system ioctl:
-Reads the values of MSR-based features that are available for the VM.  This
-is similar to KVM_GET_SUPPORTED_CPUID, but it returns MSR indices and values.
-The list of msr-based features can be obtained using KVM_GET_MSR_FEATURE_INDEX_LIST
-in a system ioctl.
-
-When used as a vcpu ioctl:
-Reads model-specific registers from the vcpu.  Supported msr indices can
-be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl.
-
-struct kvm_msrs {
-       __u32 nmsrs; /* number of msrs in entries */
-       __u32 pad;
-
-       struct kvm_msr_entry entries[0];
-};
-
-struct kvm_msr_entry {
-       __u32 index;
-       __u32 reserved;
-       __u64 data;
-};
-
-Application code should set the 'nmsrs' member (which indicates the
-size of the entries array) and the 'index' member of each array entry.
-kvm will fill in the 'data' member.
-
-
-4.19 KVM_SET_MSRS
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_msrs (in)
-Returns: 0 on success, -1 on error
-
-Writes model-specific registers to the vcpu.  See KVM_GET_MSRS for the
-data structures.
-
-Application code should set the 'nmsrs' member (which indicates the
-size of the entries array), and the 'index' and 'data' members of each
-array entry.
-
-
-4.20 KVM_SET_CPUID
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_cpuid (in)
-Returns: 0 on success, -1 on error
-
-Defines the vcpu responses to the cpuid instruction.  Applications
-should use the KVM_SET_CPUID2 ioctl if available.
-
-
-struct kvm_cpuid_entry {
-       __u32 function;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding;
-};
-
-/* for KVM_SET_CPUID */
-struct kvm_cpuid {
-       __u32 nent;
-       __u32 padding;
-       struct kvm_cpuid_entry entries[0];
-};
-
-
-4.21 KVM_SET_SIGNAL_MASK
-
-Capability: basic
-Architectures: all
-Type: vcpu ioctl
-Parameters: struct kvm_signal_mask (in)
-Returns: 0 on success, -1 on error
-
-Defines which signals are blocked during execution of KVM_RUN.  This
-signal mask temporarily overrides the threads signal mask.  Any
-unblocked signal received (except SIGKILL and SIGSTOP, which retain
-their traditional behaviour) will cause KVM_RUN to return with -EINTR.
-
-Note the signal will only be delivered if not blocked by the original
-signal mask.
-
-/* for KVM_SET_SIGNAL_MASK */
-struct kvm_signal_mask {
-       __u32 len;
-       __u8  sigset[0];
-};
-
-
-4.22 KVM_GET_FPU
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_fpu (out)
-Returns: 0 on success, -1 on error
-
-Reads the floating point state from the vcpu.
-
-/* for KVM_GET_FPU and KVM_SET_FPU */
-struct kvm_fpu {
-       __u8  fpr[8][16];
-       __u16 fcw;
-       __u16 fsw;
-       __u8  ftwx;  /* in fxsave format */
-       __u8  pad1;
-       __u16 last_opcode;
-       __u64 last_ip;
-       __u64 last_dp;
-       __u8  xmm[16][16];
-       __u32 mxcsr;
-       __u32 pad2;
-};
-
-
-4.23 KVM_SET_FPU
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_fpu (in)
-Returns: 0 on success, -1 on error
-
-Writes the floating point state to the vcpu.
-
-/* for KVM_GET_FPU and KVM_SET_FPU */
-struct kvm_fpu {
-       __u8  fpr[8][16];
-       __u16 fcw;
-       __u16 fsw;
-       __u8  ftwx;  /* in fxsave format */
-       __u8  pad1;
-       __u16 last_opcode;
-       __u64 last_ip;
-       __u64 last_dp;
-       __u8  xmm[16][16];
-       __u32 mxcsr;
-       __u32 pad2;
-};
-
-
-4.24 KVM_CREATE_IRQCHIP
-
-Capability: KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390)
-Architectures: x86, ARM, arm64, s390
-Type: vm ioctl
-Parameters: none
-Returns: 0 on success, -1 on error
-
-Creates an interrupt controller model in the kernel.
-On x86, creates a virtual ioapic, a virtual PIC (two PICs, nested), and sets up
-future vcpus to have a local APIC.  IRQ routing for GSIs 0-15 is set to both
-PIC and IOAPIC; GSI 16-23 only go to the IOAPIC.
-On ARM/arm64, a GICv2 is created. Any other GIC versions require the usage of
-KVM_CREATE_DEVICE, which also supports creating a GICv2.  Using
-KVM_CREATE_DEVICE is preferred over KVM_CREATE_IRQCHIP for GICv2.
-On s390, a dummy irq routing table is created.
-
-Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled
-before KVM_CREATE_IRQCHIP can be used.
-
-
-4.25 KVM_IRQ_LINE
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86, arm, arm64
-Type: vm ioctl
-Parameters: struct kvm_irq_level
-Returns: 0 on success, -1 on error
-
-Sets the level of a GSI input to the interrupt controller model in the kernel.
-On some architectures it is required that an interrupt controller model has
-been previously created with KVM_CREATE_IRQCHIP.  Note that edge-triggered
-interrupts require the level to be set to 1 and then back to 0.
-
-On real hardware, interrupt pins can be active-low or active-high.  This
-does not matter for the level field of struct kvm_irq_level: 1 always
-means active (asserted), 0 means inactive (deasserted).
-
-x86 allows the operating system to program the interrupt polarity
-(active-low/active-high) for level-triggered interrupts, and KVM used
-to consider the polarity.  However, due to bitrot in the handling of
-active-low interrupts, the above convention is now valid on x86 too.
-This is signaled by KVM_CAP_X86_IOAPIC_POLARITY_IGNORED.  Userspace
-should not present interrupts to the guest as active-low unless this
-capability is present (or unless it is not using the in-kernel irqchip,
-of course).
-
-
-ARM/arm64 can signal an interrupt either at the CPU level, or at the
-in-kernel irqchip (GIC), and for in-kernel irqchip can tell the GIC to
-use PPIs designated for specific cpus.  The irq field is interpreted
-like this:
-
-  bits:  | 31 ... 24 | 23  ... 16 | 15    ...    0 |
-  field: | irq_type  | vcpu_index |     irq_id     |
-
-The irq_type field has the following values:
-- irq_type[0]: out-of-kernel GIC: irq_id 0 is IRQ, irq_id 1 is FIQ
-- irq_type[1]: in-kernel GIC: SPI, irq_id between 32 and 1019 (incl.)
-               (the vcpu_index field is ignored)
-- irq_type[2]: in-kernel GIC: PPI, irq_id between 16 and 31 (incl.)
-
-(The irq_id field thus corresponds nicely to the IRQ ID in the ARM GIC specs)
-
-In both cases, level is used to assert/deassert the line.
-
-struct kvm_irq_level {
-       union {
-               __u32 irq;     /* GSI */
-               __s32 status;  /* not used for KVM_IRQ_LEVEL */
-       };
-       __u32 level;           /* 0 or 1 */
-};
-
-
-4.26 KVM_GET_IRQCHIP
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_irqchip (in/out)
-Returns: 0 on success, -1 on error
-
-Reads the state of a kernel interrupt controller created with
-KVM_CREATE_IRQCHIP into a buffer provided by the caller.
-
-struct kvm_irqchip {
-       __u32 chip_id;  /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
-       __u32 pad;
-        union {
-               char dummy[512];  /* reserving space */
-               struct kvm_pic_state pic;
-               struct kvm_ioapic_state ioapic;
-       } chip;
-};
-
-
-4.27 KVM_SET_IRQCHIP
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_irqchip (in)
-Returns: 0 on success, -1 on error
-
-Sets the state of a kernel interrupt controller created with
-KVM_CREATE_IRQCHIP from a buffer provided by the caller.
-
-struct kvm_irqchip {
-       __u32 chip_id;  /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
-       __u32 pad;
-        union {
-               char dummy[512];  /* reserving space */
-               struct kvm_pic_state pic;
-               struct kvm_ioapic_state ioapic;
-       } chip;
-};
-
-
-4.28 KVM_XEN_HVM_CONFIG
-
-Capability: KVM_CAP_XEN_HVM
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_xen_hvm_config (in)
-Returns: 0 on success, -1 on error
-
-Sets the MSR that the Xen HVM guest uses to initialize its hypercall
-page, and provides the starting address and size of the hypercall
-blobs in userspace.  When the guest writes the MSR, kvm copies one
-page of a blob (32- or 64-bit, depending on the vcpu mode) to guest
-memory.
-
-struct kvm_xen_hvm_config {
-       __u32 flags;
-       __u32 msr;
-       __u64 blob_addr_32;
-       __u64 blob_addr_64;
-       __u8 blob_size_32;
-       __u8 blob_size_64;
-       __u8 pad2[30];
-};
-
-
-4.29 KVM_GET_CLOCK
-
-Capability: KVM_CAP_ADJUST_CLOCK
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_clock_data (out)
-Returns: 0 on success, -1 on error
-
-Gets the current timestamp of kvmclock as seen by the current guest. In
-conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios
-such as migration.
-
-When KVM_CAP_ADJUST_CLOCK is passed to KVM_CHECK_EXTENSION, it returns the
-set of bits that KVM can return in struct kvm_clock_data's flag member.
-
-The only flag defined now is KVM_CLOCK_TSC_STABLE.  If set, the returned
-value is the exact kvmclock value seen by all VCPUs at the instant
-when KVM_GET_CLOCK was called.  If clear, the returned value is simply
-CLOCK_MONOTONIC plus a constant offset; the offset can be modified
-with KVM_SET_CLOCK.  KVM will try to make all VCPUs follow this clock,
-but the exact value read by each VCPU could differ, because the host
-TSC is not stable.
-
-struct kvm_clock_data {
-       __u64 clock;  /* kvmclock current value */
-       __u32 flags;
-       __u32 pad[9];
-};
-
-
-4.30 KVM_SET_CLOCK
-
-Capability: KVM_CAP_ADJUST_CLOCK
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_clock_data (in)
-Returns: 0 on success, -1 on error
-
-Sets the current timestamp of kvmclock to the value specified in its parameter.
-In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios
-such as migration.
-
-struct kvm_clock_data {
-       __u64 clock;  /* kvmclock current value */
-       __u32 flags;
-       __u32 pad[9];
-};
-
-
-4.31 KVM_GET_VCPU_EVENTS
-
-Capability: KVM_CAP_VCPU_EVENTS
-Extended by: KVM_CAP_INTR_SHADOW
-Architectures: x86, arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_vcpu_event (out)
-Returns: 0 on success, -1 on error
-
-X86:
-
-Gets currently pending exceptions, interrupts, and NMIs as well as related
-states of the vcpu.
-
-struct kvm_vcpu_events {
-       struct {
-               __u8 injected;
-               __u8 nr;
-               __u8 has_error_code;
-               __u8 pending;
-               __u32 error_code;
-       } exception;
-       struct {
-               __u8 injected;
-               __u8 nr;
-               __u8 soft;
-               __u8 shadow;
-       } interrupt;
-       struct {
-               __u8 injected;
-               __u8 pending;
-               __u8 masked;
-               __u8 pad;
-       } nmi;
-       __u32 sipi_vector;
-       __u32 flags;
-       struct {
-               __u8 smm;
-               __u8 pending;
-               __u8 smm_inside_nmi;
-               __u8 latched_init;
-       } smi;
-       __u8 reserved[27];
-       __u8 exception_has_payload;
-       __u64 exception_payload;
-};
-
-The following bits are defined in the flags field:
-
-- KVM_VCPUEVENT_VALID_SHADOW may be set to signal that
-  interrupt.shadow contains a valid state.
-
-- KVM_VCPUEVENT_VALID_SMM may be set to signal that smi contains a
-  valid state.
-
-- KVM_VCPUEVENT_VALID_PAYLOAD may be set to signal that the
-  exception_has_payload, exception_payload, and exception.pending
-  fields contain a valid state. This bit will be set whenever
-  KVM_CAP_EXCEPTION_PAYLOAD is enabled.
-
-ARM/ARM64:
-
-If the guest accesses a device that is being emulated by the host kernel in
-such a way that a real device would generate a physical SError, KVM may make
-a virtual SError pending for that VCPU. This system error interrupt remains
-pending until the guest takes the exception by unmasking PSTATE.A.
-
-Running the VCPU may cause it to take a pending SError, or make an access that
-causes an SError to become pending. The event's description is only valid while
-the VPCU is not running.
-
-This API provides a way to read and write the pending 'event' state that is not
-visible to the guest. To save, restore or migrate a VCPU the struct representing
-the state can be read then written using this GET/SET API, along with the other
-guest-visible registers. It is not possible to 'cancel' an SError that has been
-made pending.
-
-A device being emulated in user-space may also wish to generate an SError. To do
-this the events structure can be populated by user-space. The current state
-should be read first, to ensure no existing SError is pending. If an existing
-SError is pending, the architecture's 'Multiple SError interrupts' rules should
-be followed. (2.5.3 of DDI0587.a "ARM Reliability, Availability, and
-Serviceability (RAS) Specification").
-
-SError exceptions always have an ESR value. Some CPUs have the ability to
-specify what the virtual SError's ESR value should be. These systems will
-advertise KVM_CAP_ARM_INJECT_SERROR_ESR. In this case exception.has_esr will
-always have a non-zero value when read, and the agent making an SError pending
-should specify the ISS field in the lower 24 bits of exception.serror_esr. If
-the system supports KVM_CAP_ARM_INJECT_SERROR_ESR, but user-space sets the events
-with exception.has_esr as zero, KVM will choose an ESR.
-
-Specifying exception.has_esr on a system that does not support it will return
--EINVAL. Setting anything other than the lower 24bits of exception.serror_esr
-will return -EINVAL.
-
-struct kvm_vcpu_events {
-       struct {
-               __u8 serror_pending;
-               __u8 serror_has_esr;
-               /* Align it to 8 bytes */
-               __u8 pad[6];
-               __u64 serror_esr;
-       } exception;
-       __u32 reserved[12];
-};
-
-4.32 KVM_SET_VCPU_EVENTS
-
-Capability: KVM_CAP_VCPU_EVENTS
-Extended by: KVM_CAP_INTR_SHADOW
-Architectures: x86, arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_vcpu_event (in)
-Returns: 0 on success, -1 on error
-
-X86:
-
-Set pending exceptions, interrupts, and NMIs as well as related states of the
-vcpu.
-
-See KVM_GET_VCPU_EVENTS for the data structure.
-
-Fields that may be modified asynchronously by running VCPUs can be excluded
-from the update. These fields are nmi.pending, sipi_vector, smi.smm,
-smi.pending. Keep the corresponding bits in the flags field cleared to
-suppress overwriting the current in-kernel state. The bits are:
-
-KVM_VCPUEVENT_VALID_NMI_PENDING - transfer nmi.pending to the kernel
-KVM_VCPUEVENT_VALID_SIPI_VECTOR - transfer sipi_vector
-KVM_VCPUEVENT_VALID_SMM         - transfer the smi sub-struct.
-
-If KVM_CAP_INTR_SHADOW is available, KVM_VCPUEVENT_VALID_SHADOW can be set in
-the flags field to signal that interrupt.shadow contains a valid state and
-shall be written into the VCPU.
-
-KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available.
-
-If KVM_CAP_EXCEPTION_PAYLOAD is enabled, KVM_VCPUEVENT_VALID_PAYLOAD
-can be set in the flags field to signal that the
-exception_has_payload, exception_payload, and exception.pending fields
-contain a valid state and shall be written into the VCPU.
-
-ARM/ARM64:
-
-Set the pending SError exception state for this VCPU. It is not possible to
-'cancel' an Serror that has been made pending.
-
-See KVM_GET_VCPU_EVENTS for the data structure.
-
-
-4.33 KVM_GET_DEBUGREGS
-
-Capability: KVM_CAP_DEBUGREGS
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_debugregs (out)
-Returns: 0 on success, -1 on error
-
-Reads debug registers from the vcpu.
-
-struct kvm_debugregs {
-       __u64 db[4];
-       __u64 dr6;
-       __u64 dr7;
-       __u64 flags;
-       __u64 reserved[9];
-};
-
-
-4.34 KVM_SET_DEBUGREGS
-
-Capability: KVM_CAP_DEBUGREGS
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_debugregs (in)
-Returns: 0 on success, -1 on error
-
-Writes debug registers into the vcpu.
-
-See KVM_GET_DEBUGREGS for the data structure. The flags field is unused
-yet and must be cleared on entry.
-
-
-4.35 KVM_SET_USER_MEMORY_REGION
-
-Capability: KVM_CAP_USER_MEMORY
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_userspace_memory_region (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_userspace_memory_region {
-       __u32 slot;
-       __u32 flags;
-       __u64 guest_phys_addr;
-       __u64 memory_size; /* bytes */
-       __u64 userspace_addr; /* start of the userspace allocated memory */
-};
-
-/* for kvm_memory_region::flags */
-#define KVM_MEM_LOG_DIRTY_PAGES        (1UL << 0)
-#define KVM_MEM_READONLY       (1UL << 1)
-
-This ioctl allows the user to create, modify or delete a guest physical
-memory slot.  Bits 0-15 of "slot" specify the slot id and this value
-should be less than the maximum number of user memory slots supported per
-VM.  The maximum allowed slots can be queried using KVM_CAP_NR_MEMSLOTS.
-Slots may not overlap in guest physical address space.
-
-If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 of "slot"
-specifies the address space which is being modified.  They must be
-less than the value that KVM_CHECK_EXTENSION returns for the
-KVM_CAP_MULTI_ADDRESS_SPACE capability.  Slots in separate address spaces
-are unrelated; the restriction on overlapping slots only applies within
-each address space.
-
-Deleting a slot is done by passing zero for memory_size.  When changing
-an existing slot, it may be moved in the guest physical memory space,
-or its flags may be modified, but it may not be resized.
-
-Memory for the region is taken starting at the address denoted by the
-field userspace_addr, which must point at user addressable memory for
-the entire memory slot size.  Any object may back this memory, including
-anonymous memory, ordinary files, and hugetlbfs.
-
-It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
-be identical.  This allows large pages in the guest to be backed by large
-pages in the host.
-
-The flags field supports two flags: KVM_MEM_LOG_DIRTY_PAGES and
-KVM_MEM_READONLY.  The former can be set to instruct KVM to keep track of
-writes to memory within the slot.  See KVM_GET_DIRTY_LOG ioctl to know how to
-use it.  The latter can be set, if KVM_CAP_READONLY_MEM capability allows it,
-to make a new slot read-only.  In this case, writes to this memory will be
-posted to userspace as KVM_EXIT_MMIO exits.
-
-When the KVM_CAP_SYNC_MMU capability is available, changes in the backing of
-the memory region are automatically reflected into the guest.  For example, an
-mmap() that affects the region will be made visible immediately.  Another
-example is madvise(MADV_DROP).
-
-It is recommended to use this API instead of the KVM_SET_MEMORY_REGION ioctl.
-The KVM_SET_MEMORY_REGION does not allow fine grained control over memory
-allocation and is deprecated.
-
-
-4.36 KVM_SET_TSS_ADDR
-
-Capability: KVM_CAP_SET_TSS_ADDR
-Architectures: x86
-Type: vm ioctl
-Parameters: unsigned long tss_address (in)
-Returns: 0 on success, -1 on error
-
-This ioctl defines the physical address of a three-page region in the guest
-physical address space.  The region must be within the first 4GB of the
-guest physical address space and must not conflict with any memory slot
-or any mmio address.  The guest may malfunction if it accesses this memory
-region.
-
-This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
-because of a quirk in the virtualization implementation (see the internals
-documentation when it pops into existence).
-
-
-4.37 KVM_ENABLE_CAP
-
-Capability: KVM_CAP_ENABLE_CAP
-Architectures: mips, ppc, s390
-Type: vcpu ioctl
-Parameters: struct kvm_enable_cap (in)
-Returns: 0 on success; -1 on error
-
-Capability: KVM_CAP_ENABLE_CAP_VM
-Architectures: all
-Type: vcpu ioctl
-Parameters: struct kvm_enable_cap (in)
-Returns: 0 on success; -1 on error
-
-+Not all extensions are enabled by default. Using this ioctl the application
-can enable an extension, making it available to the guest.
-
-On systems that do not support this ioctl, it always fails. On systems that
-do support it, it only works for extensions that are supported for enablement.
-
-To check if a capability can be enabled, the KVM_CHECK_EXTENSION ioctl should
-be used.
-
-struct kvm_enable_cap {
-       /* in */
-       __u32 cap;
-
-The capability that is supposed to get enabled.
-
-       __u32 flags;
-
-A bitfield indicating future enhancements. Has to be 0 for now.
-
-       __u64 args[4];
-
-Arguments for enabling a feature. If a feature needs initial values to
-function properly, this is the place to put them.
-
-       __u8  pad[64];
-};
-
-The vcpu ioctl should be used for vcpu-specific capabilities, the vm ioctl
-for vm-wide capabilities.
-
-4.38 KVM_GET_MP_STATE
-
-Capability: KVM_CAP_MP_STATE
-Architectures: x86, s390, arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_mp_state (out)
-Returns: 0 on success; -1 on error
-
-struct kvm_mp_state {
-       __u32 mp_state;
-};
-
-Returns the vcpu's current "multiprocessing state" (though also valid on
-uniprocessor guests).
-
-Possible values are:
-
- - KVM_MP_STATE_RUNNABLE:        the vcpu is currently running [x86,arm/arm64]
- - KVM_MP_STATE_UNINITIALIZED:   the vcpu is an application processor (AP)
-                                 which has not yet received an INIT signal [x86]
- - KVM_MP_STATE_INIT_RECEIVED:   the vcpu has received an INIT signal, and is
-                                 now ready for a SIPI [x86]
- - KVM_MP_STATE_HALTED:          the vcpu has executed a HLT instruction and
-                                 is waiting for an interrupt [x86]
- - KVM_MP_STATE_SIPI_RECEIVED:   the vcpu has just received a SIPI (vector
-                                 accessible via KVM_GET_VCPU_EVENTS) [x86]
- - KVM_MP_STATE_STOPPED:         the vcpu is stopped [s390,arm/arm64]
- - KVM_MP_STATE_CHECK_STOP:      the vcpu is in a special error state [s390]
- - KVM_MP_STATE_OPERATING:       the vcpu is operating (running or halted)
-                                 [s390]
- - KVM_MP_STATE_LOAD:            the vcpu is in a special load/startup state
-                                 [s390]
-
-On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
-in-kernel irqchip, the multiprocessing state must be maintained by userspace on
-these architectures.
-
-For arm/arm64:
-
-The only states that are valid are KVM_MP_STATE_STOPPED and
-KVM_MP_STATE_RUNNABLE which reflect if the vcpu is paused or not.
-
-4.39 KVM_SET_MP_STATE
-
-Capability: KVM_CAP_MP_STATE
-Architectures: x86, s390, arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_mp_state (in)
-Returns: 0 on success; -1 on error
-
-Sets the vcpu's current "multiprocessing state"; see KVM_GET_MP_STATE for
-arguments.
-
-On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
-in-kernel irqchip, the multiprocessing state must be maintained by userspace on
-these architectures.
-
-For arm/arm64:
-
-The only states that are valid are KVM_MP_STATE_STOPPED and
-KVM_MP_STATE_RUNNABLE which reflect if the vcpu should be paused or not.
-
-4.40 KVM_SET_IDENTITY_MAP_ADDR
-
-Capability: KVM_CAP_SET_IDENTITY_MAP_ADDR
-Architectures: x86
-Type: vm ioctl
-Parameters: unsigned long identity (in)
-Returns: 0 on success, -1 on error
-
-This ioctl defines the physical address of a one-page region in the guest
-physical address space.  The region must be within the first 4GB of the
-guest physical address space and must not conflict with any memory slot
-or any mmio address.  The guest may malfunction if it accesses this memory
-region.
-
-Setting the address to 0 will result in resetting the address to its default
-(0xfffbc000).
-
-This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
-because of a quirk in the virtualization implementation (see the internals
-documentation when it pops into existence).
-
-Fails if any VCPU has already been created.
-
-4.41 KVM_SET_BOOT_CPU_ID
-
-Capability: KVM_CAP_SET_BOOT_CPU_ID
-Architectures: x86
-Type: vm ioctl
-Parameters: unsigned long vcpu_id
-Returns: 0 on success, -1 on error
-
-Define which vcpu is the Bootstrap Processor (BSP).  Values are the same
-as the vcpu id in KVM_CREATE_VCPU.  If this ioctl is not called, the default
-is vcpu 0.
-
-
-4.42 KVM_GET_XSAVE
-
-Capability: KVM_CAP_XSAVE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_xsave (out)
-Returns: 0 on success, -1 on error
-
-struct kvm_xsave {
-       __u32 region[1024];
-};
-
-This ioctl would copy current vcpu's xsave struct to the userspace.
-
-
-4.43 KVM_SET_XSAVE
-
-Capability: KVM_CAP_XSAVE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_xsave (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_xsave {
-       __u32 region[1024];
-};
-
-This ioctl would copy userspace's xsave struct to the kernel.
-
-
-4.44 KVM_GET_XCRS
-
-Capability: KVM_CAP_XCRS
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_xcrs (out)
-Returns: 0 on success, -1 on error
-
-struct kvm_xcr {
-       __u32 xcr;
-       __u32 reserved;
-       __u64 value;
-};
-
-struct kvm_xcrs {
-       __u32 nr_xcrs;
-       __u32 flags;
-       struct kvm_xcr xcrs[KVM_MAX_XCRS];
-       __u64 padding[16];
-};
-
-This ioctl would copy current vcpu's xcrs to the userspace.
-
-
-4.45 KVM_SET_XCRS
-
-Capability: KVM_CAP_XCRS
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_xcrs (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_xcr {
-       __u32 xcr;
-       __u32 reserved;
-       __u64 value;
-};
-
-struct kvm_xcrs {
-       __u32 nr_xcrs;
-       __u32 flags;
-       struct kvm_xcr xcrs[KVM_MAX_XCRS];
-       __u64 padding[16];
-};
-
-This ioctl would set vcpu's xcr to the value userspace specified.
-
-
-4.46 KVM_GET_SUPPORTED_CPUID
-
-Capability: KVM_CAP_EXT_CPUID
-Architectures: x86
-Type: system ioctl
-Parameters: struct kvm_cpuid2 (in/out)
-Returns: 0 on success, -1 on error
-
-struct kvm_cpuid2 {
-       __u32 nent;
-       __u32 padding;
-       struct kvm_cpuid_entry2 entries[0];
-};
-
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX                BIT(0)
-#define KVM_CPUID_FLAG_STATEFUL_FUNC           BIT(1)
-#define KVM_CPUID_FLAG_STATE_READ_NEXT         BIT(2)
-
-struct kvm_cpuid_entry2 {
-       __u32 function;
-       __u32 index;
-       __u32 flags;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding[3];
-};
-
-This ioctl returns x86 cpuid features which are supported by both the
-hardware and kvm in its default configuration.  Userspace can use the
-information returned by this ioctl to construct cpuid information (for
-KVM_SET_CPUID2) that is consistent with hardware, kernel, and
-userspace capabilities, and with user requirements (for example, the
-user may wish to constrain cpuid to emulate older hardware, or for
-feature consistency across a cluster).
-
-Note that certain capabilities, such as KVM_CAP_X86_DISABLE_EXITS, may
-expose cpuid features (e.g. MONITOR) which are not supported by kvm in
-its default configuration. If userspace enables such capabilities, it
-is responsible for modifying the results of this ioctl appropriately.
-
-Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
-with the 'nent' field indicating the number of entries in the variable-size
-array 'entries'.  If the number of entries is too low to describe the cpu
-capabilities, an error (E2BIG) is returned.  If the number is too high,
-the 'nent' field is adjusted and an error (ENOMEM) is returned.  If the
-number is just right, the 'nent' field is adjusted to the number of valid
-entries in the 'entries' array, which is then filled.
-
-The entries returned are the host cpuid as returned by the cpuid instruction,
-with unknown or unsupported features masked out.  Some features (for example,
-x2apic), may not be present in the host cpu, but are exposed by kvm if it can
-emulate them efficiently. The fields in each entry are defined as follows:
-
-  function: the eax value used to obtain the entry
-  index: the ecx value used to obtain the entry (for entries that are
-         affected by ecx)
-  flags: an OR of zero or more of the following:
-        KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
-           if the index field is valid
-        KVM_CPUID_FLAG_STATEFUL_FUNC:
-           if cpuid for this function returns different values for successive
-           invocations; there will be several entries with the same function,
-           all with this flag set
-        KVM_CPUID_FLAG_STATE_READ_NEXT:
-           for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
-           the first entry to be read by a cpu
-   eax, ebx, ecx, edx: the values returned by the cpuid instruction for
-         this function/index combination
-
-The TSC deadline timer feature (CPUID leaf 1, ecx[24]) is always returned
-as false, since the feature depends on KVM_CREATE_IRQCHIP for local APIC
-support.  Instead it is reported via
-
-  ioctl(KVM_CHECK_EXTENSION, KVM_CAP_TSC_DEADLINE_TIMER)
-
-if that returns true and you use KVM_CREATE_IRQCHIP, or if you emulate the
-feature in userspace, then you can enable the feature for KVM_SET_CPUID2.
-
-
-4.47 KVM_PPC_GET_PVINFO
-
-Capability: KVM_CAP_PPC_GET_PVINFO
-Architectures: ppc
-Type: vm ioctl
-Parameters: struct kvm_ppc_pvinfo (out)
-Returns: 0 on success, !0 on error
-
-struct kvm_ppc_pvinfo {
-       __u32 flags;
-       __u32 hcall[4];
-       __u8  pad[108];
-};
-
-This ioctl fetches PV specific information that need to be passed to the guest
-using the device tree or other means from vm context.
-
-The hcall array defines 4 instructions that make up a hypercall.
-
-If any additional field gets added to this structure later on, a bit for that
-additional piece of information will be set in the flags bitmap.
-
-The flags bitmap is defined as:
-
-   /* the host supports the ePAPR idle hcall
-   #define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
-
-4.52 KVM_SET_GSI_ROUTING
-
-Capability: KVM_CAP_IRQ_ROUTING
-Architectures: x86 s390 arm arm64
-Type: vm ioctl
-Parameters: struct kvm_irq_routing (in)
-Returns: 0 on success, -1 on error
-
-Sets the GSI routing table entries, overwriting any previously set entries.
-
-On arm/arm64, GSI routing has the following limitation:
-- GSI routing does not apply to KVM_IRQ_LINE but only to KVM_IRQFD.
-
-struct kvm_irq_routing {
-       __u32 nr;
-       __u32 flags;
-       struct kvm_irq_routing_entry entries[0];
-};
-
-No flags are specified so far, the corresponding field must be set to zero.
-
-struct kvm_irq_routing_entry {
-       __u32 gsi;
-       __u32 type;
-       __u32 flags;
-       __u32 pad;
-       union {
-               struct kvm_irq_routing_irqchip irqchip;
-               struct kvm_irq_routing_msi msi;
-               struct kvm_irq_routing_s390_adapter adapter;
-               struct kvm_irq_routing_hv_sint hv_sint;
-               __u32 pad[8];
-       } u;
-};
-
-/* gsi routing entry types */
-#define KVM_IRQ_ROUTING_IRQCHIP 1
-#define KVM_IRQ_ROUTING_MSI 2
-#define KVM_IRQ_ROUTING_S390_ADAPTER 3
-#define KVM_IRQ_ROUTING_HV_SINT 4
-
-flags:
-- KVM_MSI_VALID_DEVID: used along with KVM_IRQ_ROUTING_MSI routing entry
-  type, specifies that the devid field contains a valid value.  The per-VM
-  KVM_CAP_MSI_DEVID capability advertises the requirement to provide
-  the device ID.  If this capability is not available, userspace should
-  never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
-- zero otherwise
-
-struct kvm_irq_routing_irqchip {
-       __u32 irqchip;
-       __u32 pin;
-};
-
-struct kvm_irq_routing_msi {
-       __u32 address_lo;
-       __u32 address_hi;
-       __u32 data;
-       union {
-               __u32 pad;
-               __u32 devid;
-       };
-};
-
-If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
-for the device that wrote the MSI message.  For PCI, this is usually a
-BFD identifier in the lower 16 bits.
-
-On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
-feature of KVM_CAP_X2APIC_API capability is enabled.  If it is enabled,
-address_hi bits 31-8 provide bits 31-8 of the destination id.  Bits 7-0 of
-address_hi must be zero.
-
-struct kvm_irq_routing_s390_adapter {
-       __u64 ind_addr;
-       __u64 summary_addr;
-       __u64 ind_offset;
-       __u32 summary_offset;
-       __u32 adapter_id;
-};
-
-struct kvm_irq_routing_hv_sint {
-       __u32 vcpu;
-       __u32 sint;
-};
-
-
-4.55 KVM_SET_TSC_KHZ
-
-Capability: KVM_CAP_TSC_CONTROL
-Architectures: x86
-Type: vcpu ioctl
-Parameters: virtual tsc_khz
-Returns: 0 on success, -1 on error
-
-Specifies the tsc frequency for the virtual machine. The unit of the
-frequency is KHz.
-
-
-4.56 KVM_GET_TSC_KHZ
-
-Capability: KVM_CAP_GET_TSC_KHZ
-Architectures: x86
-Type: vcpu ioctl
-Parameters: none
-Returns: virtual tsc-khz on success, negative value on error
-
-Returns the tsc frequency of the guest. The unit of the return value is
-KHz. If the host has unstable tsc this ioctl returns -EIO instead as an
-error.
-
-
-4.57 KVM_GET_LAPIC
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_lapic_state (out)
-Returns: 0 on success, -1 on error
-
-#define KVM_APIC_REG_SIZE 0x400
-struct kvm_lapic_state {
-       char regs[KVM_APIC_REG_SIZE];
-};
-
-Reads the Local APIC registers and copies them into the input argument.  The
-data format and layout are the same as documented in the architecture manual.
-
-If KVM_X2APIC_API_USE_32BIT_IDS feature of KVM_CAP_X2APIC_API is
-enabled, then the format of APIC_ID register depends on the APIC mode
-(reported by MSR_IA32_APICBASE) of its VCPU.  x2APIC stores APIC ID in
-the APIC_ID register (bytes 32-35).  xAPIC only allows an 8-bit APIC ID
-which is stored in bits 31-24 of the APIC register, or equivalently in
-byte 35 of struct kvm_lapic_state's regs field.  KVM_GET_LAPIC must then
-be called after MSR_IA32_APICBASE has been set with KVM_SET_MSR.
-
-If KVM_X2APIC_API_USE_32BIT_IDS feature is disabled, struct kvm_lapic_state
-always uses xAPIC format.
-
-
-4.58 KVM_SET_LAPIC
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_lapic_state (in)
-Returns: 0 on success, -1 on error
-
-#define KVM_APIC_REG_SIZE 0x400
-struct kvm_lapic_state {
-       char regs[KVM_APIC_REG_SIZE];
-};
-
-Copies the input argument into the Local APIC registers.  The data format
-and layout are the same as documented in the architecture manual.
-
-The format of the APIC ID register (bytes 32-35 of struct kvm_lapic_state's
-regs field) depends on the state of the KVM_CAP_X2APIC_API capability.
-See the note in KVM_GET_LAPIC.
-
-
-4.59 KVM_IOEVENTFD
-
-Capability: KVM_CAP_IOEVENTFD
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_ioeventfd (in)
-Returns: 0 on success, !0 on error
-
-This ioctl attaches or detaches an ioeventfd to a legal pio/mmio address
-within the guest.  A guest write in the registered address will signal the
-provided event instead of triggering an exit.
-
-struct kvm_ioeventfd {
-       __u64 datamatch;
-       __u64 addr;        /* legal pio/mmio address */
-       __u32 len;         /* 0, 1, 2, 4, or 8 bytes    */
-       __s32 fd;
-       __u32 flags;
-       __u8  pad[36];
-};
-
-For the special case of virtio-ccw devices on s390, the ioevent is matched
-to a subchannel/virtqueue tuple instead.
-
-The following flags are defined:
-
-#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
-#define KVM_IOEVENTFD_FLAG_PIO       (1 << kvm_ioeventfd_flag_nr_pio)
-#define KVM_IOEVENTFD_FLAG_DEASSIGN  (1 << kvm_ioeventfd_flag_nr_deassign)
-#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
-       (1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
-
-If datamatch flag is set, the event will be signaled only if the written value
-to the registered address is equal to datamatch in struct kvm_ioeventfd.
-
-For virtio-ccw devices, addr contains the subchannel id and datamatch the
-virtqueue index.
-
-With KVM_CAP_IOEVENTFD_ANY_LENGTH, a zero length ioeventfd is allowed, and
-the kernel will ignore the length of guest write and may get a faster vmexit.
-The speedup may only apply to specific architectures, but the ioeventfd will
-work anyway.
-
-4.60 KVM_DIRTY_TLB
-
-Capability: KVM_CAP_SW_TLB
-Architectures: ppc
-Type: vcpu ioctl
-Parameters: struct kvm_dirty_tlb (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_dirty_tlb {
-       __u64 bitmap;
-       __u32 num_dirty;
-};
-
-This must be called whenever userspace has changed an entry in the shared
-TLB, prior to calling KVM_RUN on the associated vcpu.
-
-The "bitmap" field is the userspace address of an array.  This array
-consists of a number of bits, equal to the total number of TLB entries as
-determined by the last successful call to KVM_CONFIG_TLB, rounded up to the
-nearest multiple of 64.
-
-Each bit corresponds to one TLB entry, ordered the same as in the shared TLB
-array.
-
-The array is little-endian: the bit 0 is the least significant bit of the
-first byte, bit 8 is the least significant bit of the second byte, etc.
-This avoids any complications with differing word sizes.
-
-The "num_dirty" field is a performance hint for KVM to determine whether it
-should skip processing the bitmap and just invalidate everything.  It must
-be set to the number of set bits in the bitmap.
-
-
-4.62 KVM_CREATE_SPAPR_TCE
-
-Capability: KVM_CAP_SPAPR_TCE
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_create_spapr_tce (in)
-Returns: file descriptor for manipulating the created TCE table
-
-This creates a virtual TCE (translation control entry) table, which
-is an IOMMU for PAPR-style virtual I/O.  It is used to translate
-logical addresses used in virtual I/O into guest physical addresses,
-and provides a scatter/gather capability for PAPR virtual I/O.
-
-/* for KVM_CAP_SPAPR_TCE */
-struct kvm_create_spapr_tce {
-       __u64 liobn;
-       __u32 window_size;
-};
-
-The liobn field gives the logical IO bus number for which to create a
-TCE table.  The window_size field specifies the size of the DMA window
-which this TCE table will translate - the table will contain one 64
-bit TCE entry for every 4kiB of the DMA window.
-
-When the guest issues an H_PUT_TCE hcall on a liobn for which a TCE
-table has been created using this ioctl(), the kernel will handle it
-in real mode, updating the TCE table.  H_PUT_TCE calls for other
-liobns will cause a vm exit and must be handled by userspace.
-
-The return value is a file descriptor which can be passed to mmap(2)
-to map the created TCE table into userspace.  This lets userspace read
-the entries written by kernel-handled H_PUT_TCE calls, and also lets
-userspace update the TCE table directly which is useful in some
-circumstances.
-
-
-4.63 KVM_ALLOCATE_RMA
-
-Capability: KVM_CAP_PPC_RMA
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_allocate_rma (out)
-Returns: file descriptor for mapping the allocated RMA
-
-This allocates a Real Mode Area (RMA) from the pool allocated at boot
-time by the kernel.  An RMA is a physically-contiguous, aligned region
-of memory used on older POWER processors to provide the memory which
-will be accessed by real-mode (MMU off) accesses in a KVM guest.
-POWER processors support a set of sizes for the RMA that usually
-includes 64MB, 128MB, 256MB and some larger powers of two.
-
-/* for KVM_ALLOCATE_RMA */
-struct kvm_allocate_rma {
-       __u64 rma_size;
-};
-
-The return value is a file descriptor which can be passed to mmap(2)
-to map the allocated RMA into userspace.  The mapped area can then be
-passed to the KVM_SET_USER_MEMORY_REGION ioctl to establish it as the
-RMA for a virtual machine.  The size of the RMA in bytes (which is
-fixed at host kernel boot time) is returned in the rma_size field of
-the argument structure.
-
-The KVM_CAP_PPC_RMA capability is 1 or 2 if the KVM_ALLOCATE_RMA ioctl
-is supported; 2 if the processor requires all virtual machines to have
-an RMA, or 1 if the processor can use an RMA but doesn't require it,
-because it supports the Virtual RMA (VRMA) facility.
-
-
-4.64 KVM_NMI
-
-Capability: KVM_CAP_USER_NMI
-Architectures: x86
-Type: vcpu ioctl
-Parameters: none
-Returns: 0 on success, -1 on error
-
-Queues an NMI on the thread's vcpu.  Note this is well defined only
-when KVM_CREATE_IRQCHIP has not been called, since this is an interface
-between the virtual cpu core and virtual local APIC.  After KVM_CREATE_IRQCHIP
-has been called, this interface is completely emulated within the kernel.
-
-To use this to emulate the LINT1 input with KVM_CREATE_IRQCHIP, use the
-following algorithm:
-
-  - pause the vcpu
-  - read the local APIC's state (KVM_GET_LAPIC)
-  - check whether changing LINT1 will queue an NMI (see the LVT entry for LINT1)
-  - if so, issue KVM_NMI
-  - resume the vcpu
-
-Some guests configure the LINT1 NMI input to cause a panic, aiding in
-debugging.
-
-
-4.65 KVM_S390_UCAS_MAP
-
-Capability: KVM_CAP_S390_UCONTROL
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_ucas_mapping (in)
-Returns: 0 in case of success
-
-The parameter is defined like this:
-       struct kvm_s390_ucas_mapping {
-               __u64 user_addr;
-               __u64 vcpu_addr;
-               __u64 length;
-       };
-
-This ioctl maps the memory at "user_addr" with the length "length" to
-the vcpu's address space starting at "vcpu_addr". All parameters need to
-be aligned by 1 megabyte.
-
-
-4.66 KVM_S390_UCAS_UNMAP
-
-Capability: KVM_CAP_S390_UCONTROL
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_ucas_mapping (in)
-Returns: 0 in case of success
-
-The parameter is defined like this:
-       struct kvm_s390_ucas_mapping {
-               __u64 user_addr;
-               __u64 vcpu_addr;
-               __u64 length;
-       };
-
-This ioctl unmaps the memory in the vcpu's address space starting at
-"vcpu_addr" with the length "length". The field "user_addr" is ignored.
-All parameters need to be aligned by 1 megabyte.
-
-
-4.67 KVM_S390_VCPU_FAULT
-
-Capability: KVM_CAP_S390_UCONTROL
-Architectures: s390
-Type: vcpu ioctl
-Parameters: vcpu absolute address (in)
-Returns: 0 in case of success
-
-This call creates a page table entry on the virtual cpu's address space
-(for user controlled virtual machines) or the virtual machine's address
-space (for regular virtual machines). This only works for minor faults,
-thus it's recommended to access subject memory page via the user page
-table upfront. This is useful to handle validity intercepts for user
-controlled virtual machines to fault in the virtual cpu's lowcore pages
-prior to calling the KVM_RUN ioctl.
-
-
-4.68 KVM_SET_ONE_REG
-
-Capability: KVM_CAP_ONE_REG
-Architectures: all
-Type: vcpu ioctl
-Parameters: struct kvm_one_reg (in)
-Returns: 0 on success, negative value on failure
-Errors:
-  ENOENT:   no such register
-  EINVAL:   invalid register ID, or no such register
-  EPERM:    (arm64) register access not allowed before vcpu finalization
-(These error codes are indicative only: do not rely on a specific error
-code being returned in a specific situation.)
-
-struct kvm_one_reg {
-       __u64 id;
-       __u64 addr;
-};
-
-Using this ioctl, a single vcpu register can be set to a specific value
-defined by user space with the passed in struct kvm_one_reg, where id
-refers to the register identifier as described below and addr is a pointer
-to a variable with the respective size. There can be architecture agnostic
-and architecture specific registers. Each have their own range of operation
-and their own constants and width. To keep track of the implemented
-registers, find a list below:
-
-  Arch  |           Register            | Width (bits)
-        |                               |
-  PPC   | KVM_REG_PPC_HIOR              | 64
-  PPC   | KVM_REG_PPC_IAC1              | 64
-  PPC   | KVM_REG_PPC_IAC2              | 64
-  PPC   | KVM_REG_PPC_IAC3              | 64
-  PPC   | KVM_REG_PPC_IAC4              | 64
-  PPC   | KVM_REG_PPC_DAC1              | 64
-  PPC   | KVM_REG_PPC_DAC2              | 64
-  PPC   | KVM_REG_PPC_DABR              | 64
-  PPC   | KVM_REG_PPC_DSCR              | 64
-  PPC   | KVM_REG_PPC_PURR              | 64
-  PPC   | KVM_REG_PPC_SPURR             | 64
-  PPC   | KVM_REG_PPC_DAR               | 64
-  PPC   | KVM_REG_PPC_DSISR             | 32
-  PPC   | KVM_REG_PPC_AMR               | 64
-  PPC   | KVM_REG_PPC_UAMOR             | 64
-  PPC   | KVM_REG_PPC_MMCR0             | 64
-  PPC   | KVM_REG_PPC_MMCR1             | 64
-  PPC   | KVM_REG_PPC_MMCRA             | 64
-  PPC   | KVM_REG_PPC_MMCR2             | 64
-  PPC   | KVM_REG_PPC_MMCRS             | 64
-  PPC   | KVM_REG_PPC_SIAR              | 64
-  PPC   | KVM_REG_PPC_SDAR              | 64
-  PPC   | KVM_REG_PPC_SIER              | 64
-  PPC   | KVM_REG_PPC_PMC1              | 32
-  PPC   | KVM_REG_PPC_PMC2              | 32
-  PPC   | KVM_REG_PPC_PMC3              | 32
-  PPC   | KVM_REG_PPC_PMC4              | 32
-  PPC   | KVM_REG_PPC_PMC5              | 32
-  PPC   | KVM_REG_PPC_PMC6              | 32
-  PPC   | KVM_REG_PPC_PMC7              | 32
-  PPC   | KVM_REG_PPC_PMC8              | 32
-  PPC   | KVM_REG_PPC_FPR0              | 64
-          ...
-  PPC   | KVM_REG_PPC_FPR31             | 64
-  PPC   | KVM_REG_PPC_VR0               | 128
-          ...
-  PPC   | KVM_REG_PPC_VR31              | 128
-  PPC   | KVM_REG_PPC_VSR0              | 128
-          ...
-  PPC   | KVM_REG_PPC_VSR31             | 128
-  PPC   | KVM_REG_PPC_FPSCR             | 64
-  PPC   | KVM_REG_PPC_VSCR              | 32
-  PPC   | KVM_REG_PPC_VPA_ADDR          | 64
-  PPC   | KVM_REG_PPC_VPA_SLB           | 128
-  PPC   | KVM_REG_PPC_VPA_DTL           | 128
-  PPC   | KVM_REG_PPC_EPCR              | 32
-  PPC   | KVM_REG_PPC_EPR               | 32
-  PPC   | KVM_REG_PPC_TCR               | 32
-  PPC   | KVM_REG_PPC_TSR               | 32
-  PPC   | KVM_REG_PPC_OR_TSR            | 32
-  PPC   | KVM_REG_PPC_CLEAR_TSR         | 32
-  PPC   | KVM_REG_PPC_MAS0              | 32
-  PPC   | KVM_REG_PPC_MAS1              | 32
-  PPC   | KVM_REG_PPC_MAS2              | 64
-  PPC   | KVM_REG_PPC_MAS7_3            | 64
-  PPC   | KVM_REG_PPC_MAS4              | 32
-  PPC   | KVM_REG_PPC_MAS6              | 32
-  PPC   | KVM_REG_PPC_MMUCFG            | 32
-  PPC   | KVM_REG_PPC_TLB0CFG           | 32
-  PPC   | KVM_REG_PPC_TLB1CFG           | 32
-  PPC   | KVM_REG_PPC_TLB2CFG           | 32
-  PPC   | KVM_REG_PPC_TLB3CFG           | 32
-  PPC   | KVM_REG_PPC_TLB0PS            | 32
-  PPC   | KVM_REG_PPC_TLB1PS            | 32
-  PPC   | KVM_REG_PPC_TLB2PS            | 32
-  PPC   | KVM_REG_PPC_TLB3PS            | 32
-  PPC   | KVM_REG_PPC_EPTCFG            | 32
-  PPC   | KVM_REG_PPC_ICP_STATE         | 64
-  PPC   | KVM_REG_PPC_VP_STATE          | 128
-  PPC   | KVM_REG_PPC_TB_OFFSET         | 64
-  PPC   | KVM_REG_PPC_SPMC1             | 32
-  PPC   | KVM_REG_PPC_SPMC2             | 32
-  PPC   | KVM_REG_PPC_IAMR              | 64
-  PPC   | KVM_REG_PPC_TFHAR             | 64
-  PPC   | KVM_REG_PPC_TFIAR             | 64
-  PPC   | KVM_REG_PPC_TEXASR            | 64
-  PPC   | KVM_REG_PPC_FSCR              | 64
-  PPC   | KVM_REG_PPC_PSPB              | 32
-  PPC   | KVM_REG_PPC_EBBHR             | 64
-  PPC   | KVM_REG_PPC_EBBRR             | 64
-  PPC   | KVM_REG_PPC_BESCR             | 64
-  PPC   | KVM_REG_PPC_TAR               | 64
-  PPC   | KVM_REG_PPC_DPDES             | 64
-  PPC   | KVM_REG_PPC_DAWR              | 64
-  PPC   | KVM_REG_PPC_DAWRX             | 64
-  PPC   | KVM_REG_PPC_CIABR             | 64
-  PPC   | KVM_REG_PPC_IC                | 64
-  PPC   | KVM_REG_PPC_VTB               | 64
-  PPC   | KVM_REG_PPC_CSIGR             | 64
-  PPC   | KVM_REG_PPC_TACR              | 64
-  PPC   | KVM_REG_PPC_TCSCR             | 64
-  PPC   | KVM_REG_PPC_PID               | 64
-  PPC   | KVM_REG_PPC_ACOP              | 64
-  PPC   | KVM_REG_PPC_VRSAVE            | 32
-  PPC   | KVM_REG_PPC_LPCR              | 32
-  PPC   | KVM_REG_PPC_LPCR_64           | 64
-  PPC   | KVM_REG_PPC_PPR               | 64
-  PPC   | KVM_REG_PPC_ARCH_COMPAT       | 32
-  PPC   | KVM_REG_PPC_DABRX             | 32
-  PPC   | KVM_REG_PPC_WORT              | 64
-  PPC  | KVM_REG_PPC_SPRG9             | 64
-  PPC  | KVM_REG_PPC_DBSR              | 32
-  PPC   | KVM_REG_PPC_TIDR              | 64
-  PPC   | KVM_REG_PPC_PSSCR             | 64
-  PPC   | KVM_REG_PPC_DEC_EXPIRY        | 64
-  PPC   | KVM_REG_PPC_PTCR              | 64
-  PPC   | KVM_REG_PPC_TM_GPR0           | 64
-          ...
-  PPC   | KVM_REG_PPC_TM_GPR31          | 64
-  PPC   | KVM_REG_PPC_TM_VSR0           | 128
-          ...
-  PPC   | KVM_REG_PPC_TM_VSR63          | 128
-  PPC   | KVM_REG_PPC_TM_CR             | 64
-  PPC   | KVM_REG_PPC_TM_LR             | 64
-  PPC   | KVM_REG_PPC_TM_CTR            | 64
-  PPC   | KVM_REG_PPC_TM_FPSCR          | 64
-  PPC   | KVM_REG_PPC_TM_AMR            | 64
-  PPC   | KVM_REG_PPC_TM_PPR            | 64
-  PPC   | KVM_REG_PPC_TM_VRSAVE         | 64
-  PPC   | KVM_REG_PPC_TM_VSCR           | 32
-  PPC   | KVM_REG_PPC_TM_DSCR           | 64
-  PPC   | KVM_REG_PPC_TM_TAR            | 64
-  PPC   | KVM_REG_PPC_TM_XER            | 64
-        |                               |
-  MIPS  | KVM_REG_MIPS_R0               | 64
-          ...
-  MIPS  | KVM_REG_MIPS_R31              | 64
-  MIPS  | KVM_REG_MIPS_HI               | 64
-  MIPS  | KVM_REG_MIPS_LO               | 64
-  MIPS  | KVM_REG_MIPS_PC               | 64
-  MIPS  | KVM_REG_MIPS_CP0_INDEX        | 32
-  MIPS  | KVM_REG_MIPS_CP0_ENTRYLO0     | 64
-  MIPS  | KVM_REG_MIPS_CP0_ENTRYLO1     | 64
-  MIPS  | KVM_REG_MIPS_CP0_CONTEXT      | 64
-  MIPS  | KVM_REG_MIPS_CP0_CONTEXTCONFIG| 32
-  MIPS  | KVM_REG_MIPS_CP0_USERLOCAL    | 64
-  MIPS  | KVM_REG_MIPS_CP0_XCONTEXTCONFIG| 64
-  MIPS  | KVM_REG_MIPS_CP0_PAGEMASK     | 32
-  MIPS  | KVM_REG_MIPS_CP0_PAGEGRAIN    | 32
-  MIPS  | KVM_REG_MIPS_CP0_SEGCTL0      | 64
-  MIPS  | KVM_REG_MIPS_CP0_SEGCTL1      | 64
-  MIPS  | KVM_REG_MIPS_CP0_SEGCTL2      | 64
-  MIPS  | KVM_REG_MIPS_CP0_PWBASE       | 64
-  MIPS  | KVM_REG_MIPS_CP0_PWFIELD      | 64
-  MIPS  | KVM_REG_MIPS_CP0_PWSIZE       | 64
-  MIPS  | KVM_REG_MIPS_CP0_WIRED        | 32
-  MIPS  | KVM_REG_MIPS_CP0_PWCTL        | 32
-  MIPS  | KVM_REG_MIPS_CP0_HWRENA       | 32
-  MIPS  | KVM_REG_MIPS_CP0_BADVADDR     | 64
-  MIPS  | KVM_REG_MIPS_CP0_BADINSTR     | 32
-  MIPS  | KVM_REG_MIPS_CP0_BADINSTRP    | 32
-  MIPS  | KVM_REG_MIPS_CP0_COUNT        | 32
-  MIPS  | KVM_REG_MIPS_CP0_ENTRYHI      | 64
-  MIPS  | KVM_REG_MIPS_CP0_COMPARE      | 32
-  MIPS  | KVM_REG_MIPS_CP0_STATUS       | 32
-  MIPS  | KVM_REG_MIPS_CP0_INTCTL       | 32
-  MIPS  | KVM_REG_MIPS_CP0_CAUSE        | 32
-  MIPS  | KVM_REG_MIPS_CP0_EPC          | 64
-  MIPS  | KVM_REG_MIPS_CP0_PRID         | 32
-  MIPS  | KVM_REG_MIPS_CP0_EBASE        | 64
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG       | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG1      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG2      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG3      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG4      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG5      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG7      | 32
-  MIPS  | KVM_REG_MIPS_CP0_XCONTEXT     | 64
-  MIPS  | KVM_REG_MIPS_CP0_ERROREPC     | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH1    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH2    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH3    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH4    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH5    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH6    | 64
-  MIPS  | KVM_REG_MIPS_CP0_MAAR(0..63)  | 64
-  MIPS  | KVM_REG_MIPS_COUNT_CTL        | 64
-  MIPS  | KVM_REG_MIPS_COUNT_RESUME     | 64
-  MIPS  | KVM_REG_MIPS_COUNT_HZ         | 64
-  MIPS  | KVM_REG_MIPS_FPR_32(0..31)    | 32
-  MIPS  | KVM_REG_MIPS_FPR_64(0..31)    | 64
-  MIPS  | KVM_REG_MIPS_VEC_128(0..31)   | 128
-  MIPS  | KVM_REG_MIPS_FCR_IR           | 32
-  MIPS  | KVM_REG_MIPS_FCR_CSR          | 32
-  MIPS  | KVM_REG_MIPS_MSA_IR           | 32
-  MIPS  | KVM_REG_MIPS_MSA_CSR          | 32
-
-ARM registers are mapped using the lower 32 bits.  The upper 16 of that
-is the register group type, or coprocessor number:
-
-ARM core registers have the following id bit patterns:
-  0x4020 0000 0010 <index into the kvm_regs struct:16>
-
-ARM 32-bit CP15 registers have the following id bit patterns:
-  0x4020 0000 000F <zero:1> <crn:4> <crm:4> <opc1:4> <opc2:3>
-
-ARM 64-bit CP15 registers have the following id bit patterns:
-  0x4030 0000 000F <zero:1> <zero:4> <crm:4> <opc1:4> <zero:3>
-
-ARM CCSIDR registers are demultiplexed by CSSELR value:
-  0x4020 0000 0011 00 <csselr:8>
-
-ARM 32-bit VFP control registers have the following id bit patterns:
-  0x4020 0000 0012 1 <regno:12>
-
-ARM 64-bit FP registers have the following id bit patterns:
-  0x4030 0000 0012 0 <regno:12>
-
-ARM firmware pseudo-registers have the following bit pattern:
-  0x4030 0000 0014 <regno:16>
-
-
-arm64 registers are mapped using the lower 32 bits. The upper 16 of
-that is the register group type, or coprocessor number:
-
-arm64 core/FP-SIMD registers have the following id bit patterns. Note
-that the size of the access is variable, as the kvm_regs structure
-contains elements ranging from 32 to 128 bits. The index is a 32bit
-value in the kvm_regs structure seen as a 32bit array.
-  0x60x0 0000 0010 <index into the kvm_regs struct:16>
-
-Specifically:
-    Encoding            Register  Bits  kvm_regs member
-----------------------------------------------------------------
-  0x6030 0000 0010 0000 X0          64  regs.regs[0]
-  0x6030 0000 0010 0002 X1          64  regs.regs[1]
-    ...
-  0x6030 0000 0010 003c X30         64  regs.regs[30]
-  0x6030 0000 0010 003e SP          64  regs.sp
-  0x6030 0000 0010 0040 PC          64  regs.pc
-  0x6030 0000 0010 0042 PSTATE      64  regs.pstate
-  0x6030 0000 0010 0044 SP_EL1      64  sp_el1
-  0x6030 0000 0010 0046 ELR_EL1     64  elr_el1
-  0x6030 0000 0010 0048 SPSR_EL1    64  spsr[KVM_SPSR_EL1] (alias SPSR_SVC)
-  0x6030 0000 0010 004a SPSR_ABT    64  spsr[KVM_SPSR_ABT]
-  0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
-  0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
-  0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
-  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]    (*)
-  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]    (*)
-    ...
-  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]   (*)
-  0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
-  0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
-
-(*) These encodings are not accepted for SVE-enabled vcpus.  See
-    KVM_ARM_VCPU_INIT.
-
-    The equivalent register content can be accessed via bits [127:0] of
-    the corresponding SVE Zn registers instead for vcpus that have SVE
-    enabled (see below).
-
-arm64 CCSIDR registers are demultiplexed by CSSELR value:
-  0x6020 0000 0011 00 <csselr:8>
-
-arm64 system registers have the following id bit patterns:
-  0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3>
-
-arm64 firmware pseudo-registers have the following bit pattern:
-  0x6030 0000 0014 <regno:16>
-
-arm64 SVE registers have the following bit patterns:
-  0x6080 0000 0015 00 <n:5> <slice:5>   Zn bits[2048*slice + 2047 : 2048*slice]
-  0x6050 0000 0015 04 <n:4> <slice:5>   Pn bits[256*slice + 255 : 256*slice]
-  0x6050 0000 0015 060 <slice:5>        FFR bits[256*slice + 255 : 256*slice]
-  0x6060 0000 0015 ffff                 KVM_REG_ARM64_SVE_VLS pseudo-register
-
-Access to register IDs where 2048 * slice >= 128 * max_vq will fail with
-ENOENT.  max_vq is the vcpu's maximum supported vector length in 128-bit
-quadwords: see (**) below.
-
-These registers are only accessible on vcpus for which SVE is enabled.
-See KVM_ARM_VCPU_INIT for details.
-
-In addition, except for KVM_REG_ARM64_SVE_VLS, these registers are not
-accessible until the vcpu's SVE configuration has been finalized
-using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).  See KVM_ARM_VCPU_INIT
-and KVM_ARM_VCPU_FINALIZE for more information about this procedure.
-
-KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector
-lengths supported by the vcpu to be discovered and configured by
-userspace.  When transferred to or from user memory via KVM_GET_ONE_REG
-or KVM_SET_ONE_REG, the value of this register is of type
-__u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the set of vector lengths as
-follows:
-
-__u64 vector_lengths[KVM_ARM64_SVE_VLS_WORDS];
-
-if (vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX &&
-    ((vector_lengths[(vq - KVM_ARM64_SVE_VQ_MIN) / 64] >>
-               ((vq - KVM_ARM64_SVE_VQ_MIN) % 64)) & 1))
-       /* Vector length vq * 16 bytes supported */
-else
-       /* Vector length vq * 16 bytes not supported */
-
-(**) The maximum value vq for which the above condition is true is
-max_vq.  This is the maximum vector length available to the guest on
-this vcpu, and determines which register slices are visible through
-this ioctl interface.
-
-(See Documentation/arm64/sve.rst for an explanation of the "vq"
-nomenclature.)
-
-KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT.
-KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that
-the host supports.
-
-Userspace may subsequently modify it if desired until the vcpu's SVE
-configuration is finalized using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).
-
-Apart from simply removing all vector lengths from the host set that
-exceed some value, support for arbitrarily chosen sets of vector lengths
-is hardware-dependent and may not be available.  Attempting to configure
-an invalid set of vector lengths via KVM_SET_ONE_REG will fail with
-EINVAL.
-
-After the vcpu's SVE configuration is finalized, further attempts to
-write this register will fail with EPERM.
-
-
-MIPS registers are mapped using the lower 32 bits.  The upper 16 of that is
-the register group type:
-
-MIPS core registers (see above) have the following id bit patterns:
-  0x7030 0000 0000 <reg:16>
-
-MIPS CP0 registers (see KVM_REG_MIPS_CP0_* above) have the following id bit
-patterns depending on whether they're 32-bit or 64-bit registers:
-  0x7020 0000 0001 00 <reg:5> <sel:3>   (32-bit)
-  0x7030 0000 0001 00 <reg:5> <sel:3>   (64-bit)
-
-Note: KVM_REG_MIPS_CP0_ENTRYLO0 and KVM_REG_MIPS_CP0_ENTRYLO1 are the MIPS64
-versions of the EntryLo registers regardless of the word size of the host
-hardware, host kernel, guest, and whether XPA is present in the guest, i.e.
-with the RI and XI bits (if they exist) in bits 63 and 62 respectively, and
-the PFNX field starting at bit 30.
-
-MIPS MAARs (see KVM_REG_MIPS_CP0_MAAR(*) above) have the following id bit
-patterns:
-  0x7030 0000 0001 01 <reg:8>
-
-MIPS KVM control registers (see above) have the following id bit patterns:
-  0x7030 0000 0002 <reg:16>
-
-MIPS FPU registers (see KVM_REG_MIPS_FPR_{32,64}() above) have the following
-id bit patterns depending on the size of the register being accessed. They are
-always accessed according to the current guest FPU mode (Status.FR and
-Config5.FRE), i.e. as the guest would see them, and they become unpredictable
-if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector
-registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they
-overlap the FPU registers:
-  0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers)
-  0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers)
-  0x7040 0000 0003 00 <0:3> <reg:5> (128-bit MSA vector registers)
-
-MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the
-following id bit patterns:
-  0x7020 0000 0003 01 <0:3> <reg:5>
-
-MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the
-following id bit patterns:
-  0x7020 0000 0003 02 <0:3> <reg:5>
-
-
-4.69 KVM_GET_ONE_REG
-
-Capability: KVM_CAP_ONE_REG
-Architectures: all
-Type: vcpu ioctl
-Parameters: struct kvm_one_reg (in and out)
-Returns: 0 on success, negative value on failure
-Errors include:
-  ENOENT:   no such register
-  EINVAL:   invalid register ID, or no such register
-  EPERM:    (arm64) register access not allowed before vcpu finalization
-(These error codes are indicative only: do not rely on a specific error
-code being returned in a specific situation.)
-
-This ioctl allows to receive the value of a single register implemented
-in a vcpu. The register to read is indicated by the "id" field of the
-kvm_one_reg struct passed in. On success, the register value can be found
-at the memory location pointed to by "addr".
-
-The list of registers accessible using this interface is identical to the
-list in 4.68.
-
-
-4.70 KVM_KVMCLOCK_CTRL
-
-Capability: KVM_CAP_KVMCLOCK_CTRL
-Architectures: Any that implement pvclocks (currently x86 only)
-Type: vcpu ioctl
-Parameters: None
-Returns: 0 on success, -1 on error
-
-This signals to the host kernel that the specified guest is being paused by
-userspace.  The host will set a flag in the pvclock structure that is checked
-from the soft lockup watchdog.  The flag is part of the pvclock structure that
-is shared between guest and host, specifically the second bit of the flags
-field of the pvclock_vcpu_time_info structure.  It will be set exclusively by
-the host and read/cleared exclusively by the guest.  The guest operation of
-checking and clearing the flag must an atomic operation so
-load-link/store-conditional, or equivalent must be used.  There are two cases
-where the guest will clear the flag: when the soft lockup watchdog timer resets
-itself or when a soft lockup is detected.  This ioctl can be called any time
-after pausing the vcpu, but before it is resumed.
-
-
-4.71 KVM_SIGNAL_MSI
-
-Capability: KVM_CAP_SIGNAL_MSI
-Architectures: x86 arm arm64
-Type: vm ioctl
-Parameters: struct kvm_msi (in)
-Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
-
-Directly inject a MSI message. Only valid with in-kernel irqchip that handles
-MSI messages.
-
-struct kvm_msi {
-       __u32 address_lo;
-       __u32 address_hi;
-       __u32 data;
-       __u32 flags;
-       __u32 devid;
-       __u8  pad[12];
-};
-
-flags: KVM_MSI_VALID_DEVID: devid contains a valid value.  The per-VM
-  KVM_CAP_MSI_DEVID capability advertises the requirement to provide
-  the device ID.  If this capability is not available, userspace
-  should never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
-
-If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
-for the device that wrote the MSI message.  For PCI, this is usually a
-BFD identifier in the lower 16 bits.
-
-On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
-feature of KVM_CAP_X2APIC_API capability is enabled.  If it is enabled,
-address_hi bits 31-8 provide bits 31-8 of the destination id.  Bits 7-0 of
-address_hi must be zero.
-
-
-4.71 KVM_CREATE_PIT2
-
-Capability: KVM_CAP_PIT2
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_pit_config (in)
-Returns: 0 on success, -1 on error
-
-Creates an in-kernel device model for the i8254 PIT. This call is only valid
-after enabling in-kernel irqchip support via KVM_CREATE_IRQCHIP. The following
-parameters have to be passed:
-
-struct kvm_pit_config {
-       __u32 flags;
-       __u32 pad[15];
-};
-
-Valid flags are:
-
-#define KVM_PIT_SPEAKER_DUMMY     1 /* emulate speaker port stub */
-
-PIT timer interrupts may use a per-VM kernel thread for injection. If it
-exists, this thread will have a name of the following pattern:
-
-kvm-pit/<owner-process-pid>
-
-When running a guest with elevated priorities, the scheduling parameters of
-this thread may have to be adjusted accordingly.
-
-This IOCTL replaces the obsolete KVM_CREATE_PIT.
-
-
-4.72 KVM_GET_PIT2
-
-Capability: KVM_CAP_PIT_STATE2
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_pit_state2 (out)
-Returns: 0 on success, -1 on error
-
-Retrieves the state of the in-kernel PIT model. Only valid after
-KVM_CREATE_PIT2. The state is returned in the following structure:
-
-struct kvm_pit_state2 {
-       struct kvm_pit_channel_state channels[3];
-       __u32 flags;
-       __u32 reserved[9];
-};
-
-Valid flags are:
-
-/* disable PIT in HPET legacy mode */
-#define KVM_PIT_FLAGS_HPET_LEGACY  0x00000001
-
-This IOCTL replaces the obsolete KVM_GET_PIT.
-
-
-4.73 KVM_SET_PIT2
-
-Capability: KVM_CAP_PIT_STATE2
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_pit_state2 (in)
-Returns: 0 on success, -1 on error
-
-Sets the state of the in-kernel PIT model. Only valid after KVM_CREATE_PIT2.
-See KVM_GET_PIT2 for details on struct kvm_pit_state2.
-
-This IOCTL replaces the obsolete KVM_SET_PIT.
-
-
-4.74 KVM_PPC_GET_SMMU_INFO
-
-Capability: KVM_CAP_PPC_GET_SMMU_INFO
-Architectures: powerpc
-Type: vm ioctl
-Parameters: None
-Returns: 0 on success, -1 on error
-
-This populates and returns a structure describing the features of
-the "Server" class MMU emulation supported by KVM.
-This can in turn be used by userspace to generate the appropriate
-device-tree properties for the guest operating system.
-
-The structure contains some global information, followed by an
-array of supported segment page sizes:
-
-      struct kvm_ppc_smmu_info {
-            __u64 flags;
-            __u32 slb_size;
-            __u32 pad;
-            struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
-      };
-
-The supported flags are:
-
-    - KVM_PPC_PAGE_SIZES_REAL:
-        When that flag is set, guest page sizes must "fit" the backing
-        store page sizes. When not set, any page size in the list can
-        be used regardless of how they are backed by userspace.
-
-    - KVM_PPC_1T_SEGMENTS
-        The emulated MMU supports 1T segments in addition to the
-        standard 256M ones.
-
-    - KVM_PPC_NO_HASH
-       This flag indicates that HPT guests are not supported by KVM,
-       thus all guests must use radix MMU mode.
-
-The "slb_size" field indicates how many SLB entries are supported
-
-The "sps" array contains 8 entries indicating the supported base
-page sizes for a segment in increasing order. Each entry is defined
-as follow:
-
-   struct kvm_ppc_one_seg_page_size {
-       __u32 page_shift;       /* Base page shift of segment (or 0) */
-       __u32 slb_enc;          /* SLB encoding for BookS */
-       struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
-   };
-
-An entry with a "page_shift" of 0 is unused. Because the array is
-organized in increasing order, a lookup can stop when encoutering
-such an entry.
-
-The "slb_enc" field provides the encoding to use in the SLB for the
-page size. The bits are in positions such as the value can directly
-be OR'ed into the "vsid" argument of the slbmte instruction.
-
-The "enc" array is a list which for each of those segment base page
-size provides the list of supported actual page sizes (which can be
-only larger or equal to the base page size), along with the
-corresponding encoding in the hash PTE. Similarly, the array is
-8 entries sorted by increasing sizes and an entry with a "0" shift
-is an empty entry and a terminator:
-
-   struct kvm_ppc_one_page_size {
-       __u32 page_shift;       /* Page shift (or 0) */
-       __u32 pte_enc;          /* Encoding in the HPTE (>>12) */
-   };
-
-The "pte_enc" field provides a value that can OR'ed into the hash
-PTE's RPN field (ie, it needs to be shifted left by 12 to OR it
-into the hash PTE second double word).
-
-4.75 KVM_IRQFD
-
-Capability: KVM_CAP_IRQFD
-Architectures: x86 s390 arm arm64
-Type: vm ioctl
-Parameters: struct kvm_irqfd (in)
-Returns: 0 on success, -1 on error
-
-Allows setting an eventfd to directly trigger a guest interrupt.
-kvm_irqfd.fd specifies the file descriptor to use as the eventfd and
-kvm_irqfd.gsi specifies the irqchip pin toggled by this event.  When
-an event is triggered on the eventfd, an interrupt is injected into
-the guest using the specified gsi pin.  The irqfd is removed using
-the KVM_IRQFD_FLAG_DEASSIGN flag, specifying both kvm_irqfd.fd
-and kvm_irqfd.gsi.
-
-With KVM_CAP_IRQFD_RESAMPLE, KVM_IRQFD supports a de-assert and notify
-mechanism allowing emulation of level-triggered, irqfd-based
-interrupts.  When KVM_IRQFD_FLAG_RESAMPLE is set the user must pass an
-additional eventfd in the kvm_irqfd.resamplefd field.  When operating
-in resample mode, posting of an interrupt through kvm_irq.fd asserts
-the specified gsi in the irqchip.  When the irqchip is resampled, such
-as from an EOI, the gsi is de-asserted and the user is notified via
-kvm_irqfd.resamplefd.  It is the user's responsibility to re-queue
-the interrupt if the device making use of it still requires service.
-Note that closing the resamplefd is not sufficient to disable the
-irqfd.  The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
-and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
-
-On arm/arm64, gsi routing being supported, the following can happen:
-- in case no routing entry is associated to this gsi, injection fails
-- in case the gsi is associated to an irqchip routing entry,
-  irqchip.pin + 32 corresponds to the injected SPI ID.
-- in case the gsi is associated to an MSI routing entry, the MSI
-  message and device ID are translated into an LPI (support restricted
-  to GICv3 ITS in-kernel emulation).
-
-4.76 KVM_PPC_ALLOCATE_HTAB
-
-Capability: KVM_CAP_PPC_ALLOC_HTAB
-Architectures: powerpc
-Type: vm ioctl
-Parameters: Pointer to u32 containing hash table order (in/out)
-Returns: 0 on success, -1 on error
-
-This requests the host kernel to allocate an MMU hash table for a
-guest using the PAPR paravirtualization interface.  This only does
-anything if the kernel is configured to use the Book 3S HV style of
-virtualization.  Otherwise the capability doesn't exist and the ioctl
-returns an ENOTTY error.  The rest of this description assumes Book 3S
-HV.
-
-There must be no vcpus running when this ioctl is called; if there
-are, it will do nothing and return an EBUSY error.
-
-The parameter is a pointer to a 32-bit unsigned integer variable
-containing the order (log base 2) of the desired size of the hash
-table, which must be between 18 and 46.  On successful return from the
-ioctl, the value will not be changed by the kernel.
-
-If no hash table has been allocated when any vcpu is asked to run
-(with the KVM_RUN ioctl), the host kernel will allocate a
-default-sized hash table (16 MB).
-
-If this ioctl is called when a hash table has already been allocated,
-with a different order from the existing hash table, the existing hash
-table will be freed and a new one allocated.  If this is ioctl is
-called when a hash table has already been allocated of the same order
-as specified, the kernel will clear out the existing hash table (zero
-all HPTEs).  In either case, if the guest is using the virtualized
-real-mode area (VRMA) facility, the kernel will re-create the VMRA
-HPTEs on the next KVM_RUN of any vcpu.
-
-4.77 KVM_S390_INTERRUPT
-
-Capability: basic
-Architectures: s390
-Type: vm ioctl, vcpu ioctl
-Parameters: struct kvm_s390_interrupt (in)
-Returns: 0 on success, -1 on error
-
-Allows to inject an interrupt to the guest. Interrupts can be floating
-(vm ioctl) or per cpu (vcpu ioctl), depending on the interrupt type.
-
-Interrupt parameters are passed via kvm_s390_interrupt:
-
-struct kvm_s390_interrupt {
-       __u32 type;
-       __u32 parm;
-       __u64 parm64;
-};
-
-type can be one of the following:
-
-KVM_S390_SIGP_STOP (vcpu) - sigp stop; optional flags in parm
-KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
-KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
-KVM_S390_RESTART (vcpu) - restart
-KVM_S390_INT_CLOCK_COMP (vcpu) - clock comparator interrupt
-KVM_S390_INT_CPU_TIMER (vcpu) - CPU timer interrupt
-KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
-                          parameters in parm and parm64
-KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
-KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
-KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
-KVM_S390_INT_IO(ai,cssid,ssid,schid) (vm) - compound value to indicate an
-    I/O interrupt (ai - adapter interrupt; cssid,ssid,schid - subchannel);
-    I/O interruption parameters in parm (subchannel) and parm64 (intparm,
-    interruption subclass)
-KVM_S390_MCHK (vm, vcpu) - machine check interrupt; cr 14 bits in parm,
-                           machine check interrupt code in parm64 (note that
-                           machine checks needing further payload are not
-                           supported by this ioctl)
-
-This is an asynchronous vcpu ioctl and can be invoked from any thread.
-
-4.78 KVM_PPC_GET_HTAB_FD
-
-Capability: KVM_CAP_PPC_HTAB_FD
-Architectures: powerpc
-Type: vm ioctl
-Parameters: Pointer to struct kvm_get_htab_fd (in)
-Returns: file descriptor number (>= 0) on success, -1 on error
-
-This returns a file descriptor that can be used either to read out the
-entries in the guest's hashed page table (HPT), or to write entries to
-initialize the HPT.  The returned fd can only be written to if the
-KVM_GET_HTAB_WRITE bit is set in the flags field of the argument, and
-can only be read if that bit is clear.  The argument struct looks like
-this:
-
-/* For KVM_PPC_GET_HTAB_FD */
-struct kvm_get_htab_fd {
-       __u64   flags;
-       __u64   start_index;
-       __u64   reserved[2];
-};
-
-/* Values for kvm_get_htab_fd.flags */
-#define KVM_GET_HTAB_BOLTED_ONLY       ((__u64)0x1)
-#define KVM_GET_HTAB_WRITE             ((__u64)0x2)
-
-The `start_index' field gives the index in the HPT of the entry at
-which to start reading.  It is ignored when writing.
-
-Reads on the fd will initially supply information about all
-"interesting" HPT entries.  Interesting entries are those with the
-bolted bit set, if the KVM_GET_HTAB_BOLTED_ONLY bit is set, otherwise
-all entries.  When the end of the HPT is reached, the read() will
-return.  If read() is called again on the fd, it will start again from
-the beginning of the HPT, but will only return HPT entries that have
-changed since they were last read.
-
-Data read or written is structured as a header (8 bytes) followed by a
-series of valid HPT entries (16 bytes) each.  The header indicates how
-many valid HPT entries there are and how many invalid entries follow
-the valid entries.  The invalid entries are not represented explicitly
-in the stream.  The header format is:
-
-struct kvm_get_htab_header {
-       __u32   index;
-       __u16   n_valid;
-       __u16   n_invalid;
-};
-
-Writes to the fd create HPT entries starting at the index given in the
-header; first `n_valid' valid entries with contents from the data
-written, then `n_invalid' invalid entries, invalidating any previously
-valid entries found.
-
-4.79 KVM_CREATE_DEVICE
-
-Capability: KVM_CAP_DEVICE_CTRL
-Type: vm ioctl
-Parameters: struct kvm_create_device (in/out)
-Returns: 0 on success, -1 on error
-Errors:
-  ENODEV: The device type is unknown or unsupported
-  EEXIST: Device already created, and this type of device may not
-          be instantiated multiple times
-
-  Other error conditions may be defined by individual device types or
-  have their standard meanings.
-
-Creates an emulated device in the kernel.  The file descriptor returned
-in fd can be used with KVM_SET/GET/HAS_DEVICE_ATTR.
-
-If the KVM_CREATE_DEVICE_TEST flag is set, only test whether the
-device type is supported (not necessarily whether it can be created
-in the current vm).
-
-Individual devices should not define flags.  Attributes should be used
-for specifying any behavior that is not implied by the device type
-number.
-
-struct kvm_create_device {
-       __u32   type;   /* in: KVM_DEV_TYPE_xxx */
-       __u32   fd;     /* out: device handle */
-       __u32   flags;  /* in: KVM_CREATE_DEVICE_xxx */
-};
-
-4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR
-
-Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
-  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
-Type: device ioctl, vm ioctl, vcpu ioctl
-Parameters: struct kvm_device_attr
-Returns: 0 on success, -1 on error
-Errors:
-  ENXIO:  The group or attribute is unknown/unsupported for this device
-          or hardware support is missing.
-  EPERM:  The attribute cannot (currently) be accessed this way
-          (e.g. read-only attribute, or attribute that only makes
-          sense when the device is in a different state)
-
-  Other error conditions may be defined by individual device types.
-
-Gets/sets a specified piece of device configuration and/or state.  The
-semantics are device-specific.  See individual device documentation in
-the "devices" directory.  As with ONE_REG, the size of the data
-transferred is defined by the particular attribute.
-
-struct kvm_device_attr {
-       __u32   flags;          /* no flags currently defined */
-       __u32   group;          /* device-defined */
-       __u64   attr;           /* group-defined */
-       __u64   addr;           /* userspace address of attr data */
-};
-
-4.81 KVM_HAS_DEVICE_ATTR
-
-Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
-  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
-Type: device ioctl, vm ioctl, vcpu ioctl
-Parameters: struct kvm_device_attr
-Returns: 0 on success, -1 on error
-Errors:
-  ENXIO:  The group or attribute is unknown/unsupported for this device
-          or hardware support is missing.
-
-Tests whether a device supports a particular attribute.  A successful
-return indicates the attribute is implemented.  It does not necessarily
-indicate that the attribute can be read or written in the device's
-current state.  "addr" is ignored.
-
-4.82 KVM_ARM_VCPU_INIT
-
-Capability: basic
-Architectures: arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_vcpu_init (in)
-Returns: 0 on success; -1 on error
-Errors:
-  EINVAL:    the target is unknown, or the combination of features is invalid.
-  ENOENT:    a features bit specified is unknown.
-
-This tells KVM what type of CPU to present to the guest, and what
-optional features it should have.  This will cause a reset of the cpu
-registers to their initial values.  If this is not called, KVM_RUN will
-return ENOEXEC for that vcpu.
-
-Note that because some registers reflect machine topology, all vcpus
-should be created before this ioctl is invoked.
-
-Userspace can call this function multiple times for a given vcpu, including
-after the vcpu has been run. This will reset the vcpu to its initial
-state. All calls to this function after the initial call must use the same
-target and same set of feature flags, otherwise EINVAL will be returned.
-
-Possible features:
-       - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state.
-         Depends on KVM_CAP_ARM_PSCI.  If not set, the CPU will be powered on
-         and execute guest code when KVM_RUN is called.
-       - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
-         Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
-       - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
-          backward compatible with v0.2) for the CPU.
-         Depends on KVM_CAP_ARM_PSCI_0_2.
-       - KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
-         Depends on KVM_CAP_ARM_PMU_V3.
-
-       - KVM_ARM_VCPU_PTRAUTH_ADDRESS: Enables Address Pointer authentication
-         for arm64 only.
-         Depends on KVM_CAP_ARM_PTRAUTH_ADDRESS.
-         If KVM_CAP_ARM_PTRAUTH_ADDRESS and KVM_CAP_ARM_PTRAUTH_GENERIC are
-         both present, then both KVM_ARM_VCPU_PTRAUTH_ADDRESS and
-         KVM_ARM_VCPU_PTRAUTH_GENERIC must be requested or neither must be
-         requested.
-
-       - KVM_ARM_VCPU_PTRAUTH_GENERIC: Enables Generic Pointer authentication
-         for arm64 only.
-         Depends on KVM_CAP_ARM_PTRAUTH_GENERIC.
-         If KVM_CAP_ARM_PTRAUTH_ADDRESS and KVM_CAP_ARM_PTRAUTH_GENERIC are
-         both present, then both KVM_ARM_VCPU_PTRAUTH_ADDRESS and
-         KVM_ARM_VCPU_PTRAUTH_GENERIC must be requested or neither must be
-         requested.
-
-       - KVM_ARM_VCPU_SVE: Enables SVE for the CPU (arm64 only).
-         Depends on KVM_CAP_ARM_SVE.
-         Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
-
-          * After KVM_ARM_VCPU_INIT:
-
-             - KVM_REG_ARM64_SVE_VLS may be read using KVM_GET_ONE_REG: the
-               initial value of this pseudo-register indicates the best set of
-               vector lengths possible for a vcpu on this host.
-
-          * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
-
-             - KVM_RUN and KVM_GET_REG_LIST are not available;
-
-             - KVM_GET_ONE_REG and KVM_SET_ONE_REG cannot be used to access
-               the scalable archietctural SVE registers
-               KVM_REG_ARM64_SVE_ZREG(), KVM_REG_ARM64_SVE_PREG() or
-               KVM_REG_ARM64_SVE_FFR;
-
-             - KVM_REG_ARM64_SVE_VLS may optionally be written using
-               KVM_SET_ONE_REG, to modify the set of vector lengths available
-               for the vcpu.
-
-          * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
-
-             - the KVM_REG_ARM64_SVE_VLS pseudo-register is immutable, and can
-               no longer be written using KVM_SET_ONE_REG.
-
-4.83 KVM_ARM_PREFERRED_TARGET
-
-Capability: basic
-Architectures: arm, arm64
-Type: vm ioctl
-Parameters: struct struct kvm_vcpu_init (out)
-Returns: 0 on success; -1 on error
-Errors:
-  ENODEV:    no preferred target available for the host
-
-This queries KVM for preferred CPU target type which can be emulated
-by KVM on underlying host.
-
-The ioctl returns struct kvm_vcpu_init instance containing information
-about preferred CPU target type and recommended features for it.  The
-kvm_vcpu_init->features bitmap returned will have feature bits set if
-the preferred target recommends setting these features, but this is
-not mandatory.
-
-The information returned by this ioctl can be used to prepare an instance
-of struct kvm_vcpu_init for KVM_ARM_VCPU_INIT ioctl which will result in
-in VCPU matching underlying host.
-
-
-4.84 KVM_GET_REG_LIST
-
-Capability: basic
-Architectures: arm, arm64, mips
-Type: vcpu ioctl
-Parameters: struct kvm_reg_list (in/out)
-Returns: 0 on success; -1 on error
-Errors:
-  E2BIG:     the reg index list is too big to fit in the array specified by
-             the user (the number required will be written into n).
-
-struct kvm_reg_list {
-       __u64 n; /* number of registers in reg[] */
-       __u64 reg[0];
-};
-
-This ioctl returns the guest registers that are supported for the
-KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
-
-
-4.85 KVM_ARM_SET_DEVICE_ADDR (deprecated)
-
-Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
-Architectures: arm, arm64
-Type: vm ioctl
-Parameters: struct kvm_arm_device_address (in)
-Returns: 0 on success, -1 on error
-Errors:
-  ENODEV: The device id is unknown
-  ENXIO:  Device not supported on current system
-  EEXIST: Address already set
-  E2BIG:  Address outside guest physical address space
-  EBUSY:  Address overlaps with other device range
-
-struct kvm_arm_device_addr {
-       __u64 id;
-       __u64 addr;
-};
-
-Specify a device address in the guest's physical address space where guests
-can access emulated or directly exposed devices, which the host kernel needs
-to know about. The id field is an architecture specific identifier for a
-specific device.
-
-ARM/arm64 divides the id field into two parts, a device id and an
-address type id specific to the individual device.
-
-  bits:  | 63        ...       32 | 31    ...    16 | 15    ...    0 |
-  field: |        0x00000000      |     device id   |  addr type id  |
-
-ARM/arm64 currently only require this when using the in-kernel GIC
-support for the hardware VGIC features, using KVM_ARM_DEVICE_VGIC_V2
-as the device id.  When setting the base address for the guest's
-mapping of the VGIC virtual CPU and distributor interface, the ioctl
-must be called after calling KVM_CREATE_IRQCHIP, but before calling
-KVM_RUN on any of the VCPUs.  Calling this ioctl twice for any of the
-base addresses will return -EEXIST.
-
-Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
-should be used instead.
-
-
-4.86 KVM_PPC_RTAS_DEFINE_TOKEN
-
-Capability: KVM_CAP_PPC_RTAS
-Architectures: ppc
-Type: vm ioctl
-Parameters: struct kvm_rtas_token_args
-Returns: 0 on success, -1 on error
-
-Defines a token value for a RTAS (Run Time Abstraction Services)
-service in order to allow it to be handled in the kernel.  The
-argument struct gives the name of the service, which must be the name
-of a service that has a kernel-side implementation.  If the token
-value is non-zero, it will be associated with that service, and
-subsequent RTAS calls by the guest specifying that token will be
-handled by the kernel.  If the token value is 0, then any token
-associated with the service will be forgotten, and subsequent RTAS
-calls by the guest for that service will be passed to userspace to be
-handled.
-
-4.87 KVM_SET_GUEST_DEBUG
-
-Capability: KVM_CAP_SET_GUEST_DEBUG
-Architectures: x86, s390, ppc, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_guest_debug (in)
-Returns: 0 on success; -1 on error
-
-struct kvm_guest_debug {
-       __u32 control;
-       __u32 pad;
-       struct kvm_guest_debug_arch arch;
-};
-
-Set up the processor specific debug registers and configure vcpu for
-handling guest debug events. There are two parts to the structure, the
-first a control bitfield indicates the type of debug events to handle
-when running. Common control bits are:
-
-  - KVM_GUESTDBG_ENABLE:        guest debugging is enabled
-  - KVM_GUESTDBG_SINGLESTEP:    the next run should single-step
-
-The top 16 bits of the control field are architecture specific control
-flags which can include the following:
-
-  - KVM_GUESTDBG_USE_SW_BP:     using software breakpoints [x86, arm64]
-  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390, arm64]
-  - KVM_GUESTDBG_INJECT_DB:     inject DB type exception [x86]
-  - KVM_GUESTDBG_INJECT_BP:     inject BP type exception [x86]
-  - KVM_GUESTDBG_EXIT_PENDING:  trigger an immediate guest exit [s390]
-
-For example KVM_GUESTDBG_USE_SW_BP indicates that software breakpoints
-are enabled in memory so we need to ensure breakpoint exceptions are
-correctly trapped and the KVM run loop exits at the breakpoint and not
-running off into the normal guest vector. For KVM_GUESTDBG_USE_HW_BP
-we need to ensure the guest vCPUs architecture specific registers are
-updated to the correct (supplied) values.
-
-The second part of the structure is architecture specific and
-typically contains a set of debug registers.
-
-For arm64 the number of debug registers is implementation defined and
-can be determined by querying the KVM_CAP_GUEST_DEBUG_HW_BPS and
-KVM_CAP_GUEST_DEBUG_HW_WPS capabilities which return a positive number
-indicating the number of supported registers.
-
-When debug events exit the main run loop with the reason
-KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
-structure containing architecture specific debug information.
-
-4.88 KVM_GET_EMULATED_CPUID
-
-Capability: KVM_CAP_EXT_EMUL_CPUID
-Architectures: x86
-Type: system ioctl
-Parameters: struct kvm_cpuid2 (in/out)
-Returns: 0 on success, -1 on error
-
-struct kvm_cpuid2 {
-       __u32 nent;
-       __u32 flags;
-       struct kvm_cpuid_entry2 entries[0];
-};
-
-The member 'flags' is used for passing flags from userspace.
-
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX                BIT(0)
-#define KVM_CPUID_FLAG_STATEFUL_FUNC           BIT(1)
-#define KVM_CPUID_FLAG_STATE_READ_NEXT         BIT(2)
-
-struct kvm_cpuid_entry2 {
-       __u32 function;
-       __u32 index;
-       __u32 flags;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding[3];
-};
-
-This ioctl returns x86 cpuid features which are emulated by
-kvm.Userspace can use the information returned by this ioctl to query
-which features are emulated by kvm instead of being present natively.
-
-Userspace invokes KVM_GET_EMULATED_CPUID by passing a kvm_cpuid2
-structure with the 'nent' field indicating the number of entries in
-the variable-size array 'entries'. If the number of entries is too low
-to describe the cpu capabilities, an error (E2BIG) is returned. If the
-number is too high, the 'nent' field is adjusted and an error (ENOMEM)
-is returned. If the number is just right, the 'nent' field is adjusted
-to the number of valid entries in the 'entries' array, which is then
-filled.
-
-The entries returned are the set CPUID bits of the respective features
-which kvm emulates, as returned by the CPUID instruction, with unknown
-or unsupported feature bits cleared.
-
-Features like x2apic, for example, may not be present in the host cpu
-but are exposed by kvm in KVM_GET_SUPPORTED_CPUID because they can be
-emulated efficiently and thus not included here.
-
-The fields in each entry are defined as follows:
-
-  function: the eax value used to obtain the entry
-  index: the ecx value used to obtain the entry (for entries that are
-         affected by ecx)
-  flags: an OR of zero or more of the following:
-        KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
-           if the index field is valid
-        KVM_CPUID_FLAG_STATEFUL_FUNC:
-           if cpuid for this function returns different values for successive
-           invocations; there will be several entries with the same function,
-           all with this flag set
-        KVM_CPUID_FLAG_STATE_READ_NEXT:
-           for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
-           the first entry to be read by a cpu
-   eax, ebx, ecx, edx: the values returned by the cpuid instruction for
-         this function/index combination
-
-4.89 KVM_S390_MEM_OP
-
-Capability: KVM_CAP_S390_MEM_OP
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_mem_op (in)
-Returns: = 0 on success,
-         < 0 on generic error (e.g. -EFAULT or -ENOMEM),
-         > 0 if an exception occurred while walking the page tables
-
-Read or write data from/to the logical (virtual) memory of a VCPU.
-
-Parameters are specified via the following structure:
-
-struct kvm_s390_mem_op {
-       __u64 gaddr;            /* the guest address */
-       __u64 flags;            /* flags */
-       __u32 size;             /* amount of bytes */
-       __u32 op;               /* type of operation */
-       __u64 buf;              /* buffer in userspace */
-       __u8 ar;                /* the access register number */
-       __u8 reserved[31];      /* should be set to 0 */
-};
-
-The type of operation is specified in the "op" field. It is either
-KVM_S390_MEMOP_LOGICAL_READ for reading from logical memory space or
-KVM_S390_MEMOP_LOGICAL_WRITE for writing to logical memory space. The
-KVM_S390_MEMOP_F_CHECK_ONLY flag can be set in the "flags" field to check
-whether the corresponding memory access would create an access exception
-(without touching the data in the memory at the destination). In case an
-access exception occurred while walking the MMU tables of the guest, the
-ioctl returns a positive error number to indicate the type of exception.
-This exception is also raised directly at the corresponding VCPU if the
-flag KVM_S390_MEMOP_F_INJECT_EXCEPTION is set in the "flags" field.
-
-The start address of the memory region has to be specified in the "gaddr"
-field, and the length of the region in the "size" field. "buf" is the buffer
-supplied by the userspace application where the read data should be written
-to for KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written
-is stored for a KVM_S390_MEMOP_LOGICAL_WRITE. "buf" is unused and can be NULL
-when KVM_S390_MEMOP_F_CHECK_ONLY is specified. "ar" designates the access
-register number to be used.
-
-The "reserved" field is meant for future extensions. It is not used by
-KVM with the currently defined set of flags.
-
-4.90 KVM_S390_GET_SKEYS
-
-Capability: KVM_CAP_S390_SKEYS
-Architectures: s390
-Type: vm ioctl
-Parameters: struct kvm_s390_skeys
-Returns: 0 on success, KVM_S390_GET_KEYS_NONE if guest is not using storage
-         keys, negative value on error
-
-This ioctl is used to get guest storage key values on the s390
-architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
-
-struct kvm_s390_skeys {
-       __u64 start_gfn;
-       __u64 count;
-       __u64 skeydata_addr;
-       __u32 flags;
-       __u32 reserved[9];
-};
-
-The start_gfn field is the number of the first guest frame whose storage keys
-you want to get.
-
-The count field is the number of consecutive frames (starting from start_gfn)
-whose storage keys to get. The count field must be at least 1 and the maximum
-allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
-will cause the ioctl to return -EINVAL.
-
-The skeydata_addr field is the address to a buffer large enough to hold count
-bytes. This buffer will be filled with storage key data by the ioctl.
-
-4.91 KVM_S390_SET_SKEYS
-
-Capability: KVM_CAP_S390_SKEYS
-Architectures: s390
-Type: vm ioctl
-Parameters: struct kvm_s390_skeys
-Returns: 0 on success, negative value on error
-
-This ioctl is used to set guest storage key values on the s390
-architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
-See section on KVM_S390_GET_SKEYS for struct definition.
-
-The start_gfn field is the number of the first guest frame whose storage keys
-you want to set.
-
-The count field is the number of consecutive frames (starting from start_gfn)
-whose storage keys to get. The count field must be at least 1 and the maximum
-allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
-will cause the ioctl to return -EINVAL.
-
-The skeydata_addr field is the address to a buffer containing count bytes of
-storage keys. Each byte in the buffer will be set as the storage key for a
-single frame starting at start_gfn for count frames.
-
-Note: If any architecturally invalid key value is found in the given data then
-the ioctl will return -EINVAL.
-
-4.92 KVM_S390_IRQ
-
-Capability: KVM_CAP_S390_INJECT_IRQ
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_irq (in)
-Returns: 0 on success, -1 on error
-Errors:
-  EINVAL: interrupt type is invalid
-          type is KVM_S390_SIGP_STOP and flag parameter is invalid value
-          type is KVM_S390_INT_EXTERNAL_CALL and code is bigger
-            than the maximum of VCPUs
-  EBUSY:  type is KVM_S390_SIGP_SET_PREFIX and vcpu is not stopped
-          type is KVM_S390_SIGP_STOP and a stop irq is already pending
-          type is KVM_S390_INT_EXTERNAL_CALL and an external call interrupt
-            is already pending
-
-Allows to inject an interrupt to the guest.
-
-Using struct kvm_s390_irq as a parameter allows
-to inject additional payload which is not
-possible via KVM_S390_INTERRUPT.
-
-Interrupt parameters are passed via kvm_s390_irq:
-
-struct kvm_s390_irq {
-       __u64 type;
-       union {
-               struct kvm_s390_io_info io;
-               struct kvm_s390_ext_info ext;
-               struct kvm_s390_pgm_info pgm;
-               struct kvm_s390_emerg_info emerg;
-               struct kvm_s390_extcall_info extcall;
-               struct kvm_s390_prefix_info prefix;
-               struct kvm_s390_stop_info stop;
-               struct kvm_s390_mchk_info mchk;
-               char reserved[64];
-       } u;
-};
-
-type can be one of the following:
-
-KVM_S390_SIGP_STOP - sigp stop; parameter in .stop
-KVM_S390_PROGRAM_INT - program check; parameters in .pgm
-KVM_S390_SIGP_SET_PREFIX - sigp set prefix; parameters in .prefix
-KVM_S390_RESTART - restart; no parameters
-KVM_S390_INT_CLOCK_COMP - clock comparator interrupt; no parameters
-KVM_S390_INT_CPU_TIMER - CPU timer interrupt; no parameters
-KVM_S390_INT_EMERGENCY - sigp emergency; parameters in .emerg
-KVM_S390_INT_EXTERNAL_CALL - sigp external call; parameters in .extcall
-KVM_S390_MCHK - machine check interrupt; parameters in .mchk
-
-This is an asynchronous vcpu ioctl and can be invoked from any thread.
-
-4.94 KVM_S390_GET_IRQ_STATE
-
-Capability: KVM_CAP_S390_IRQ_STATE
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_irq_state (out)
-Returns: >= number of bytes copied into buffer,
-         -EINVAL if buffer size is 0,
-         -ENOBUFS if buffer size is too small to fit all pending interrupts,
-         -EFAULT if the buffer address was invalid
-
-This ioctl allows userspace to retrieve the complete state of all currently
-pending interrupts in a single buffer. Use cases include migration
-and introspection. The parameter structure contains the address of a
-userspace buffer and its length:
-
-struct kvm_s390_irq_state {
-       __u64 buf;
-       __u32 flags;        /* will stay unused for compatibility reasons */
-       __u32 len;
-       __u32 reserved[4];  /* will stay unused for compatibility reasons */
-};
-
-Userspace passes in the above struct and for each pending interrupt a
-struct kvm_s390_irq is copied to the provided buffer.
-
-The structure contains a flags and a reserved field for future extensions. As
-the kernel never checked for flags == 0 and QEMU never pre-zeroed flags and
-reserved, these fields can not be used in the future without breaking
-compatibility.
-
-If -ENOBUFS is returned the buffer provided was too small and userspace
-may retry with a bigger buffer.
-
-4.95 KVM_S390_SET_IRQ_STATE
-
-Capability: KVM_CAP_S390_IRQ_STATE
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_irq_state (in)
-Returns: 0 on success,
-         -EFAULT if the buffer address was invalid,
-         -EINVAL for an invalid buffer length (see below),
-         -EBUSY if there were already interrupts pending,
-         errors occurring when actually injecting the
-          interrupt. See KVM_S390_IRQ.
-
-This ioctl allows userspace to set the complete state of all cpu-local
-interrupts currently pending for the vcpu. It is intended for restoring
-interrupt state after a migration. The input parameter is a userspace buffer
-containing a struct kvm_s390_irq_state:
-
-struct kvm_s390_irq_state {
-       __u64 buf;
-       __u32 flags;        /* will stay unused for compatibility reasons */
-       __u32 len;
-       __u32 reserved[4];  /* will stay unused for compatibility reasons */
-};
-
-The restrictions for flags and reserved apply as well.
-(see KVM_S390_GET_IRQ_STATE)
-
-The userspace memory referenced by buf contains a struct kvm_s390_irq
-for each interrupt to be injected into the guest.
-If one of the interrupts could not be injected for some reason the
-ioctl aborts.
-
-len must be a multiple of sizeof(struct kvm_s390_irq). It must be > 0
-and it must not exceed (max_vcpus + 32) * sizeof(struct kvm_s390_irq),
-which is the maximum number of possibly pending cpu-local interrupts.
-
-4.96 KVM_SMI
-
-Capability: KVM_CAP_X86_SMM
-Architectures: x86
-Type: vcpu ioctl
-Parameters: none
-Returns: 0 on success, -1 on error
-
-Queues an SMI on the thread's vcpu.
-
-4.97 KVM_CAP_PPC_MULTITCE
-
-Capability: KVM_CAP_PPC_MULTITCE
-Architectures: ppc
-Type: vm
-
-This capability means the kernel is capable of handling hypercalls
-H_PUT_TCE_INDIRECT and H_STUFF_TCE without passing those into the user
-space. This significantly accelerates DMA operations for PPC KVM guests.
-User space should expect that its handlers for these hypercalls
-are not going to be called if user space previously registered LIOBN
-in KVM (via KVM_CREATE_SPAPR_TCE or similar calls).
-
-In order to enable H_PUT_TCE_INDIRECT and H_STUFF_TCE use in the guest,
-user space might have to advertise it for the guest. For example,
-IBM pSeries (sPAPR) guest starts using them if "hcall-multi-tce" is
-present in the "ibm,hypertas-functions" device-tree property.
-
-The hypercalls mentioned above may or may not be processed successfully
-in the kernel based fast path. If they can not be handled by the kernel,
-they will get passed on to user space. So user space still has to have
-an implementation for these despite the in kernel acceleration.
-
-This capability is always enabled.
-
-4.98 KVM_CREATE_SPAPR_TCE_64
-
-Capability: KVM_CAP_SPAPR_TCE_64
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_create_spapr_tce_64 (in)
-Returns: file descriptor for manipulating the created TCE table
-
-This is an extension for KVM_CAP_SPAPR_TCE which only supports 32bit
-windows, described in 4.62 KVM_CREATE_SPAPR_TCE
-
-This capability uses extended struct in ioctl interface:
-
-/* for KVM_CAP_SPAPR_TCE_64 */
-struct kvm_create_spapr_tce_64 {
-       __u64 liobn;
-       __u32 page_shift;
-       __u32 flags;
-       __u64 offset;   /* in pages */
-       __u64 size;     /* in pages */
-};
-
-The aim of extension is to support an additional bigger DMA window with
-a variable page size.
-KVM_CREATE_SPAPR_TCE_64 receives a 64bit window size, an IOMMU page shift and
-a bus offset of the corresponding DMA window, @size and @offset are numbers
-of IOMMU pages.
-
-@flags are not used at the moment.
-
-The rest of functionality is identical to KVM_CREATE_SPAPR_TCE.
-
-4.99 KVM_REINJECT_CONTROL
-
-Capability: KVM_CAP_REINJECT_CONTROL
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_reinject_control (in)
-Returns: 0 on success,
-         -EFAULT if struct kvm_reinject_control cannot be read,
-         -ENXIO if KVM_CREATE_PIT or KVM_CREATE_PIT2 didn't succeed earlier.
-
-i8254 (PIT) has two modes, reinject and !reinject.  The default is reinject,
-where KVM queues elapsed i8254 ticks and monitors completion of interrupt from
-vector(s) that i8254 injects.  Reinject mode dequeues a tick and injects its
-interrupt whenever there isn't a pending interrupt from i8254.
-!reinject mode injects an interrupt as soon as a tick arrives.
-
-struct kvm_reinject_control {
-       __u8 pit_reinject;
-       __u8 reserved[31];
-};
-
-pit_reinject = 0 (!reinject mode) is recommended, unless running an old
-operating system that uses the PIT for timing (e.g. Linux 2.4.x).
-
-4.100 KVM_PPC_CONFIGURE_V3_MMU
-
-Capability: KVM_CAP_PPC_RADIX_MMU or KVM_CAP_PPC_HASH_MMU_V3
-Architectures: ppc
-Type: vm ioctl
-Parameters: struct kvm_ppc_mmuv3_cfg (in)
-Returns: 0 on success,
-         -EFAULT if struct kvm_ppc_mmuv3_cfg cannot be read,
-         -EINVAL if the configuration is invalid
-
-This ioctl controls whether the guest will use radix or HPT (hashed
-page table) translation, and sets the pointer to the process table for
-the guest.
-
-struct kvm_ppc_mmuv3_cfg {
-       __u64   flags;
-       __u64   process_table;
-};
-
-There are two bits that can be set in flags; KVM_PPC_MMUV3_RADIX and
-KVM_PPC_MMUV3_GTSE.  KVM_PPC_MMUV3_RADIX, if set, configures the guest
-to use radix tree translation, and if clear, to use HPT translation.
-KVM_PPC_MMUV3_GTSE, if set and if KVM permits it, configures the guest
-to be able to use the global TLB and SLB invalidation instructions;
-if clear, the guest may not use these instructions.
-
-The process_table field specifies the address and size of the guest
-process table, which is in the guest's space.  This field is formatted
-as the second doubleword of the partition table entry, as defined in
-the Power ISA V3.00, Book III section 5.7.6.1.
-
-4.101 KVM_PPC_GET_RMMU_INFO
-
-Capability: KVM_CAP_PPC_RADIX_MMU
-Architectures: ppc
-Type: vm ioctl
-Parameters: struct kvm_ppc_rmmu_info (out)
-Returns: 0 on success,
-        -EFAULT if struct kvm_ppc_rmmu_info cannot be written,
-        -EINVAL if no useful information can be returned
-
-This ioctl returns a structure containing two things: (a) a list
-containing supported radix tree geometries, and (b) a list that maps
-page sizes to put in the "AP" (actual page size) field for the tlbie
-(TLB invalidate entry) instruction.
-
-struct kvm_ppc_rmmu_info {
-       struct kvm_ppc_radix_geom {
-               __u8    page_shift;
-               __u8    level_bits[4];
-               __u8    pad[3];
-       }       geometries[8];
-       __u32   ap_encodings[8];
-};
-
-The geometries[] field gives up to 8 supported geometries for the
-radix page table, in terms of the log base 2 of the smallest page
-size, and the number of bits indexed at each level of the tree, from
-the PTE level up to the PGD level in that order.  Any unused entries
-will have 0 in the page_shift field.
-
-The ap_encodings gives the supported page sizes and their AP field
-encodings, encoded with the AP value in the top 3 bits and the log
-base 2 of the page size in the bottom 6 bits.
-
-4.102 KVM_PPC_RESIZE_HPT_PREPARE
-
-Capability: KVM_CAP_SPAPR_RESIZE_HPT
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_ppc_resize_hpt (in)
-Returns: 0 on successful completion,
-        >0 if a new HPT is being prepared, the value is an estimated
-             number of milliseconds until preparation is complete
-         -EFAULT if struct kvm_reinject_control cannot be read,
-        -EINVAL if the supplied shift or flags are invalid
-        -ENOMEM if unable to allocate the new HPT
-        -ENOSPC if there was a hash collision when moving existing
-                  HPT entries to the new HPT
-        -EIO on other error conditions
-
-Used to implement the PAPR extension for runtime resizing of a guest's
-Hashed Page Table (HPT).  Specifically this starts, stops or monitors
-the preparation of a new potential HPT for the guest, essentially
-implementing the H_RESIZE_HPT_PREPARE hypercall.
-
-If called with shift > 0 when there is no pending HPT for the guest,
-this begins preparation of a new pending HPT of size 2^(shift) bytes.
-It then returns a positive integer with the estimated number of
-milliseconds until preparation is complete.
-
-If called when there is a pending HPT whose size does not match that
-requested in the parameters, discards the existing pending HPT and
-creates a new one as above.
-
-If called when there is a pending HPT of the size requested, will:
-  * If preparation of the pending HPT is already complete, return 0
-  * If preparation of the pending HPT has failed, return an error
-    code, then discard the pending HPT.
-  * If preparation of the pending HPT is still in progress, return an
-    estimated number of milliseconds until preparation is complete.
-
-If called with shift == 0, discards any currently pending HPT and
-returns 0 (i.e. cancels any in-progress preparation).
-
-flags is reserved for future expansion, currently setting any bits in
-flags will result in an -EINVAL.
-
-Normally this will be called repeatedly with the same parameters until
-it returns <= 0.  The first call will initiate preparation, subsequent
-ones will monitor preparation until it completes or fails.
-
-struct kvm_ppc_resize_hpt {
-       __u64 flags;
-       __u32 shift;
-       __u32 pad;
-};
-
-4.103 KVM_PPC_RESIZE_HPT_COMMIT
-
-Capability: KVM_CAP_SPAPR_RESIZE_HPT
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_ppc_resize_hpt (in)
-Returns: 0 on successful completion,
-         -EFAULT if struct kvm_reinject_control cannot be read,
-        -EINVAL if the supplied shift or flags are invalid
-        -ENXIO is there is no pending HPT, or the pending HPT doesn't
-                 have the requested size
-        -EBUSY if the pending HPT is not fully prepared
-        -ENOSPC if there was a hash collision when moving existing
-                  HPT entries to the new HPT
-        -EIO on other error conditions
-
-Used to implement the PAPR extension for runtime resizing of a guest's
-Hashed Page Table (HPT).  Specifically this requests that the guest be
-transferred to working with the new HPT, essentially implementing the
-H_RESIZE_HPT_COMMIT hypercall.
-
-This should only be called after KVM_PPC_RESIZE_HPT_PREPARE has
-returned 0 with the same parameters.  In other cases
-KVM_PPC_RESIZE_HPT_COMMIT will return an error (usually -ENXIO or
--EBUSY, though others may be possible if the preparation was started,
-but failed).
-
-This will have undefined effects on the guest if it has not already
-placed itself in a quiescent state where no vcpu will make MMU enabled
-memory accesses.
-
-On succsful completion, the pending HPT will become the guest's active
-HPT and the previous HPT will be discarded.
-
-On failure, the guest will still be operating on its previous HPT.
-
-struct kvm_ppc_resize_hpt {
-       __u64 flags;
-       __u32 shift;
-       __u32 pad;
-};
-
-4.104 KVM_X86_GET_MCE_CAP_SUPPORTED
-
-Capability: KVM_CAP_MCE
-Architectures: x86
-Type: system ioctl
-Parameters: u64 mce_cap (out)
-Returns: 0 on success, -1 on error
-
-Returns supported MCE capabilities. The u64 mce_cap parameter
-has the same format as the MSR_IA32_MCG_CAP register. Supported
-capabilities will have the corresponding bits set.
-
-4.105 KVM_X86_SETUP_MCE
-
-Capability: KVM_CAP_MCE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: u64 mcg_cap (in)
-Returns: 0 on success,
-         -EFAULT if u64 mcg_cap cannot be read,
-         -EINVAL if the requested number of banks is invalid,
-         -EINVAL if requested MCE capability is not supported.
-
-Initializes MCE support for use. The u64 mcg_cap parameter
-has the same format as the MSR_IA32_MCG_CAP register and
-specifies which capabilities should be enabled. The maximum
-supported number of error-reporting banks can be retrieved when
-checking for KVM_CAP_MCE. The supported capabilities can be
-retrieved with KVM_X86_GET_MCE_CAP_SUPPORTED.
-
-4.106 KVM_X86_SET_MCE
-
-Capability: KVM_CAP_MCE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_x86_mce (in)
-Returns: 0 on success,
-         -EFAULT if struct kvm_x86_mce cannot be read,
-         -EINVAL if the bank number is invalid,
-         -EINVAL if VAL bit is not set in status field.
-
-Inject a machine check error (MCE) into the guest. The input
-parameter is:
-
-struct kvm_x86_mce {
-       __u64 status;
-       __u64 addr;
-       __u64 misc;
-       __u64 mcg_status;
-       __u8 bank;
-       __u8 pad1[7];
-       __u64 pad2[3];
-};
-
-If the MCE being reported is an uncorrected error, KVM will
-inject it as an MCE exception into the guest. If the guest
-MCG_STATUS register reports that an MCE is in progress, KVM
-causes an KVM_EXIT_SHUTDOWN vmexit.
-
-Otherwise, if the MCE is a corrected error, KVM will just
-store it in the corresponding bank (provided this bank is
-not holding a previously reported uncorrected error).
-
-4.107 KVM_S390_GET_CMMA_BITS
-
-Capability: KVM_CAP_S390_CMMA_MIGRATION
-Architectures: s390
-Type: vm ioctl
-Parameters: struct kvm_s390_cmma_log (in, out)
-Returns: 0 on success, a negative value on error
-
-This ioctl is used to get the values of the CMMA bits on the s390
-architecture. It is meant to be used in two scenarios:
-- During live migration to save the CMMA values. Live migration needs
-  to be enabled via the KVM_REQ_START_MIGRATION VM property.
-- To non-destructively peek at the CMMA values, with the flag
-  KVM_S390_CMMA_PEEK set.
-
-The ioctl takes parameters via the kvm_s390_cmma_log struct. The desired
-values are written to a buffer whose location is indicated via the "values"
-member in the kvm_s390_cmma_log struct.  The values in the input struct are
-also updated as needed.
-Each CMMA value takes up one byte.
-
-struct kvm_s390_cmma_log {
-       __u64 start_gfn;
-       __u32 count;
-       __u32 flags;
-       union {
-               __u64 remaining;
-               __u64 mask;
-       };
-       __u64 values;
-};
-
-start_gfn is the number of the first guest frame whose CMMA values are
-to be retrieved,
-
-count is the length of the buffer in bytes,
-
-values points to the buffer where the result will be written to.
-
-If count is greater than KVM_S390_SKEYS_MAX, then it is considered to be
-KVM_S390_SKEYS_MAX. KVM_S390_SKEYS_MAX is re-used for consistency with
-other ioctls.
-
-The result is written in the buffer pointed to by the field values, and
-the values of the input parameter are updated as follows.
-
-Depending on the flags, different actions are performed. The only
-supported flag so far is KVM_S390_CMMA_PEEK.
-
-The default behaviour if KVM_S390_CMMA_PEEK is not set is:
-start_gfn will indicate the first page frame whose CMMA bits were dirty.
-It is not necessarily the same as the one passed as input, as clean pages
-are skipped.
-
-count will indicate the number of bytes actually written in the buffer.
-It can (and very often will) be smaller than the input value, since the
-buffer is only filled until 16 bytes of clean values are found (which
-are then not copied in the buffer). Since a CMMA migration block needs
-the base address and the length, for a total of 16 bytes, we will send
-back some clean data if there is some dirty data afterwards, as long as
-the size of the clean data does not exceed the size of the header. This
-allows to minimize the amount of data to be saved or transferred over
-the network at the expense of more roundtrips to userspace. The next
-invocation of the ioctl will skip over all the clean values, saving
-potentially more than just the 16 bytes we found.
-
-If KVM_S390_CMMA_PEEK is set:
-the existing storage attributes are read even when not in migration
-mode, and no other action is performed;
-
-the output start_gfn will be equal to the input start_gfn,
-
-the output count will be equal to the input count, except if the end of
-memory has been reached.
-
-In both cases:
-the field "remaining" will indicate the total number of dirty CMMA values
-still remaining, or 0 if KVM_S390_CMMA_PEEK is set and migration mode is
-not enabled.
-
-mask is unused.
-
-values points to the userspace buffer where the result will be stored.
-
-This ioctl can fail with -ENOMEM if not enough memory can be allocated to
-complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
-KVM_S390_CMMA_PEEK is not set but migration mode was not enabled, with
--EFAULT if the userspace address is invalid or if no page table is
-present for the addresses (e.g. when using hugepages).
-
-4.108 KVM_S390_SET_CMMA_BITS
-
-Capability: KVM_CAP_S390_CMMA_MIGRATION
-Architectures: s390
-Type: vm ioctl
-Parameters: struct kvm_s390_cmma_log (in)
-Returns: 0 on success, a negative value on error
-
-This ioctl is used to set the values of the CMMA bits on the s390
-architecture. It is meant to be used during live migration to restore
-the CMMA values, but there are no restrictions on its use.
-The ioctl takes parameters via the kvm_s390_cmma_values struct.
-Each CMMA value takes up one byte.
-
-struct kvm_s390_cmma_log {
-       __u64 start_gfn;
-       __u32 count;
-       __u32 flags;
-       union {
-               __u64 remaining;
-               __u64 mask;
-       };
-       __u64 values;
-};
-
-start_gfn indicates the starting guest frame number,
-
-count indicates how many values are to be considered in the buffer,
-
-flags is not used and must be 0.
-
-mask indicates which PGSTE bits are to be considered.
-
-remaining is not used.
-
-values points to the buffer in userspace where to store the values.
-
-This ioctl can fail with -ENOMEM if not enough memory can be allocated to
-complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
-the count field is too large (e.g. more than KVM_S390_CMMA_SIZE_MAX) or
-if the flags field was not 0, with -EFAULT if the userspace address is
-invalid, if invalid pages are written to (e.g. after the end of memory)
-or if no page table is present for the addresses (e.g. when using
-hugepages).
-
-4.109 KVM_PPC_GET_CPU_CHAR
-
-Capability: KVM_CAP_PPC_GET_CPU_CHAR
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_ppc_cpu_char (out)
-Returns: 0 on successful completion
-        -EFAULT if struct kvm_ppc_cpu_char cannot be written
-
-This ioctl gives userspace information about certain characteristics
-of the CPU relating to speculative execution of instructions and
-possible information leakage resulting from speculative execution (see
-CVE-2017-5715, CVE-2017-5753 and CVE-2017-5754).  The information is
-returned in struct kvm_ppc_cpu_char, which looks like this:
-
-struct kvm_ppc_cpu_char {
-       __u64   character;              /* characteristics of the CPU */
-       __u64   behaviour;              /* recommended software behaviour */
-       __u64   character_mask;         /* valid bits in character */
-       __u64   behaviour_mask;         /* valid bits in behaviour */
-};
-
-For extensibility, the character_mask and behaviour_mask fields
-indicate which bits of character and behaviour have been filled in by
-the kernel.  If the set of defined bits is extended in future then
-userspace will be able to tell whether it is running on a kernel that
-knows about the new bits.
-
-The character field describes attributes of the CPU which can help
-with preventing inadvertent information disclosure - specifically,
-whether there is an instruction to flash-invalidate the L1 data cache
-(ori 30,30,0 or mtspr SPRN_TRIG2,rN), whether the L1 data cache is set
-to a mode where entries can only be used by the thread that created
-them, whether the bcctr[l] instruction prevents speculation, and
-whether a speculation barrier instruction (ori 31,31,0) is provided.
-
-The behaviour field describes actions that software should take to
-prevent inadvertent information disclosure, and thus describes which
-vulnerabilities the hardware is subject to; specifically whether the
-L1 data cache should be flushed when returning to user mode from the
-kernel, and whether a speculation barrier should be placed between an
-array bounds check and the array access.
-
-These fields use the same bit definitions as the new
-H_GET_CPU_CHARACTERISTICS hypercall.
-
-4.110 KVM_MEMORY_ENCRYPT_OP
-
-Capability: basic
-Architectures: x86
-Type: system
-Parameters: an opaque platform specific structure (in/out)
-Returns: 0 on success; -1 on error
-
-If the platform supports creating encrypted VMs then this ioctl can be used
-for issuing platform-specific memory encryption commands to manage those
-encrypted VMs.
-
-Currently, this ioctl is used for issuing Secure Encrypted Virtualization
-(SEV) commands on AMD Processors. The SEV commands are defined in
-Documentation/virtual/kvm/amd-memory-encryption.rst.
-
-4.111 KVM_MEMORY_ENCRYPT_REG_REGION
-
-Capability: basic
-Architectures: x86
-Type: system
-Parameters: struct kvm_enc_region (in)
-Returns: 0 on success; -1 on error
-
-This ioctl can be used to register a guest memory region which may
-contain encrypted data (e.g. guest RAM, SMRAM etc).
-
-It is used in the SEV-enabled guest. When encryption is enabled, a guest
-memory region may contain encrypted data. The SEV memory encryption
-engine uses a tweak such that two identical plaintext pages, each at
-different locations will have differing ciphertexts. So swapping or
-moving ciphertext of those pages will not result in plaintext being
-swapped. So relocating (or migrating) physical backing pages for the SEV
-guest will require some additional steps.
-
-Note: The current SEV key management spec does not provide commands to
-swap or migrate (move) ciphertext pages. Hence, for now we pin the guest
-memory region registered with the ioctl.
-
-4.112 KVM_MEMORY_ENCRYPT_UNREG_REGION
-
-Capability: basic
-Architectures: x86
-Type: system
-Parameters: struct kvm_enc_region (in)
-Returns: 0 on success; -1 on error
-
-This ioctl can be used to unregister the guest memory region registered
-with KVM_MEMORY_ENCRYPT_REG_REGION ioctl above.
-
-4.113 KVM_HYPERV_EVENTFD
-
-Capability: KVM_CAP_HYPERV_EVENTFD
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_hyperv_eventfd (in)
-
-This ioctl (un)registers an eventfd to receive notifications from the guest on
-the specified Hyper-V connection id through the SIGNAL_EVENT hypercall, without
-causing a user exit.  SIGNAL_EVENT hypercall with non-zero event flag number
-(bits 24-31) still triggers a KVM_EXIT_HYPERV_HCALL user exit.
-
-struct kvm_hyperv_eventfd {
-       __u32 conn_id;
-       __s32 fd;
-       __u32 flags;
-       __u32 padding[3];
-};
-
-The conn_id field should fit within 24 bits:
-
-#define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
-
-The acceptable values for the flags field are:
-
-#define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
-
-Returns: 0 on success,
-       -EINVAL if conn_id or flags is outside the allowed range
-       -ENOENT on deassign if the conn_id isn't registered
-       -EEXIST on assign if the conn_id is already registered
-
-4.114 KVM_GET_NESTED_STATE
-
-Capability: KVM_CAP_NESTED_STATE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_nested_state (in/out)
-Returns: 0 on success, -1 on error
-Errors:
-  E2BIG:     the total state size exceeds the value of 'size' specified by
-             the user; the size required will be written into size.
-
-struct kvm_nested_state {
-       __u16 flags;
-       __u16 format;
-       __u32 size;
-
-       union {
-               struct kvm_vmx_nested_state_hdr vmx;
-               struct kvm_svm_nested_state_hdr svm;
-
-               /* Pad the header to 128 bytes.  */
-               __u8 pad[120];
-       } hdr;
-
-       union {
-               struct kvm_vmx_nested_state_data vmx[0];
-               struct kvm_svm_nested_state_data svm[0];
-       } data;
-};
-
-#define KVM_STATE_NESTED_GUEST_MODE    0x00000001
-#define KVM_STATE_NESTED_RUN_PENDING   0x00000002
-#define KVM_STATE_NESTED_EVMCS         0x00000004
-
-#define KVM_STATE_NESTED_FORMAT_VMX            0
-#define KVM_STATE_NESTED_FORMAT_SVM            1
-
-#define KVM_STATE_NESTED_VMX_VMCS_SIZE         0x1000
-
-#define KVM_STATE_NESTED_VMX_SMM_GUEST_MODE    0x00000001
-#define KVM_STATE_NESTED_VMX_SMM_VMXON         0x00000002
-
-struct kvm_vmx_nested_state_hdr {
-       __u64 vmxon_pa;
-       __u64 vmcs12_pa;
-
-       struct {
-               __u16 flags;
-       } smm;
-};
-
-struct kvm_vmx_nested_state_data {
-       __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
-       __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
-};
-
-This ioctl copies the vcpu's nested virtualization state from the kernel to
-userspace.
-
-The maximum size of the state can be retrieved by passing KVM_CAP_NESTED_STATE
-to the KVM_CHECK_EXTENSION ioctl().
-
-4.115 KVM_SET_NESTED_STATE
-
-Capability: KVM_CAP_NESTED_STATE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_nested_state (in)
-Returns: 0 on success, -1 on error
-
-This copies the vcpu's kvm_nested_state struct from userspace to the kernel.
-For the definition of struct kvm_nested_state, see KVM_GET_NESTED_STATE.
-
-4.116 KVM_(UN)REGISTER_COALESCED_MMIO
-
-Capability: KVM_CAP_COALESCED_MMIO (for coalesced mmio)
-           KVM_CAP_COALESCED_PIO (for coalesced pio)
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_coalesced_mmio_zone
-Returns: 0 on success, < 0 on error
-
-Coalesced I/O is a performance optimization that defers hardware
-register write emulation so that userspace exits are avoided.  It is
-typically used to reduce the overhead of emulating frequently accessed
-hardware registers.
-
-When a hardware register is configured for coalesced I/O, write accesses
-do not exit to userspace and their value is recorded in a ring buffer
-that is shared between kernel and userspace.
-
-Coalesced I/O is used if one or more write accesses to a hardware
-register can be deferred until a read or a write to another hardware
-register on the same device.  This last access will cause a vmexit and
-userspace will process accesses from the ring buffer before emulating
-it. That will avoid exiting to userspace on repeated writes.
-
-Coalesced pio is based on coalesced mmio. There is little difference
-between coalesced mmio and pio except that coalesced pio records accesses
-to I/O ports.
-
-4.117 KVM_CLEAR_DIRTY_LOG (vm ioctl)
-
-Capability: KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
-Architectures: x86, arm, arm64, mips
-Type: vm ioctl
-Parameters: struct kvm_dirty_log (in)
-Returns: 0 on success, -1 on error
-
-/* for KVM_CLEAR_DIRTY_LOG */
-struct kvm_clear_dirty_log {
-       __u32 slot;
-       __u32 num_pages;
-       __u64 first_page;
-       union {
-               void __user *dirty_bitmap; /* one bit per page */
-               __u64 padding;
-       };
-};
-
-The ioctl clears the dirty status of pages in a memory slot, according to
-the bitmap that is passed in struct kvm_clear_dirty_log's dirty_bitmap
-field.  Bit 0 of the bitmap corresponds to page "first_page" in the
-memory slot, and num_pages is the size in bits of the input bitmap.
-first_page must be a multiple of 64; num_pages must also be a multiple of
-64 unless first_page + num_pages is the size of the memory slot.  For each
-bit that is set in the input bitmap, the corresponding page is marked "clean"
-in KVM's dirty bitmap, and dirty tracking is re-enabled for that page
-(for example via write-protection, or by clearing the dirty bit in
-a page table entry).
-
-If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 specifies
-the address space for which you want to return the dirty bitmap.
-They must be less than the value that KVM_CHECK_EXTENSION returns for
-the KVM_CAP_MULTI_ADDRESS_SPACE capability.
-
-This ioctl is mostly useful when KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
-is enabled; for more information, see the description of the capability.
-However, it can always be used as long as KVM_CHECK_EXTENSION confirms
-that KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is present.
-
-4.118 KVM_GET_SUPPORTED_HV_CPUID
-
-Capability: KVM_CAP_HYPERV_CPUID
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_cpuid2 (in/out)
-Returns: 0 on success, -1 on error
-
-struct kvm_cpuid2 {
-       __u32 nent;
-       __u32 padding;
-       struct kvm_cpuid_entry2 entries[0];
-};
-
-struct kvm_cpuid_entry2 {
-       __u32 function;
-       __u32 index;
-       __u32 flags;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding[3];
-};
-
-This ioctl returns x86 cpuid features leaves related to Hyper-V emulation in
-KVM.  Userspace can use the information returned by this ioctl to construct
-cpuid information presented to guests consuming Hyper-V enlightenments (e.g.
-Windows or Hyper-V guests).
-
-CPUID feature leaves returned by this ioctl are defined by Hyper-V Top Level
-Functional Specification (TLFS). These leaves can't be obtained with
-KVM_GET_SUPPORTED_CPUID ioctl because some of them intersect with KVM feature
-leaves (0x40000000, 0x40000001).
-
-Currently, the following list of CPUID leaves are returned:
- HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS
- HYPERV_CPUID_INTERFACE
- HYPERV_CPUID_VERSION
- HYPERV_CPUID_FEATURES
- HYPERV_CPUID_ENLIGHTMENT_INFO
- HYPERV_CPUID_IMPLEMENT_LIMITS
- HYPERV_CPUID_NESTED_FEATURES
-
-HYPERV_CPUID_NESTED_FEATURES leaf is only exposed when Enlightened VMCS was
-enabled on the corresponding vCPU (KVM_CAP_HYPERV_ENLIGHTENED_VMCS).
-
-Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
-with the 'nent' field indicating the number of entries in the variable-size
-array 'entries'.  If the number of entries is too low to describe all Hyper-V
-feature leaves, an error (E2BIG) is returned. If the number is more or equal
-to the number of Hyper-V feature leaves, the 'nent' field is adjusted to the
-number of valid entries in the 'entries' array, which is then filled.
-
-'index' and 'flags' fields in 'struct kvm_cpuid_entry2' are currently reserved,
-userspace should not expect to get any particular value there.
-
-4.119 KVM_ARM_VCPU_FINALIZE
-
-Architectures: arm, arm64
-Type: vcpu ioctl
-Parameters: int feature (in)
-Returns: 0 on success, -1 on error
-Errors:
-  EPERM:     feature not enabled, needs configuration, or already finalized
-  EINVAL:    feature unknown or not present
-
-Recognised values for feature:
-  arm64      KVM_ARM_VCPU_SVE (requires KVM_CAP_ARM_SVE)
-
-Finalizes the configuration of the specified vcpu feature.
-
-The vcpu must already have been initialised, enabling the affected feature, by
-means of a successful KVM_ARM_VCPU_INIT call with the appropriate flag set in
-features[].
-
-For affected vcpu features, this is a mandatory step that must be performed
-before the vcpu is fully usable.
-
-Between KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE, the feature may be
-configured by use of ioctls such as KVM_SET_ONE_REG.  The exact configuration
-that should be performaned and how to do it are feature-dependent.
-
-Other calls that depend on a particular feature being finalized, such as
-KVM_RUN, KVM_GET_REG_LIST, KVM_GET_ONE_REG and KVM_SET_ONE_REG, will fail with
--EPERM unless the feature has already been finalized by means of a
-KVM_ARM_VCPU_FINALIZE call.
-
-See KVM_ARM_VCPU_INIT for details of vcpu features that require finalization
-using this ioctl.
-
-4.120 KVM_SET_PMU_EVENT_FILTER
-
-Capability: KVM_CAP_PMU_EVENT_FILTER
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_pmu_event_filter (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_pmu_event_filter {
-       __u32 action;
-       __u32 nevents;
-       __u32 fixed_counter_bitmap;
-       __u32 flags;
-       __u32 pad[4];
-       __u64 events[0];
-};
-
-This ioctl restricts the set of PMU events that the guest can program.
-The argument holds a list of events which will be allowed or denied.
-The eventsel+umask of each event the guest attempts to program is compared
-against the events field to determine whether the guest should have access.
-The events field only controls general purpose counters; fixed purpose
-counters are controlled by the fixed_counter_bitmap.
-
-No flags are defined yet, the field must be zero.
-
-Valid values for 'action':
-#define KVM_PMU_EVENT_ALLOW 0
-#define KVM_PMU_EVENT_DENY 1
-
-
-5. The kvm_run structure
-------------------------
-
-Application code obtains a pointer to the kvm_run structure by
-mmap()ing a vcpu fd.  From that point, application code can control
-execution by changing fields in kvm_run prior to calling the KVM_RUN
-ioctl, and obtain information about the reason KVM_RUN returned by
-looking up structure members.
-
-struct kvm_run {
-       /* in */
-       __u8 request_interrupt_window;
-
-Request that KVM_RUN return when it becomes possible to inject external
-interrupts into the guest.  Useful in conjunction with KVM_INTERRUPT.
-
-       __u8 immediate_exit;
-
-This field is polled once when KVM_RUN starts; if non-zero, KVM_RUN
-exits immediately, returning -EINTR.  In the common scenario where a
-signal is used to "kick" a VCPU out of KVM_RUN, this field can be used
-to avoid usage of KVM_SET_SIGNAL_MASK, which has worse scalability.
-Rather than blocking the signal outside KVM_RUN, userspace can set up
-a signal handler that sets run->immediate_exit to a non-zero value.
-
-This field is ignored if KVM_CAP_IMMEDIATE_EXIT is not available.
-
-       __u8 padding1[6];
-
-       /* out */
-       __u32 exit_reason;
-
-When KVM_RUN has returned successfully (return value 0), this informs
-application code why KVM_RUN has returned.  Allowable values for this
-field are detailed below.
-
-       __u8 ready_for_interrupt_injection;
-
-If request_interrupt_window has been specified, this field indicates
-an interrupt can be injected now with KVM_INTERRUPT.
-
-       __u8 if_flag;
-
-The value of the current interrupt flag.  Only valid if in-kernel
-local APIC is not used.
-
-       __u16 flags;
-
-More architecture-specific flags detailing state of the VCPU that may
-affect the device's behavior.  The only currently defined flag is
-KVM_RUN_X86_SMM, which is valid on x86 machines and is set if the
-VCPU is in system management mode.
-
-       /* in (pre_kvm_run), out (post_kvm_run) */
-       __u64 cr8;
-
-The value of the cr8 register.  Only valid if in-kernel local APIC is
-not used.  Both input and output.
-
-       __u64 apic_base;
-
-The value of the APIC BASE msr.  Only valid if in-kernel local
-APIC is not used.  Both input and output.
-
-       union {
-               /* KVM_EXIT_UNKNOWN */
-               struct {
-                       __u64 hardware_exit_reason;
-               } hw;
-
-If exit_reason is KVM_EXIT_UNKNOWN, the vcpu has exited due to unknown
-reasons.  Further architecture-specific information is available in
-hardware_exit_reason.
-
-               /* KVM_EXIT_FAIL_ENTRY */
-               struct {
-                       __u64 hardware_entry_failure_reason;
-               } fail_entry;
-
-If exit_reason is KVM_EXIT_FAIL_ENTRY, the vcpu could not be run due
-to unknown reasons.  Further architecture-specific information is
-available in hardware_entry_failure_reason.
-
-               /* KVM_EXIT_EXCEPTION */
-               struct {
-                       __u32 exception;
-                       __u32 error_code;
-               } ex;
-
-Unused.
-
-               /* KVM_EXIT_IO */
-               struct {
-#define KVM_EXIT_IO_IN  0
-#define KVM_EXIT_IO_OUT 1
-                       __u8 direction;
-                       __u8 size; /* bytes */
-                       __u16 port;
-                       __u32 count;
-                       __u64 data_offset; /* relative to kvm_run start */
-               } io;
-
-If exit_reason is KVM_EXIT_IO, then the vcpu has
-executed a port I/O instruction which could not be satisfied by kvm.
-data_offset describes where the data is located (KVM_EXIT_IO_OUT) or
-where kvm expects application code to place the data for the next
-KVM_RUN invocation (KVM_EXIT_IO_IN).  Data format is a packed array.
-
-               /* KVM_EXIT_DEBUG */
-               struct {
-                       struct kvm_debug_exit_arch arch;
-               } debug;
-
-If the exit_reason is KVM_EXIT_DEBUG, then a vcpu is processing a debug event
-for which architecture specific information is returned.
-
-               /* KVM_EXIT_MMIO */
-               struct {
-                       __u64 phys_addr;
-                       __u8  data[8];
-                       __u32 len;
-                       __u8  is_write;
-               } mmio;
-
-If exit_reason is KVM_EXIT_MMIO, then the vcpu has
-executed a memory-mapped I/O instruction which could not be satisfied
-by kvm.  The 'data' member contains the written data if 'is_write' is
-true, and should be filled by application code otherwise.
-
-The 'data' member contains, in its first 'len' bytes, the value as it would
-appear if the VCPU performed a load or store of the appropriate width directly
-to the byte array.
-
-NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR and
-      KVM_EXIT_EPR the corresponding
-operations are complete (and guest state is consistent) only after userspace
-has re-entered the kernel with KVM_RUN.  The kernel side will first finish
-incomplete operations and then check for pending signals.  Userspace
-can re-enter the guest with an unmasked signal pending to complete
-pending operations.
-
-               /* KVM_EXIT_HYPERCALL */
-               struct {
-                       __u64 nr;
-                       __u64 args[6];
-                       __u64 ret;
-                       __u32 longmode;
-                       __u32 pad;
-               } hypercall;
-
-Unused.  This was once used for 'hypercall to userspace'.  To implement
-such functionality, use KVM_EXIT_IO (x86) or KVM_EXIT_MMIO (all except s390).
-Note KVM_EXIT_IO is significantly faster than KVM_EXIT_MMIO.
-
-               /* KVM_EXIT_TPR_ACCESS */
-               struct {
-                       __u64 rip;
-                       __u32 is_write;
-                       __u32 pad;
-               } tpr_access;
-
-To be documented (KVM_TPR_ACCESS_REPORTING).
-
-               /* KVM_EXIT_S390_SIEIC */
-               struct {
-                       __u8 icptcode;
-                       __u64 mask; /* psw upper half */
-                       __u64 addr; /* psw lower half */
-                       __u16 ipa;
-                       __u32 ipb;
-               } s390_sieic;
-
-s390 specific.
-
-               /* KVM_EXIT_S390_RESET */
-#define KVM_S390_RESET_POR       1
-#define KVM_S390_RESET_CLEAR     2
-#define KVM_S390_RESET_SUBSYSTEM 4
-#define KVM_S390_RESET_CPU_INIT  8
-#define KVM_S390_RESET_IPL       16
-               __u64 s390_reset_flags;
-
-s390 specific.
-
-               /* KVM_EXIT_S390_UCONTROL */
-               struct {
-                       __u64 trans_exc_code;
-                       __u32 pgm_code;
-               } s390_ucontrol;
-
-s390 specific. A page fault has occurred for a user controlled virtual
-machine (KVM_VM_S390_UNCONTROL) on it's host page table that cannot be
-resolved by the kernel.
-The program code and the translation exception code that were placed
-in the cpu's lowcore are presented here as defined by the z Architecture
-Principles of Operation Book in the Chapter for Dynamic Address Translation
-(DAT)
-
-               /* KVM_EXIT_DCR */
-               struct {
-                       __u32 dcrn;
-                       __u32 data;
-                       __u8  is_write;
-               } dcr;
-
-Deprecated - was used for 440 KVM.
-
-               /* KVM_EXIT_OSI */
-               struct {
-                       __u64 gprs[32];
-               } osi;
-
-MOL uses a special hypercall interface it calls 'OSI'. To enable it, we catch
-hypercalls and exit with this exit struct that contains all the guest gprs.
-
-If exit_reason is KVM_EXIT_OSI, then the vcpu has triggered such a hypercall.
-Userspace can now handle the hypercall and when it's done modify the gprs as
-necessary. Upon guest entry all guest GPRs will then be replaced by the values
-in this struct.
-
-               /* KVM_EXIT_PAPR_HCALL */
-               struct {
-                       __u64 nr;
-                       __u64 ret;
-                       __u64 args[9];
-               } papr_hcall;
-
-This is used on 64-bit PowerPC when emulating a pSeries partition,
-e.g. with the 'pseries' machine type in qemu.  It occurs when the
-guest does a hypercall using the 'sc 1' instruction.  The 'nr' field
-contains the hypercall number (from the guest R3), and 'args' contains
-the arguments (from the guest R4 - R12).  Userspace should put the
-return code in 'ret' and any extra returned values in args[].
-The possible hypercalls are defined in the Power Architecture Platform
-Requirements (PAPR) document available from www.power.org (free
-developer registration required to access it).
-
-               /* KVM_EXIT_S390_TSCH */
-               struct {
-                       __u16 subchannel_id;
-                       __u16 subchannel_nr;
-                       __u32 io_int_parm;
-                       __u32 io_int_word;
-                       __u32 ipb;
-                       __u8 dequeued;
-               } s390_tsch;
-
-s390 specific. This exit occurs when KVM_CAP_S390_CSS_SUPPORT has been enabled
-and TEST SUBCHANNEL was intercepted. If dequeued is set, a pending I/O
-interrupt for the target subchannel has been dequeued and subchannel_id,
-subchannel_nr, io_int_parm and io_int_word contain the parameters for that
-interrupt. ipb is needed for instruction parameter decoding.
-
-               /* KVM_EXIT_EPR */
-               struct {
-                       __u32 epr;
-               } epr;
-
-On FSL BookE PowerPC chips, the interrupt controller has a fast patch
-interrupt acknowledge path to the core. When the core successfully
-delivers an interrupt, it automatically populates the EPR register with
-the interrupt vector number and acknowledges the interrupt inside
-the interrupt controller.
-
-In case the interrupt controller lives in user space, we need to do
-the interrupt acknowledge cycle through it to fetch the next to be
-delivered interrupt vector using this exit.
-
-It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an
-external interrupt has just been delivered into the guest. User space
-should put the acknowledged interrupt vector into the 'epr' field.
-
-               /* KVM_EXIT_SYSTEM_EVENT */
-               struct {
-#define KVM_SYSTEM_EVENT_SHUTDOWN       1
-#define KVM_SYSTEM_EVENT_RESET          2
-#define KVM_SYSTEM_EVENT_CRASH          3
-                       __u32 type;
-                       __u64 flags;
-               } system_event;
-
-If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered
-a system-level event using some architecture specific mechanism (hypercall
-or some special instruction). In case of ARM/ARM64, this is triggered using
-HVC instruction based PSCI call from the vcpu. The 'type' field describes
-the system-level event type. The 'flags' field describes architecture
-specific flags for the system-level event.
-
-Valid values for 'type' are:
-  KVM_SYSTEM_EVENT_SHUTDOWN -- the guest has requested a shutdown of the
-   VM. Userspace is not obliged to honour this, and if it does honour
-   this does not need to destroy the VM synchronously (ie it may call
-   KVM_RUN again before shutdown finally occurs).
-  KVM_SYSTEM_EVENT_RESET -- the guest has requested a reset of the VM.
-   As with SHUTDOWN, userspace can choose to ignore the request, or
-   to schedule the reset to occur in the future and may call KVM_RUN again.
-  KVM_SYSTEM_EVENT_CRASH -- the guest crash occurred and the guest
-   has requested a crash condition maintenance. Userspace can choose
-   to ignore the request, or to gather VM memory core dump and/or
-   reset/shutdown of the VM.
-
-               /* KVM_EXIT_IOAPIC_EOI */
-               struct {
-                       __u8 vector;
-               } eoi;
-
-Indicates that the VCPU's in-kernel local APIC received an EOI for a
-level-triggered IOAPIC interrupt.  This exit only triggers when the
-IOAPIC is implemented in userspace (i.e. KVM_CAP_SPLIT_IRQCHIP is enabled);
-the userspace IOAPIC should process the EOI and retrigger the interrupt if
-it is still asserted.  Vector is the LAPIC interrupt vector for which the
-EOI was received.
-
-               struct kvm_hyperv_exit {
-#define KVM_EXIT_HYPERV_SYNIC          1
-#define KVM_EXIT_HYPERV_HCALL          2
-                       __u32 type;
-                       union {
-                               struct {
-                                       __u32 msr;
-                                       __u64 control;
-                                       __u64 evt_page;
-                                       __u64 msg_page;
-                               } synic;
-                               struct {
-                                       __u64 input;
-                                       __u64 result;
-                                       __u64 params[2];
-                               } hcall;
-                       } u;
-               };
-               /* KVM_EXIT_HYPERV */
-                struct kvm_hyperv_exit hyperv;
-Indicates that the VCPU exits into userspace to process some tasks
-related to Hyper-V emulation.
-Valid values for 'type' are:
-       KVM_EXIT_HYPERV_SYNIC -- synchronously notify user-space about
-Hyper-V SynIC state change. Notification is used to remap SynIC
-event/message pages and to enable/disable SynIC messages/events processing
-in userspace.
-
-               /* Fix the size of the union. */
-               char padding[256];
-       };
-
-       /*
-        * shared registers between kvm and userspace.
-        * kvm_valid_regs specifies the register classes set by the host
-        * kvm_dirty_regs specified the register classes dirtied by userspace
-        * struct kvm_sync_regs is architecture specific, as well as the
-        * bits for kvm_valid_regs and kvm_dirty_regs
-        */
-       __u64 kvm_valid_regs;
-       __u64 kvm_dirty_regs;
-       union {
-               struct kvm_sync_regs regs;
-               char padding[SYNC_REGS_SIZE_BYTES];
-       } s;
-
-If KVM_CAP_SYNC_REGS is defined, these fields allow userspace to access
-certain guest registers without having to call SET/GET_*REGS. Thus we can
-avoid some system call overhead if userspace has to handle the exit.
-Userspace can query the validity of the structure by checking
-kvm_valid_regs for specific bits. These bits are architecture specific
-and usually define the validity of a groups of registers. (e.g. one bit
- for general purpose registers)
-
-Please note that the kernel is allowed to use the kvm_run structure as the
-primary storage for certain register types. Therefore, the kernel may use the
-values in kvm_run even if the corresponding bit in kvm_dirty_regs is not set.
-
-};
-
-
-
-6. Capabilities that can be enabled on vCPUs
---------------------------------------------
-
-There are certain capabilities that change the behavior of the virtual CPU or
-the virtual machine when enabled. To enable them, please see section 4.37.
-Below you can find a list of capabilities and what their effect on the vCPU or
-the virtual machine is when enabling them.
-
-The following information is provided along with the description:
-
-  Architectures: which instruction set architectures provide this ioctl.
-      x86 includes both i386 and x86_64.
-
-  Target: whether this is a per-vcpu or per-vm capability.
-
-  Parameters: what parameters are accepted by the capability.
-
-  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
-      are not detailed, but errors with specific meanings are.
-
-
-6.1 KVM_CAP_PPC_OSI
-
-Architectures: ppc
-Target: vcpu
-Parameters: none
-Returns: 0 on success; -1 on error
-
-This capability enables interception of OSI hypercalls that otherwise would
-be treated as normal system calls to be injected into the guest. OSI hypercalls
-were invented by Mac-on-Linux to have a standardized communication mechanism
-between the guest and the host.
-
-When this capability is enabled, KVM_EXIT_OSI can occur.
-
-
-6.2 KVM_CAP_PPC_PAPR
-
-Architectures: ppc
-Target: vcpu
-Parameters: none
-Returns: 0 on success; -1 on error
-
-This capability enables interception of PAPR hypercalls. PAPR hypercalls are
-done using the hypercall instruction "sc 1".
-
-It also sets the guest privilege level to "supervisor" mode. Usually the guest
-runs in "hypervisor" privilege mode with a few missing features.
-
-In addition to the above, it changes the semantics of SDR1. In this mode, the
-HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
-HTAB invisible to the guest.
-
-When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
-
-
-6.3 KVM_CAP_SW_TLB
-
-Architectures: ppc
-Target: vcpu
-Parameters: args[0] is the address of a struct kvm_config_tlb
-Returns: 0 on success; -1 on error
-
-struct kvm_config_tlb {
-       __u64 params;
-       __u64 array;
-       __u32 mmu_type;
-       __u32 array_len;
-};
-
-Configures the virtual CPU's TLB array, establishing a shared memory area
-between userspace and KVM.  The "params" and "array" fields are userspace
-addresses of mmu-type-specific data structures.  The "array_len" field is an
-safety mechanism, and should be set to the size in bytes of the memory that
-userspace has reserved for the array.  It must be at least the size dictated
-by "mmu_type" and "params".
-
-While KVM_RUN is active, the shared region is under control of KVM.  Its
-contents are undefined, and any modification by userspace results in
-boundedly undefined behavior.
-
-On return from KVM_RUN, the shared region will reflect the current state of
-the guest's TLB.  If userspace makes any changes, it must call KVM_DIRTY_TLB
-to tell KVM which entries have been changed, prior to calling KVM_RUN again
-on this vcpu.
-
-For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
- - The "params" field is of type "struct kvm_book3e_206_tlb_params".
- - The "array" field points to an array of type "struct
-   kvm_book3e_206_tlb_entry".
- - The array consists of all entries in the first TLB, followed by all
-   entries in the second TLB.
- - Within a TLB, entries are ordered first by increasing set number.  Within a
-   set, entries are ordered by way (increasing ESEL).
- - The hash for determining set number in TLB0 is: (MAS2 >> 12) & (num_sets - 1)
-   where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value.
- - The tsize field of mas1 shall be set to 4K on TLB0, even though the
-   hardware ignores this value for TLB0.
-
-6.4 KVM_CAP_S390_CSS_SUPPORT
-
-Architectures: s390
-Target: vcpu
-Parameters: none
-Returns: 0 on success; -1 on error
-
-This capability enables support for handling of channel I/O instructions.
-
-TEST PENDING INTERRUPTION and the interrupt portion of TEST SUBCHANNEL are
-handled in-kernel, while the other I/O instructions are passed to userspace.
-
-When this capability is enabled, KVM_EXIT_S390_TSCH will occur on TEST
-SUBCHANNEL intercepts.
-
-Note that even though this capability is enabled per-vcpu, the complete
-virtual machine is affected.
-
-6.5 KVM_CAP_PPC_EPR
-
-Architectures: ppc
-Target: vcpu
-Parameters: args[0] defines whether the proxy facility is active
-Returns: 0 on success; -1 on error
-
-This capability enables or disables the delivery of interrupts through the
-external proxy facility.
-
-When enabled (args[0] != 0), every time the guest gets an external interrupt
-delivered, it automatically exits into user space with a KVM_EXIT_EPR exit
-to receive the topmost interrupt vector.
-
-When disabled (args[0] == 0), behavior is as if this facility is unsupported.
-
-When this capability is enabled, KVM_EXIT_EPR can occur.
-
-6.6 KVM_CAP_IRQ_MPIC
-
-Architectures: ppc
-Parameters: args[0] is the MPIC device fd
-            args[1] is the MPIC CPU number for this vcpu
-
-This capability connects the vcpu to an in-kernel MPIC device.
-
-6.7 KVM_CAP_IRQ_XICS
-
-Architectures: ppc
-Target: vcpu
-Parameters: args[0] is the XICS device fd
-            args[1] is the XICS CPU number (server ID) for this vcpu
-
-This capability connects the vcpu to an in-kernel XICS device.
-
-6.8 KVM_CAP_S390_IRQCHIP
-
-Architectures: s390
-Target: vm
-Parameters: none
-
-This capability enables the in-kernel irqchip for s390. Please refer to
-"4.24 KVM_CREATE_IRQCHIP" for details.
-
-6.9 KVM_CAP_MIPS_FPU
-
-Architectures: mips
-Target: vcpu
-Parameters: args[0] is reserved for future use (should be 0).
-
-This capability allows the use of the host Floating Point Unit by the guest. It
-allows the Config1.FP bit to be set to enable the FPU in the guest. Once this is
-done the KVM_REG_MIPS_FPR_* and KVM_REG_MIPS_FCR_* registers can be accessed
-(depending on the current guest FPU register mode), and the Status.FR,
-Config5.FRE bits are accessible via the KVM API and also from the guest,
-depending on them being supported by the FPU.
-
-6.10 KVM_CAP_MIPS_MSA
-
-Architectures: mips
-Target: vcpu
-Parameters: args[0] is reserved for future use (should be 0).
-
-This capability allows the use of the MIPS SIMD Architecture (MSA) by the guest.
-It allows the Config3.MSAP bit to be set to enable the use of MSA by the guest.
-Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
-accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
-the guest.
-
-6.74 KVM_CAP_SYNC_REGS
-Architectures: s390, x86
-Target: s390: always enabled, x86: vcpu
-Parameters: none
-Returns: x86: KVM_CHECK_EXTENSION returns a bit-array indicating which register
-sets are supported (bitfields defined in arch/x86/include/uapi/asm/kvm.h).
-
-As described above in the kvm_sync_regs struct info in section 5 (kvm_run):
-KVM_CAP_SYNC_REGS "allow[s] userspace to access certain guest registers
-without having to call SET/GET_*REGS". This reduces overhead by eliminating
-repeated ioctl calls for setting and/or getting register values. This is
-particularly important when userspace is making synchronous guest state
-modifications, e.g. when emulating and/or intercepting instructions in
-userspace.
-
-For s390 specifics, please refer to the source code.
-
-For x86:
-- the register sets to be copied out to kvm_run are selectable
-  by userspace (rather that all sets being copied out for every exit).
-- vcpu_events are available in addition to regs and sregs.
-
-For x86, the 'kvm_valid_regs' field of struct kvm_run is overloaded to
-function as an input bit-array field set by userspace to indicate the
-specific register sets to be copied out on the next exit.
-
-To indicate when userspace has modified values that should be copied into
-the vCPU, the all architecture bitarray field, 'kvm_dirty_regs' must be set.
-This is done using the same bitflags as for the 'kvm_valid_regs' field.
-If the dirty bit is not set, then the register set values will not be copied
-into the vCPU even if they've been modified.
-
-Unused bitfields in the bitarrays must be set to zero.
-
-struct kvm_sync_regs {
-        struct kvm_regs regs;
-        struct kvm_sregs sregs;
-        struct kvm_vcpu_events events;
-};
-
-6.75 KVM_CAP_PPC_IRQ_XIVE
-
-Architectures: ppc
-Target: vcpu
-Parameters: args[0] is the XIVE device fd
-            args[1] is the XIVE CPU number (server ID) for this vcpu
-
-This capability connects the vcpu to an in-kernel XIVE device.
-
-7. Capabilities that can be enabled on VMs
-------------------------------------------
-
-There are certain capabilities that change the behavior of the virtual
-machine when enabled. To enable them, please see section 4.37. Below
-you can find a list of capabilities and what their effect on the VM
-is when enabling them.
-
-The following information is provided along with the description:
-
-  Architectures: which instruction set architectures provide this ioctl.
-      x86 includes both i386 and x86_64.
-
-  Parameters: what parameters are accepted by the capability.
-
-  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
-      are not detailed, but errors with specific meanings are.
-
-
-7.1 KVM_CAP_PPC_ENABLE_HCALL
-
-Architectures: ppc
-Parameters: args[0] is the sPAPR hcall number
-           args[1] is 0 to disable, 1 to enable in-kernel handling
-
-This capability controls whether individual sPAPR hypercalls (hcalls)
-get handled by the kernel or not.  Enabling or disabling in-kernel
-handling of an hcall is effective across the VM.  On creation, an
-initial set of hcalls are enabled for in-kernel handling, which
-consists of those hcalls for which in-kernel handlers were implemented
-before this capability was implemented.  If disabled, the kernel will
-not to attempt to handle the hcall, but will always exit to userspace
-to handle it.  Note that it may not make sense to enable some and
-disable others of a group of related hcalls, but KVM does not prevent
-userspace from doing that.
-
-If the hcall number specified is not one that has an in-kernel
-implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL
-error.
-
-7.2 KVM_CAP_S390_USER_SIGP
-
-Architectures: s390
-Parameters: none
-
-This capability controls which SIGP orders will be handled completely in user
-space. With this capability enabled, all fast orders will be handled completely
-in the kernel:
-- SENSE
-- SENSE RUNNING
-- EXTERNAL CALL
-- EMERGENCY SIGNAL
-- CONDITIONAL EMERGENCY SIGNAL
-
-All other orders will be handled completely in user space.
-
-Only privileged operation exceptions will be checked for in the kernel (or even
-in the hardware prior to interception). If this capability is not enabled, the
-old way of handling SIGP orders is used (partially in kernel and user space).
-
-7.3 KVM_CAP_S390_VECTOR_REGISTERS
-
-Architectures: s390
-Parameters: none
-Returns: 0 on success, negative value on error
-
-Allows use of the vector registers introduced with z13 processor, and
-provides for the synchronization between host and user space.  Will
-return -EINVAL if the machine does not support vectors.
-
-7.4 KVM_CAP_S390_USER_STSI
-
-Architectures: s390
-Parameters: none
-
-This capability allows post-handlers for the STSI instruction. After
-initial handling in the kernel, KVM exits to user space with
-KVM_EXIT_S390_STSI to allow user space to insert further data.
-
-Before exiting to userspace, kvm handlers should fill in s390_stsi field of
-vcpu->run:
-struct {
-       __u64 addr;
-       __u8 ar;
-       __u8 reserved;
-       __u8 fc;
-       __u8 sel1;
-       __u16 sel2;
-} s390_stsi;
-
-@addr - guest address of STSI SYSIB
-@fc   - function code
-@sel1 - selector 1
-@sel2 - selector 2
-@ar   - access register number
-
-KVM handlers should exit to userspace with rc = -EREMOTE.
-
-7.5 KVM_CAP_SPLIT_IRQCHIP
-
-Architectures: x86
-Parameters: args[0] - number of routes reserved for userspace IOAPICs
-Returns: 0 on success, -1 on error
-
-Create a local apic for each processor in the kernel. This can be used
-instead of KVM_CREATE_IRQCHIP if the userspace VMM wishes to emulate the
-IOAPIC and PIC (and also the PIT, even though this has to be enabled
-separately).
-
-This capability also enables in kernel routing of interrupt requests;
-when KVM_CAP_SPLIT_IRQCHIP only routes of KVM_IRQ_ROUTING_MSI type are
-used in the IRQ routing table.  The first args[0] MSI routes are reserved
-for the IOAPIC pins.  Whenever the LAPIC receives an EOI for these routes,
-a KVM_EXIT_IOAPIC_EOI vmexit will be reported to userspace.
-
-Fails if VCPU has already been created, or if the irqchip is already in the
-kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
-
-7.6 KVM_CAP_S390_RI
-
-Architectures: s390
-Parameters: none
-
-Allows use of runtime-instrumentation introduced with zEC12 processor.
-Will return -EINVAL if the machine does not support runtime-instrumentation.
-Will return -EBUSY if a VCPU has already been created.
-
-7.7 KVM_CAP_X2APIC_API
-
-Architectures: x86
-Parameters: args[0] - features that should be enabled
-Returns: 0 on success, -EINVAL when args[0] contains invalid features
-
-Valid feature flags in args[0] are
-
-#define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
-#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
-
-Enabling KVM_X2APIC_API_USE_32BIT_IDS changes the behavior of
-KVM_SET_GSI_ROUTING, KVM_SIGNAL_MSI, KVM_SET_LAPIC, and KVM_GET_LAPIC,
-allowing the use of 32-bit APIC IDs.  See KVM_CAP_X2APIC_API in their
-respective sections.
-
-KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK must be enabled for x2APIC to work
-in logical mode or with more than 255 VCPUs.  Otherwise, KVM treats 0xff
-as a broadcast even in x2APIC mode in order to support physical x2APIC
-without interrupt remapping.  This is undesirable in logical mode,
-where 0xff represents CPUs 0-7 in cluster 0.
-
-7.8 KVM_CAP_S390_USER_INSTR0
-
-Architectures: s390
-Parameters: none
-
-With this capability enabled, all illegal instructions 0x0000 (2 bytes) will
-be intercepted and forwarded to user space. User space can use this
-mechanism e.g. to realize 2-byte software breakpoints. The kernel will
-not inject an operating exception for these instructions, user space has
-to take care of that.
-
-This capability can be enabled dynamically even if VCPUs were already
-created and are running.
-
-7.9 KVM_CAP_S390_GS
-
-Architectures: s390
-Parameters: none
-Returns: 0 on success; -EINVAL if the machine does not support
-        guarded storage; -EBUSY if a VCPU has already been created.
-
-Allows use of guarded storage for the KVM guest.
-
-7.10 KVM_CAP_S390_AIS
-
-Architectures: s390
-Parameters: none
-
-Allow use of adapter-interruption suppression.
-Returns: 0 on success; -EBUSY if a VCPU has already been created.
-
-7.11 KVM_CAP_PPC_SMT
-
-Architectures: ppc
-Parameters: vsmt_mode, flags
-
-Enabling this capability on a VM provides userspace with a way to set
-the desired virtual SMT mode (i.e. the number of virtual CPUs per
-virtual core).  The virtual SMT mode, vsmt_mode, must be a power of 2
-between 1 and 8.  On POWER8, vsmt_mode must also be no greater than
-the number of threads per subcore for the host.  Currently flags must
-be 0.  A successful call to enable this capability will result in
-vsmt_mode being returned when the KVM_CAP_PPC_SMT capability is
-subsequently queried for the VM.  This capability is only supported by
-HV KVM, and can only be set before any VCPUs have been created.
-The KVM_CAP_PPC_SMT_POSSIBLE capability indicates which virtual SMT
-modes are available.
-
-7.12 KVM_CAP_PPC_FWNMI
-
-Architectures: ppc
-Parameters: none
-
-With this capability a machine check exception in the guest address
-space will cause KVM to exit the guest with NMI exit reason. This
-enables QEMU to build error log and branch to guest kernel registered
-machine check handling routine. Without this capability KVM will
-branch to guests' 0x200 interrupt vector.
-
-7.13 KVM_CAP_X86_DISABLE_EXITS
-
-Architectures: x86
-Parameters: args[0] defines which exits are disabled
-Returns: 0 on success, -EINVAL when args[0] contains invalid exits
-
-Valid bits in args[0] are
-
-#define KVM_X86_DISABLE_EXITS_MWAIT            (1 << 0)
-#define KVM_X86_DISABLE_EXITS_HLT              (1 << 1)
-#define KVM_X86_DISABLE_EXITS_PAUSE            (1 << 2)
-#define KVM_X86_DISABLE_EXITS_CSTATE           (1 << 3)
-
-Enabling this capability on a VM provides userspace with a way to no
-longer intercept some instructions for improved latency in some
-workloads, and is suggested when vCPUs are associated to dedicated
-physical CPUs.  More bits can be added in the future; userspace can
-just pass the KVM_CHECK_EXTENSION result to KVM_ENABLE_CAP to disable
-all such vmexits.
-
-Do not enable KVM_FEATURE_PV_UNHALT if you disable HLT exits.
-
-7.14 KVM_CAP_S390_HPAGE_1M
-
-Architectures: s390
-Parameters: none
-Returns: 0 on success, -EINVAL if hpage module parameter was not set
-        or cmma is enabled, or the VM has the KVM_VM_S390_UCONTROL
-        flag set
-
-With this capability the KVM support for memory backing with 1m pages
-through hugetlbfs can be enabled for a VM. After the capability is
-enabled, cmma can't be enabled anymore and pfmfi and the storage key
-interpretation are disabled. If cmma has already been enabled or the
-hpage module parameter is not set to 1, -EINVAL is returned.
-
-While it is generally possible to create a huge page backed VM without
-this capability, the VM will not be able to run.
-
-7.15 KVM_CAP_MSR_PLATFORM_INFO
-
-Architectures: x86
-Parameters: args[0] whether feature should be enabled or not
-
-With this capability, a guest may read the MSR_PLATFORM_INFO MSR. Otherwise,
-a #GP would be raised when the guest tries to access. Currently, this
-capability does not enable write permissions of this MSR for the guest.
-
-7.16 KVM_CAP_PPC_NESTED_HV
-
-Architectures: ppc
-Parameters: none
-Returns: 0 on success, -EINVAL when the implementation doesn't support
-        nested-HV virtualization.
-
-HV-KVM on POWER9 and later systems allows for "nested-HV"
-virtualization, which provides a way for a guest VM to run guests that
-can run using the CPU's supervisor mode (privileged non-hypervisor
-state).  Enabling this capability on a VM depends on the CPU having
-the necessary functionality and on the facility being enabled with a
-kvm-hv module parameter.
-
-7.17 KVM_CAP_EXCEPTION_PAYLOAD
-
-Architectures: x86
-Parameters: args[0] whether feature should be enabled or not
-
-With this capability enabled, CR2 will not be modified prior to the
-emulated VM-exit when L1 intercepts a #PF exception that occurs in
-L2. Similarly, for kvm-intel only, DR6 will not be modified prior to
-the emulated VM-exit when L1 intercepts a #DB exception that occurs in
-L2. As a result, when KVM_GET_VCPU_EVENTS reports a pending #PF (or
-#DB) exception for L2, exception.has_payload will be set and the
-faulting address (or the new DR6 bits*) will be reported in the
-exception_payload field. Similarly, when userspace injects a #PF (or
-#DB) into L2 using KVM_SET_VCPU_EVENTS, it is expected to set
-exception.has_payload and to put the faulting address (or the new DR6
-bits*) in the exception_payload field.
-
-This capability also enables exception.pending in struct
-kvm_vcpu_events, which allows userspace to distinguish between pending
-and injected exceptions.
-
-
-* For the new DR6 bits, note that bit 16 is set iff the #DB exception
-  will clear DR6.RTM.
-
-7.18 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
-
-Architectures: x86, arm, arm64, mips
-Parameters: args[0] whether feature should be enabled or not
-
-With this capability enabled, KVM_GET_DIRTY_LOG will not automatically
-clear and write-protect all pages that are returned as dirty.
-Rather, userspace will have to do this operation separately using
-KVM_CLEAR_DIRTY_LOG.
-
-At the cost of a slightly more complicated operation, this provides better
-scalability and responsiveness for two reasons.  First,
-KVM_CLEAR_DIRTY_LOG ioctl can operate on a 64-page granularity rather
-than requiring to sync a full memslot; this ensures that KVM does not
-take spinlocks for an extended period of time.  Second, in some cases a
-large amount of time can pass between a call to KVM_GET_DIRTY_LOG and
-userspace actually using the data in the page.  Pages can be modified
-during this time, which is inefficint for both the guest and userspace:
-the guest will incur a higher penalty due to write protection faults,
-while userspace can see false reports of dirty pages.  Manual reprotection
-helps reducing this time, improving guest performance and reducing the
-number of dirty log false positives.
-
-KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 was previously available under the name
-KVM_CAP_MANUAL_DIRTY_LOG_PROTECT, but the implementation had bugs that make
-it hard or impossible to use it correctly.  The availability of
-KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 signals that those bugs are fixed.
-Userspace should not try to use KVM_CAP_MANUAL_DIRTY_LOG_PROTECT.
-
-8. Other capabilities.
-----------------------
-
-This section lists capabilities that give information about other
-features of the KVM implementation.
-
-8.1 KVM_CAP_PPC_HWRNG
-
-Architectures: ppc
-
-This capability, if KVM_CHECK_EXTENSION indicates that it is
-available, means that that the kernel has an implementation of the
-H_RANDOM hypercall backed by a hardware random-number generator.
-If present, the kernel H_RANDOM handler can be enabled for guest use
-with the KVM_CAP_PPC_ENABLE_HCALL capability.
-
-8.2 KVM_CAP_HYPERV_SYNIC
-
-Architectures: x86
-This capability, if KVM_CHECK_EXTENSION indicates that it is
-available, means that that the kernel has an implementation of the
-Hyper-V Synthetic interrupt controller(SynIC). Hyper-V SynIC is
-used to support Windows Hyper-V based guest paravirt drivers(VMBus).
-
-In order to use SynIC, it has to be activated by setting this
-capability via KVM_ENABLE_CAP ioctl on the vcpu fd. Note that this
-will disable the use of APIC hardware virtualization even if supported
-by the CPU, as it's incompatible with SynIC auto-EOI behavior.
-
-8.3 KVM_CAP_PPC_RADIX_MMU
-
-Architectures: ppc
-
-This capability, if KVM_CHECK_EXTENSION indicates that it is
-available, means that that the kernel can support guests using the
-radix MMU defined in Power ISA V3.00 (as implemented in the POWER9
-processor).
-
-8.4 KVM_CAP_PPC_HASH_MMU_V3
-
-Architectures: ppc
-
-This capability, if KVM_CHECK_EXTENSION indicates that it is
-available, means that that the kernel can support guests using the
-hashed page table MMU defined in Power ISA V3.00 (as implemented in
-the POWER9 processor), including in-memory segment tables.
-
-8.5 KVM_CAP_MIPS_VZ
-
-Architectures: mips
-
-This capability, if KVM_CHECK_EXTENSION on the main kvm handle indicates that
-it is available, means that full hardware assisted virtualization capabilities
-of the hardware are available for use through KVM. An appropriate
-KVM_VM_MIPS_* type must be passed to KVM_CREATE_VM to create a VM which
-utilises it.
-
-If KVM_CHECK_EXTENSION on a kvm VM handle indicates that this capability is
-available, it means that the VM is using full hardware assisted virtualization
-capabilities of the hardware. This is useful to check after creating a VM with
-KVM_VM_MIPS_DEFAULT.
-
-The value returned by KVM_CHECK_EXTENSION should be compared against known
-values (see below). All other values are reserved. This is to allow for the
-possibility of other hardware assisted virtualization implementations which
-may be incompatible with the MIPS VZ ASE.
-
- 0: The trap & emulate implementation is in use to run guest code in user
-    mode. Guest virtual memory segments are rearranged to fit the guest in the
-    user mode address space.
-
- 1: The MIPS VZ ASE is in use, providing full hardware assisted
-    virtualization, including standard guest virtual memory segments.
-
-8.6 KVM_CAP_MIPS_TE
-
-Architectures: mips
-
-This capability, if KVM_CHECK_EXTENSION on the main kvm handle indicates that
-it is available, means that the trap & emulate implementation is available to
-run guest code in user mode, even if KVM_CAP_MIPS_VZ indicates that hardware
-assisted virtualisation is also available. KVM_VM_MIPS_TE (0) must be passed
-to KVM_CREATE_VM to create a VM which utilises it.
-
-If KVM_CHECK_EXTENSION on a kvm VM handle indicates that this capability is
-available, it means that the VM is using trap & emulate.
-
-8.7 KVM_CAP_MIPS_64BIT
-
-Architectures: mips
-
-This capability indicates the supported architecture type of the guest, i.e. the
-supported register and address width.
-
-The values returned when this capability is checked by KVM_CHECK_EXTENSION on a
-kvm VM handle correspond roughly to the CP0_Config.AT register field, and should
-be checked specifically against known values (see below). All other values are
-reserved.
-
- 0: MIPS32 or microMIPS32.
-    Both registers and addresses are 32-bits wide.
-    It will only be possible to run 32-bit guest code.
-
- 1: MIPS64 or microMIPS64 with access only to 32-bit compatibility segments.
-    Registers are 64-bits wide, but addresses are 32-bits wide.
-    64-bit guest code may run but cannot access MIPS64 memory segments.
-    It will also be possible to run 32-bit guest code.
-
- 2: MIPS64 or microMIPS64 with access to all address segments.
-    Both registers and addresses are 64-bits wide.
-    It will be possible to run 64-bit or 32-bit guest code.
-
-8.9 KVM_CAP_ARM_USER_IRQ
-
-Architectures: arm, arm64
-This capability, if KVM_CHECK_EXTENSION indicates that it is available, means
-that if userspace creates a VM without an in-kernel interrupt controller, it
-will be notified of changes to the output level of in-kernel emulated devices,
-which can generate virtual interrupts, presented to the VM.
-For such VMs, on every return to userspace, the kernel
-updates the vcpu's run->s.regs.device_irq_level field to represent the actual
-output level of the device.
-
-Whenever kvm detects a change in the device output level, kvm guarantees at
-least one return to userspace before running the VM.  This exit could either
-be a KVM_EXIT_INTR or any other exit event, like KVM_EXIT_MMIO. This way,
-userspace can always sample the device output level and re-compute the state of
-the userspace interrupt controller.  Userspace should always check the state
-of run->s.regs.device_irq_level on every kvm exit.
-The value in run->s.regs.device_irq_level can represent both level and edge
-triggered interrupt signals, depending on the device.  Edge triggered interrupt
-signals will exit to userspace with the bit in run->s.regs.device_irq_level
-set exactly once per edge signal.
-
-The field run->s.regs.device_irq_level is available independent of
-run->kvm_valid_regs or run->kvm_dirty_regs bits.
-
-If KVM_CAP_ARM_USER_IRQ is supported, the KVM_CHECK_EXTENSION ioctl returns a
-number larger than 0 indicating the version of this capability is implemented
-and thereby which bits in in run->s.regs.device_irq_level can signal values.
-
-Currently the following bits are defined for the device_irq_level bitmap:
-
-  KVM_CAP_ARM_USER_IRQ >= 1:
-
-    KVM_ARM_DEV_EL1_VTIMER -  EL1 virtual timer
-    KVM_ARM_DEV_EL1_PTIMER -  EL1 physical timer
-    KVM_ARM_DEV_PMU        -  ARM PMU overflow interrupt signal
-
-Future versions of kvm may implement additional events. These will get
-indicated by returning a higher number from KVM_CHECK_EXTENSION and will be
-listed above.
-
-8.10 KVM_CAP_PPC_SMT_POSSIBLE
-
-Architectures: ppc
-
-Querying this capability returns a bitmap indicating the possible
-virtual SMT modes that can be set using KVM_CAP_PPC_SMT.  If bit N
-(counting from the right) is set, then a virtual SMT mode of 2^N is
-available.
-
-8.11 KVM_CAP_HYPERV_SYNIC2
-
-Architectures: x86
-
-This capability enables a newer version of Hyper-V Synthetic interrupt
-controller (SynIC).  The only difference with KVM_CAP_HYPERV_SYNIC is that KVM
-doesn't clear SynIC message and event flags pages when they are enabled by
-writing to the respective MSRs.
-
-8.12 KVM_CAP_HYPERV_VP_INDEX
-
-Architectures: x86
-
-This capability indicates that userspace can load HV_X64_MSR_VP_INDEX msr.  Its
-value is used to denote the target vcpu for a SynIC interrupt.  For
-compatibilty, KVM initializes this msr to KVM's internal vcpu index.  When this
-capability is absent, userspace can still query this msr's value.
-
-8.13 KVM_CAP_S390_AIS_MIGRATION
-
-Architectures: s390
-Parameters: none
-
-This capability indicates if the flic device will be able to get/set the
-AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows
-to discover this without having to create a flic device.
-
-8.14 KVM_CAP_S390_PSW
-
-Architectures: s390
-
-This capability indicates that the PSW is exposed via the kvm_run structure.
-
-8.15 KVM_CAP_S390_GMAP
-
-Architectures: s390
-
-This capability indicates that the user space memory used as guest mapping can
-be anywhere in the user memory address space, as long as the memory slots are
-aligned and sized to a segment (1MB) boundary.
-
-8.16 KVM_CAP_S390_COW
-
-Architectures: s390
-
-This capability indicates that the user space memory used as guest mapping can
-use copy-on-write semantics as well as dirty pages tracking via read-only page
-tables.
-
-8.17 KVM_CAP_S390_BPB
-
-Architectures: s390
-
-This capability indicates that kvm will implement the interfaces to handle
-reset, migration and nested KVM for branch prediction blocking. The stfle
-facility 82 should not be provided to the guest without this capability.
-
-8.18 KVM_CAP_HYPERV_TLBFLUSH
-
-Architectures: x86
-
-This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush
-hypercalls:
-HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx,
-HvFlushVirtualAddressList, HvFlushVirtualAddressListEx.
-
-8.19 KVM_CAP_ARM_INJECT_SERROR_ESR
-
-Architectures: arm, arm64
-
-This capability indicates that userspace can specify (via the
-KVM_SET_VCPU_EVENTS ioctl) the syndrome value reported to the guest when it
-takes a virtual SError interrupt exception.
-If KVM advertises this capability, userspace can only specify the ISS field for
-the ESR syndrome. Other parts of the ESR, such as the EC are generated by the
-CPU when the exception is taken. If this virtual SError is taken to EL1 using
-AArch64, this value will be reported in the ISS field of ESR_ELx.
-
-See KVM_CAP_VCPU_EVENTS for more details.
-8.20 KVM_CAP_HYPERV_SEND_IPI
-
-Architectures: x86
-
-This capability indicates that KVM supports paravirtualized Hyper-V IPI send
-hypercalls:
-HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx.
diff --git a/Documentation/virtual/kvm/arm/hyp-abi.txt b/Documentation/virtual/kvm/arm/hyp-abi.txt
deleted file mode 100644 (file)
index a20a0be..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-* Internal ABI between the kernel and HYP
-
-This file documents the interaction between the Linux kernel and the
-hypervisor layer when running Linux as a hypervisor (for example
-KVM). It doesn't cover the interaction of the kernel with the
-hypervisor when running as a guest (under Xen, KVM or any other
-hypervisor), or any hypervisor-specific interaction when the kernel is
-used as a host.
-
-On arm and arm64 (without VHE), the kernel doesn't run in hypervisor
-mode, but still needs to interact with it, allowing a built-in
-hypervisor to be either installed or torn down.
-
-In order to achieve this, the kernel must be booted at HYP (arm) or
-EL2 (arm64), allowing it to install a set of stubs before dropping to
-SVC/EL1. These stubs are accessible by using a 'hvc #0' instruction,
-and only act on individual CPUs.
-
-Unless specified otherwise, any built-in hypervisor must implement
-these functions (see arch/arm{,64}/include/asm/virt.h):
-
-* r0/x0 = HVC_SET_VECTORS
-  r1/x1 = vectors
-
-  Set HVBAR/VBAR_EL2 to 'vectors' to enable a hypervisor. 'vectors'
-  must be a physical address, and respect the alignment requirements
-  of the architecture. Only implemented by the initial stubs, not by
-  Linux hypervisors.
-
-* r0/x0 = HVC_RESET_VECTORS
-
-  Turn HYP/EL2 MMU off, and reset HVBAR/VBAR_EL2 to the initials
-  stubs' exception vector value. This effectively disables an existing
-  hypervisor.
-
-* r0/x0 = HVC_SOFT_RESTART
-  r1/x1 = restart address
-  x2 = x0's value when entering the next payload (arm64)
-  x3 = x1's value when entering the next payload (arm64)
-  x4 = x2's value when entering the next payload (arm64)
-
-  Mask all exceptions, disable the MMU, move the arguments into place
-  (arm64 only), and jump to the restart address while at HYP/EL2. This
-  hypercall is not expected to return to its caller.
-
-Any other value of r0/x0 triggers a hypervisor-specific handling,
-which is not documented here.
-
-The return value of a stub hypercall is held by r0/x0, and is 0 on
-success, and HVC_STUB_ERR on error. A stub hypercall is allowed to
-clobber any of the caller-saved registers (x0-x18 on arm64, r0-r3 and
-ip on arm). It is thus recommended to use a function call to perform
-the hypercall.
diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
deleted file mode 100644 (file)
index 559586f..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-KVM implements the PSCI (Power State Coordination Interface)
-specification in order to provide services such as CPU on/off, reset
-and power-off to the guest.
-
-The PSCI specification is regularly updated to provide new features,
-and KVM implements these updates if they make sense from a virtualization
-point of view.
-
-This means that a guest booted on two different versions of KVM can
-observe two different "firmware" revisions. This could cause issues if
-a given guest is tied to a particular PSCI revision (unlikely), or if
-a migration causes a different PSCI version to be exposed out of the
-blue to an unsuspecting guest.
-
-In order to remedy this situation, KVM exposes a set of "firmware
-pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
-interface. These registers can be saved/restored by userspace, and set
-to a convenient value if required.
-
-The following register is defined:
-
-* KVM_REG_ARM_PSCI_VERSION:
-
-  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
-    (and thus has already been initialized)
-  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
-    highest PSCI version implemented by KVM and compatible with v0.2)
-  - Allows any PSCI version implemented by KVM and compatible with
-    v0.2 to be set with SET_ONE_REG
-  - Affects the whole VM (even if the register view is per-vcpu)
-
-* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
-  Holds the state of the firmware support to mitigate CVE-2017-5715, as
-  offered by KVM to the guest via a HVC call. The workaround is described
-  under SMCCC_ARCH_WORKAROUND_1 in [1].
-  Accepted values are:
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL: KVM does not offer
-      firmware support for the workaround. The mitigation status for the
-      guest is unknown.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL: The workaround HVC call is
-      available to the guest and required for the mitigation.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED: The workaround HVC call
-      is available to the guest, but it is not needed on this VCPU.
-
-* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
-  Holds the state of the firmware support to mitigate CVE-2018-3639, as
-  offered by KVM to the guest via a HVC call. The workaround is described
-  under SMCCC_ARCH_WORKAROUND_2 in [1].
-  Accepted values are:
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL: A workaround is not
-      available. KVM does not offer firmware support for the workaround.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN: The workaround state is
-      unknown. KVM does not offer firmware support for the workaround.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL: The workaround is available,
-      and can be disabled by a vCPU. If
-      KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED is set, it is active for
-      this vCPU.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED: The workaround is
-      always active on this vCPU or it is not needed.
-
-[1] https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf
diff --git a/Documentation/virtual/kvm/cpuid.rst b/Documentation/virtual/kvm/cpuid.rst
deleted file mode 100644 (file)
index 01b081f..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==============
-KVM CPUID bits
-==============
-
-:Author: Glauber Costa <glommer@gmail.com>
-
-A guest running on a kvm host, can check some of its features using
-cpuid. This is not always guaranteed to work, since userspace can
-mask-out some, or even all KVM-related cpuid features before launching
-a guest.
-
-KVM cpuid functions are:
-
-function: KVM_CPUID_SIGNATURE (0x40000000)
-
-returns::
-
-   eax = 0x40000001
-   ebx = 0x4b4d564b
-   ecx = 0x564b4d56
-   edx = 0x4d
-
-Note that this value in ebx, ecx and edx corresponds to the string "KVMKVMKVM".
-The value in eax corresponds to the maximum cpuid function present in this leaf,
-and will be updated if more functions are added in the future.
-Note also that old hosts set eax value to 0x0. This should
-be interpreted as if the value was 0x40000001.
-This function queries the presence of KVM cpuid leafs.
-
-function: define KVM_CPUID_FEATURES (0x40000001)
-
-returns::
-
-          ebx, ecx
-          eax = an OR'ed group of (1 << flag)
-
-where ``flag`` is defined as below:
-
-================================= =========== ================================
-flag                              value       meaning
-================================= =========== ================================
-KVM_FEATURE_CLOCKSOURCE           0           kvmclock available at msrs
-                                              0x11 and 0x12
-
-KVM_FEATURE_NOP_IO_DELAY          1           not necessary to perform delays
-                                              on PIO operations
-
-KVM_FEATURE_MMU_OP                2           deprecated
-
-KVM_FEATURE_CLOCKSOURCE2          3           kvmclock available at msrs
-
-                                              0x4b564d00 and 0x4b564d01
-KVM_FEATURE_ASYNC_PF              4           async pf can be enabled by
-                                              writing to msr 0x4b564d02
-
-KVM_FEATURE_STEAL_TIME            5           steal time can be enabled by
-                                              writing to msr 0x4b564d03
-
-KVM_FEATURE_PV_EOI                6           paravirtualized end of interrupt
-                                              handler can be enabled by
-                                              writing to msr 0x4b564d04
-
-KVM_FEATURE_PV_UNHAULT            7           guest checks this feature bit
-                                              before enabling paravirtualized
-                                              spinlock support
-
-KVM_FEATURE_PV_TLB_FLUSH          9           guest checks this feature bit
-                                              before enabling paravirtualized
-                                              tlb flush
-
-KVM_FEATURE_ASYNC_PF_VMEXIT       10          paravirtualized async PF VM EXIT
-                                              can be enabled by setting bit 2
-                                              when writing to msr 0x4b564d02
-
-KVM_FEATURE_PV_SEND_IPI           11          guest checks this feature bit
-                                              before enabling paravirtualized
-                                              sebd IPIs
-
-KVM_FEATURE_PV_POLL_CONTROL       12          host-side polling on HLT can
-                                              be disabled by writing
-                                              to msr 0x4b564d05.
-
-KVM_FEATURE_PV_SCHED_YIELD        13          guest checks this feature bit
-                                              before using paravirtualized
-                                              sched yield.
-
-KVM_FEATURE_CLOCSOURCE_STABLE_BIT 24          host will warn if no guest-side
-                                              per-cpu warps are expeced in
-                                              kvmclock
-================================= =========== ================================
-
-::
-
-      edx = an OR'ed group of (1 << flag)
-
-Where ``flag`` here is defined as below:
-
-================== ============ =================================
-flag               value        meaning
-================== ============ =================================
-KVM_HINTS_REALTIME 0            guest checks this feature bit to
-                                determine that vCPUs are never
-                                preempted for an unlimited time
-                                allowing optimizations
-================== ============ =================================
diff --git a/Documentation/virtual/kvm/devices/README b/Documentation/virtual/kvm/devices/README
deleted file mode 100644 (file)
index 34a6983..0000000
+++ /dev/null
@@ -1 +0,0 @@
-This directory contains specific device bindings for KVM_CAP_DEVICE_CTRL.
diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
deleted file mode 100644 (file)
index eeaa95b..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-ARM Virtual Interrupt Translation Service (ITS)
-===============================================
-
-Device types supported:
-  KVM_DEV_TYPE_ARM_VGIC_ITS    ARM Interrupt Translation Service Controller
-
-The ITS allows MSI(-X) interrupts to be injected into guests. This extension is
-optional.  Creating a virtual ITS controller also requires a host GICv3 (see
-arm-vgic-v3.txt), but does not depend on having physical ITS controllers.
-
-There can be multiple ITS controllers per guest, each of them has to have
-a separate, non-overlapping MMIO region.
-
-
-Groups:
-  KVM_DEV_ARM_VGIC_GRP_ADDR
-  Attributes:
-    KVM_VGIC_ITS_ADDR_TYPE (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3 ITS
-      control register frame.
-      This address needs to be 64K aligned and the region covers 128K.
-  Errors:
-    -E2BIG:  Address outside of addressable IPA range
-    -EINVAL: Incorrectly aligned address
-    -EEXIST: Address already configured
-    -EFAULT: Invalid user pointer for attr->addr.
-    -ENODEV: Incorrect attribute or the ITS is not supported.
-
-
-  KVM_DEV_ARM_VGIC_GRP_CTRL
-  Attributes:
-    KVM_DEV_ARM_VGIC_CTRL_INIT
-      request the initialization of the ITS, no additional parameter in
-      kvm_device_attr.addr.
-
-    KVM_DEV_ARM_ITS_CTRL_RESET
-      reset the ITS, no additional parameter in kvm_device_attr.addr.
-      See "ITS Reset State" section.
-
-    KVM_DEV_ARM_ITS_SAVE_TABLES
-      save the ITS table data into guest RAM, at the location provisioned
-      by the guest in corresponding registers/table entries.
-
-      The layout of the tables in guest memory defines an ABI. The entries
-      are laid out in little endian format as described in the last paragraph.
-
-    KVM_DEV_ARM_ITS_RESTORE_TABLES
-      restore the ITS tables from guest RAM to ITS internal structures.
-
-      The GICV3 must be restored before the ITS and all ITS registers but
-      the GITS_CTLR must be restored before restoring the ITS tables.
-
-      The GITS_IIDR read-only register must also be restored before
-      calling KVM_DEV_ARM_ITS_RESTORE_TABLES as the IIDR revision field
-      encodes the ABI revision.
-
-      The expected ordering when restoring the GICv3/ITS is described in section
-      "ITS Restore Sequence".
-
-  Errors:
-    -ENXIO:  ITS not properly configured as required prior to setting
-             this attribute
-    -ENOMEM: Memory shortage when allocating ITS internal data
-    -EINVAL: Inconsistent restored data
-    -EFAULT: Invalid guest ram access
-    -EBUSY:  One or more VCPUS are running
-    -EACCES: The virtual ITS is backed by a physical GICv4 ITS, and the
-            state is not available
-
-  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
-  Attributes:
-      The attr field of kvm_device_attr encodes the offset of the
-      ITS register, relative to the ITS control frame base address
-      (ITS_base).
-
-      kvm_device_attr.addr points to a __u64 value whatever the width
-      of the addressed register (32/64 bits). 64 bit registers can only
-      be accessed with full length.
-
-      Writes to read-only registers are ignored by the kernel except for:
-      - GITS_CREADR. It must be restored otherwise commands in the queue
-        will be re-executed after restoring CWRITER. GITS_CREADR must be
-        restored before restoring the GITS_CTLR which is likely to enable the
-        ITS. Also it must be restored after GITS_CBASER since a write to
-        GITS_CBASER resets GITS_CREADR.
-      - GITS_IIDR. The Revision field encodes the table layout ABI revision.
-        In the future we might implement direct injection of virtual LPIs.
-        This will require an upgrade of the table layout and an evolution of
-        the ABI. GITS_IIDR must be restored before calling
-        KVM_DEV_ARM_ITS_RESTORE_TABLES.
-
-      For other registers, getting or setting a register has the same
-      effect as reading/writing the register on real hardware.
-  Errors:
-    -ENXIO: Offset does not correspond to any supported register
-    -EFAULT: Invalid user pointer for attr->addr
-    -EINVAL: Offset is not 64-bit aligned
-    -EBUSY: one or more VCPUS are running
-
- ITS Restore Sequence:
- -------------------------
-
-The following ordering must be followed when restoring the GIC and the ITS:
-a) restore all guest memory and create vcpus
-b) restore all redistributors
-c) provide the ITS base address
-   (KVM_DEV_ARM_VGIC_GRP_ADDR)
-d) restore the ITS in the following order:
-   1. Restore GITS_CBASER
-   2. Restore all other GITS_ registers, except GITS_CTLR!
-   3. Load the ITS table data (KVM_DEV_ARM_ITS_RESTORE_TABLES)
-   4. Restore GITS_CTLR
-
-Then vcpus can be started.
-
- ITS Table ABI REV0:
- -------------------
-
- Revision 0 of the ABI only supports the features of a virtual GICv3, and does
- not support a virtual GICv4 with support for direct injection of virtual
- interrupts for nested hypervisors.
-
- The device table and ITT are indexed by the DeviceID and EventID,
- respectively. The collection table is not indexed by CollectionID, and the
- entries in the collection are listed in no particular order.
- All entries are 8 bytes.
-
- Device Table Entry (DTE):
-
- bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
- values:   | V |   next    | ITT_addr |  Size   |
-
- where;
- - V indicates whether the entry is valid. If not, other fields
-   are not meaningful.
- - next: equals to 0 if this entry is the last one; otherwise it
-   corresponds to the DeviceID offset to the next DTE, capped by
-   2^14 -1.
- - ITT_addr matches bits [51:8] of the ITT address (256 Byte aligned).
- - Size specifies the supported number of bits for the EventID,
-   minus one
-
- Collection Table Entry (CTE):
-
- bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
- values:   | V |    RES0    |  RDBase   |    ICID     |
-
- where:
- - V indicates whether the entry is valid. If not, other fields are
-   not meaningful.
- - RES0: reserved field with Should-Be-Zero-or-Preserved behavior.
- - RDBase is the PE number (GICR_TYPER.Processor_Number semantic),
- - ICID is the collection ID
-
- Interrupt Translation Entry (ITE):
-
- bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
- values:   |    next   |   pINTID  |  ICID    |
-
- where:
- - next: equals to 0 if this entry is the last one; otherwise it corresponds
-   to the EventID offset to the next ITE capped by 2^16 -1.
- - pINTID is the physical LPI ID; if zero, it means the entry is not valid
-   and other fields are not meaningful.
- - ICID is the collection ID
-
- ITS Reset State:
- ----------------
-
-RESET returns the ITS to the same state that it was when first created and
-initialized. When the RESET command returns, the following things are
-guaranteed:
-
-- The ITS is not enabled and quiescent
-  GITS_CTLR.Enabled = 0 .Quiescent=1
-- There is no internally cached state
-- No collection or device table are used
-  GITS_BASER<n>.Valid = 0
-- GITS_CBASER = 0, GITS_CREADR = 0, GITS_CWRITER = 0
-- The ABI version is unchanged and remains the one set when the ITS
-  device was first created.
diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
deleted file mode 100644 (file)
index ff290b4..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
-==============================================================
-
-
-Device types supported:
-  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
-
-Only one VGIC instance may be instantiated through this API.  The created VGIC
-will act as the VM interrupt controller, requiring emulated user-space devices
-to inject interrupts to the VGIC instead of directly to CPUs.  It is not
-possible to create both a GICv3 and GICv2 on the same VM.
-
-Creating a guest GICv3 device requires a host GICv3 as well.
-
-
-Groups:
-  KVM_DEV_ARM_VGIC_GRP_ADDR
-  Attributes:
-    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3 distributor
-      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-      This address needs to be 64K aligned and the region covers 64 KByte.
-
-    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3
-      redistributor register mappings. There are two 64K pages for each
-      VCPU and all of the redistributor pages are contiguous.
-      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-      This address needs to be 64K aligned.
-
-    KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION (rw, 64-bit)
-      The attribute data pointed to by kvm_device_attr.addr is a __u64 value:
-      bits:     | 63   ....  52  |  51   ....   16 | 15 - 12  |11 - 0
-      values:   |     count      |       base      |  flags   | index
-      - index encodes the unique redistributor region index
-      - flags: reserved for future use, currently 0
-      - base field encodes bits [51:16] of the guest physical base address
-        of the first redistributor in the region.
-      - count encodes the number of redistributors in the region. Must be
-        greater than 0.
-      There are two 64K pages for each redistributor in the region and
-      redistributors are laid out contiguously within the region. Regions
-      are filled with redistributors in the index order. The sum of all
-      region count fields must be greater than or equal to the number of
-      VCPUs. Redistributor regions must be registered in the incremental
-      index order, starting from index 0.
-      The characteristics of a specific redistributor region can be read
-      by presetting the index field in the attr data.
-      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-
-  It is invalid to mix calls with KVM_VGIC_V3_ADDR_TYPE_REDIST and
-  KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attributes.
-
-  Errors:
-    -E2BIG:  Address outside of addressable IPA range
-    -EINVAL: Incorrectly aligned address, bad redistributor region
-             count/index, mixed redistributor region attribute usage
-    -EEXIST: Address already configured
-    -ENOENT: Attempt to read the characteristics of a non existing
-             redistributor region
-    -ENXIO:  The group or attribute is unknown/unsupported for this device
-             or hardware support is missing.
-    -EFAULT: Invalid user pointer for attr->addr.
-
-
-  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
-  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
-  Attributes:
-    The attr field of kvm_device_attr encodes two values:
-    bits:     | 63   ....  32  |  31   ....    0 |
-    values:   |      mpidr     |      offset     |
-
-    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
-    __u32 value.  64-bit registers must be accessed by separately accessing the
-    lower and higher word.
-
-    Writes to read-only registers are ignored by the kernel.
-
-    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
-    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
-    specified by the mpidr.
-
-    The offset is relative to the "[Re]Distributor base address" as defined
-    in the GICv3/4 specs.  Getting or setting such a register has the same
-    effect as reading or writing the register on real hardware, except for the
-    following registers: GICD_STATUSR, GICR_STATUSR, GICD_ISPENDR,
-    GICR_ISPENDR0, GICD_ICPENDR, and GICR_ICPENDR0.  These registers behave
-    differently when accessed via this interface compared to their
-    architecturally defined behavior to allow software a full view of the
-    VGIC's internal state.
-
-    The mpidr field is used to specify which
-    redistributor is accessed.  The mpidr is ignored for the distributor.
-
-    The mpidr encoding is based on the affinity information in the
-    architecture defined MPIDR, and the field is encoded as follows:
-      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
-      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
-
-    Note that distributor fields are not banked, but return the same value
-    regardless of the mpidr used to access the register.
-
-    GICD_IIDR.Revision is updated when the KVM implementation is changed in a
-    way directly observable by the guest or userspace.  Userspace should read
-    GICD_IIDR from KVM and write back the read value to confirm its expected
-    behavior is aligned with the KVM implementation.  Userspace should set
-    GICD_IIDR before setting any other registers to ensure the expected
-    behavior.
-
-
-    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
-    that a write of a clear bit has no effect, whereas a write with a set bit
-    clears that value.  To allow userspace to freely set the values of these two
-    registers, setting the attributes with the register offsets for these two
-    registers simply sets the non-reserved bits to the value written.
-
-
-    Accesses (reads and writes) to the GICD_ISPENDR register region and
-    GICR_ISPENDR0 registers get/set the value of the latched pending state for
-    the interrupts.
-
-    This is identical to the value returned by a guest read from ISPENDR for an
-    edge triggered interrupt, but may differ for level triggered interrupts.
-    For edge triggered interrupts, once an interrupt becomes pending (whether
-    because of an edge detected on the input line or because of a guest write
-    to ISPENDR) this state is "latched", and only cleared when either the
-    interrupt is activated or when the guest writes to ICPENDR. A level
-    triggered interrupt may be pending either because the level input is held
-    high by a device, or because of a guest write to the ISPENDR register. Only
-    ISPENDR writes are latched; if the device lowers the line level then the
-    interrupt is no longer pending unless the guest also wrote to ISPENDR, and
-    conversely writes to ICPENDR or activations of the interrupt do not clear
-    the pending status if the line level is still being held high.  (These
-    rules are documented in the GICv3 specification descriptions of the ICPENDR
-    and ISPENDR registers.) For a level triggered interrupt the value accessed
-    here is that of the latch which is set by ISPENDR and cleared by ICPENDR or
-    interrupt activation, whereas the value returned by a guest read from
-    ISPENDR is the logical OR of the latch value and the input line level.
-
-    Raw access to the latch state is provided to userspace so that it can save
-    and restore the entire GIC internal state (which is defined by the
-    combination of the current input line level and the latch state, and cannot
-    be deduced from purely the line level and the value of the ISPENDR
-    registers).
-
-    Accesses to GICD_ICPENDR register region and GICR_ICPENDR0 registers have
-    RAZ/WI semantics, meaning that reads always return 0 and writes are always
-    ignored.
-
-  Errors:
-    -ENXIO: Getting or setting this register is not yet supported
-    -EBUSY: One or more VCPUs are running
-
-
-  KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS
-  Attributes:
-    The attr field of kvm_device_attr encodes two values:
-    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
-    values:   |         mpidr         |      RES     |    instr    |
-
-    The mpidr field encodes the CPU ID based on the affinity information in the
-    architecture defined MPIDR, and the field is encoded as follows:
-      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
-      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
-
-    The instr field encodes the system register to access based on the fields
-    defined in the A64 instruction set encoding for system register access
-    (RES means the bits are reserved for future use and should be zero):
-
-      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
-      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
-
-    All system regs accessed through this API are (rw, 64-bit) and
-    kvm_device_attr.addr points to a __u64 value.
-
-    KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS accesses the CPU interface registers for the
-    CPU specified by the mpidr field.
-
-    CPU interface registers access is not implemented for AArch32 mode.
-    Error -ENXIO is returned when accessed in AArch32 mode.
-  Errors:
-    -ENXIO: Getting or setting this register is not yet supported
-    -EBUSY: VCPU is running
-    -EINVAL: Invalid mpidr or register value supplied
-
-
-  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
-  Attributes:
-    A value describing the number of interrupts (SGI, PPI and SPI) for
-    this GIC instance, ranging from 64 to 1024, in increments of 32.
-
-    kvm_device_attr.addr points to a __u32 value.
-
-  Errors:
-    -EINVAL: Value set is out of the expected range
-    -EBUSY: Value has already be set.
-
-
-  KVM_DEV_ARM_VGIC_GRP_CTRL
-  Attributes:
-    KVM_DEV_ARM_VGIC_CTRL_INIT
-      request the initialization of the VGIC, no additional parameter in
-      kvm_device_attr.addr.
-    KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES
-      save all LPI pending bits into guest RAM pending tables.
-
-      The first kB of the pending table is not altered by this operation.
-  Errors:
-    -ENXIO: VGIC not properly configured as required prior to calling
-     this attribute
-    -ENODEV: no online VCPU
-    -ENOMEM: memory shortage when allocating vgic internal data
-    -EFAULT: Invalid guest ram access
-    -EBUSY:  One or more VCPUS are running
-
-
-  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
-  Attributes:
-    The attr field of kvm_device_attr encodes the following values:
-    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
-    values:   |         mpidr         |      info       |   vINTID   |
-
-    The vINTID specifies which set of IRQs is reported on.
-
-    The info field specifies which information userspace wants to get or set
-    using this interface.  Currently we support the following info values:
-
-      VGIC_LEVEL_INFO_LINE_LEVEL:
-       Get/Set the input level of the IRQ line for a set of 32 contiguously
-       numbered interrupts.
-       vINTID must be a multiple of 32.
-
-       kvm_device_attr.addr points to a __u32 value which will contain a
-       bitmap where a set bit means the interrupt level is asserted.
-
-       Bit[n] indicates the status for interrupt vINTID + n.
-
-    SGIs and any interrupt with a higher ID than the number of interrupts
-    supported, will be RAZ/WI.  LPIs are always edge-triggered and are
-    therefore not supported by this interface.
-
-    PPIs are reported per VCPU as specified in the mpidr field, and SPIs are
-    reported with the same value regardless of the mpidr specified.
-
-    The mpidr field encodes the CPU ID based on the affinity information in the
-    architecture defined MPIDR, and the field is encoded as follows:
-      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
-      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
-  Errors:
-    -EINVAL: vINTID is not multiple of 32 or
-     info field is not VGIC_LEVEL_INFO_LINE_LEVEL
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
deleted file mode 100644 (file)
index 97b6518..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-ARM Virtual Generic Interrupt Controller v2 (VGIC)
-==================================================
-
-Device types supported:
-  KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0
-
-Only one VGIC instance may be instantiated through either this API or the
-legacy KVM_CREATE_IRQCHIP API.  The created VGIC will act as the VM interrupt
-controller, requiring emulated user-space devices to inject interrupts to the
-VGIC instead of directly to CPUs.
-
-GICv3 implementations with hardware compatibility support allow creating a
-guest GICv2 through this interface.  For information on creating a guest GICv3
-device and guest ITS devices, see arm-vgic-v3.txt.  It is not possible to
-create both a GICv3 and GICv2 device on the same VM.
-
-
-Groups:
-  KVM_DEV_ARM_VGIC_GRP_ADDR
-  Attributes:
-    KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
-      Base address in the guest physical address space of the GIC distributor
-      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
-      This address needs to be 4K aligned and the region covers 4 KByte.
-
-    KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
-      Base address in the guest physical address space of the GIC virtual cpu
-      interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
-      This address needs to be 4K aligned and the region covers 4 KByte.
-  Errors:
-    -E2BIG:  Address outside of addressable IPA range
-    -EINVAL: Incorrectly aligned address
-    -EEXIST: Address already configured
-    -ENXIO:  The group or attribute is unknown/unsupported for this device
-             or hardware support is missing.
-    -EFAULT: Invalid user pointer for attr->addr.
-
-  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
-  Attributes:
-    The attr field of kvm_device_attr encodes two values:
-    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
-    values:   |    reserved   | vcpu_index |      offset     |
-
-    All distributor regs are (rw, 32-bit)
-
-    The offset is relative to the "Distributor base address" as defined in the
-    GICv2 specs.  Getting or setting such a register has the same effect as
-    reading or writing the register on the actual hardware from the cpu whose
-    index is specified with the vcpu_index field.  Note that most distributor
-    fields are not banked, but return the same value regardless of the
-    vcpu_index used to access the register.
-
-    GICD_IIDR.Revision is updated when the KVM implementation of an emulated
-    GICv2 is changed in a way directly observable by the guest or userspace.
-    Userspace should read GICD_IIDR from KVM and write back the read value to
-    confirm its expected behavior is aligned with the KVM implementation.
-    Userspace should set GICD_IIDR before setting any other registers (both
-    KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_CPU_REGS) to ensure
-    the expected behavior. Unless GICD_IIDR has been set from userspace, writes
-    to the interrupt group registers (GICD_IGROUPR) are ignored.
-  Errors:
-    -ENXIO: Getting or setting this register is not yet supported
-    -EBUSY: One or more VCPUs are running
-    -EINVAL: Invalid vcpu_index supplied
-
-  KVM_DEV_ARM_VGIC_GRP_CPU_REGS
-  Attributes:
-    The attr field of kvm_device_attr encodes two values:
-    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
-    values:   |    reserved   | vcpu_index |      offset     |
-
-    All CPU interface regs are (rw, 32-bit)
-
-    The offset specifies the offset from the "CPU interface base address" as
-    defined in the GICv2 specs.  Getting or setting such a register has the
-    same effect as reading or writing the register on the actual hardware.
-
-    The Active Priorities Registers APRn are implementation defined, so we set a
-    fixed format for our implementation that fits with the model of a "GICv2
-    implementation without the security extensions" which we present to the
-    guest.  This interface always exposes four register APR[0-3] describing the
-    maximum possible 128 preemption levels.  The semantics of the register
-    indicate if any interrupts in a given preemption level are in the active
-    state by setting the corresponding bit.
-
-    Thus, preemption level X has one or more active interrupts if and only if:
-
-      APRn[X mod 32] == 0b1,  where n = X / 32
-
-    Bits for undefined preemption levels are RAZ/WI.
-
-    Note that this differs from a CPU's view of the APRs on hardware in which
-    a GIC without the security extensions expose group 0 and group 1 active
-    priorities in separate register groups, whereas we show a combined view
-    similar to GICv2's GICH_APR.
-
-    For historical reasons and to provide ABI compatibility with userspace we
-    export the GICC_PMR register in the format of the GICH_VMCR.VMPriMask
-    field in the lower 5 bits of a word, meaning that userspace must always
-    use the lower 5 bits to communicate with the KVM device and must shift the
-    value left by 3 places to obtain the actual priority mask level.
-
-  Errors:
-    -ENXIO: Getting or setting this register is not yet supported
-    -EBUSY: One or more VCPUs are running
-    -EINVAL: Invalid vcpu_index supplied
-
-  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
-  Attributes:
-    A value describing the number of interrupts (SGI, PPI and SPI) for
-    this GIC instance, ranging from 64 to 1024, in increments of 32.
-
-  Errors:
-    -EINVAL: Value set is out of the expected range
-    -EBUSY: Value has already be set, or GIC has already been initialized
-            with default values.
-
-  KVM_DEV_ARM_VGIC_GRP_CTRL
-  Attributes:
-    KVM_DEV_ARM_VGIC_CTRL_INIT
-      request the initialization of the VGIC or ITS, no additional parameter
-      in kvm_device_attr.addr.
-  Errors:
-    -ENXIO: VGIC not properly configured as required prior to calling
-     this attribute
-    -ENODEV: no online VCPU
-    -ENOMEM: memory shortage when allocating vgic internal data
diff --git a/Documentation/virtual/kvm/devices/mpic.txt b/Documentation/virtual/kvm/devices/mpic.txt
deleted file mode 100644 (file)
index 8257397..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-MPIC interrupt controller
-=========================
-
-Device types supported:
-  KVM_DEV_TYPE_FSL_MPIC_20     Freescale MPIC v2.0
-  KVM_DEV_TYPE_FSL_MPIC_42     Freescale MPIC v4.2
-
-Only one MPIC instance, of any type, may be instantiated.  The created
-MPIC will act as the system interrupt controller, connecting to each
-vcpu's interrupt inputs.
-
-Groups:
-  KVM_DEV_MPIC_GRP_MISC
-  Attributes:
-    KVM_DEV_MPIC_BASE_ADDR (rw, 64-bit)
-      Base address of the 256 KiB MPIC register space.  Must be
-      naturally aligned.  A value of zero disables the mapping.
-      Reset value is zero.
-
-  KVM_DEV_MPIC_GRP_REGISTER (rw, 32-bit)
-    Access an MPIC register, as if the access were made from the guest.
-    "attr" is the byte offset into the MPIC register space.  Accesses
-    must be 4-byte aligned.
-
-    MSIs may be signaled by using this attribute group to write
-    to the relevant MSIIR.
-
-  KVM_DEV_MPIC_GRP_IRQ_ACTIVE (rw, 32-bit)
-    IRQ input line for each standard openpic source.  0 is inactive and 1
-    is active, regardless of interrupt sense.
-
-    For edge-triggered interrupts:  Writing 1 is considered an activating
-    edge, and writing 0 is ignored.  Reading returns 1 if a previously
-    signaled edge has not been acknowledged, and 0 otherwise.
-
-    "attr" is the IRQ number.  IRQ numbers for standard sources are the
-    byte offset of the relevant IVPR from EIVPR0, divided by 32.
-
-IRQ Routing:
-
-  The MPIC emulation supports IRQ routing. Only a single MPIC device can
-  be instantiated. Once that device has been created, it's available as
-  irqchip id 0.
-
-  This irqchip 0 has 256 interrupt pins, which expose the interrupts in
-  the main array of interrupt sources (a.k.a. "SRC" interrupts).
-
-  The numbering is the same as the MPIC device tree binding -- based on
-  the register offset from the beginning of the sources array, without
-  regard to any subdivisions in chip documentation such as "internal"
-  or "external" interrupts.
-
-  Access to non-SRC interrupts is not implemented through IRQ routing mechanisms.
diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt
deleted file mode 100644 (file)
index a4e20a0..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-FLIC (floating interrupt controller)
-====================================
-
-FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some
-machine check interruptions. All interrupts are stored in a per-vm list of
-pending interrupts. FLIC performs operations on this list.
-
-Only one FLIC instance may be instantiated.
-
-FLIC provides support to
-- add interrupts (KVM_DEV_FLIC_ENQUEUE)
-- inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS)
-- purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS)
-- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
-- enable/disable for the guest transparent async page faults
-- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
-- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
-- inject adapter interrupts on a specified adapter (KVM_DEV_FLIC_AIRQ_INJECT)
-- get/set all AIS mode states (KVM_DEV_FLIC_AISM_ALL)
-
-Groups:
-  KVM_DEV_FLIC_ENQUEUE
-    Passes a buffer and length into the kernel which are then injected into
-    the list of pending interrupts.
-    attr->addr contains the pointer to the buffer and attr->attr contains
-    the length of the buffer.
-    The format of the data structure kvm_s390_irq as it is copied from userspace
-    is defined in usr/include/linux/kvm.h.
-
-  KVM_DEV_FLIC_GET_ALL_IRQS
-    Copies all floating interrupts into a buffer provided by userspace.
-    When the buffer is too small it returns -ENOMEM, which is the indication
-    for userspace to try again with a bigger buffer.
-    -ENOBUFS is returned when the allocation of a kernelspace buffer has
-    failed.
-    -EFAULT is returned when copying data to userspace failed.
-    All interrupts remain pending, i.e. are not deleted from the list of
-    currently pending interrupts.
-    attr->addr contains the userspace address of the buffer into which all
-    interrupt data will be copied.
-    attr->attr contains the size of the buffer in bytes.
-
-  KVM_DEV_FLIC_CLEAR_IRQS
-    Simply deletes all elements from the list of currently pending floating
-    interrupts.  No interrupts are injected into the guest.
-
-  KVM_DEV_FLIC_CLEAR_IO_IRQ
-    Deletes one (if any) I/O interrupt for a subchannel identified by the
-    subsystem identification word passed via the buffer specified by
-    attr->addr (address) and attr->attr (length).
-
-  KVM_DEV_FLIC_APF_ENABLE
-    Enables async page faults for the guest. So in case of a major page fault
-    the host is allowed to handle this async and continues the guest.
-
-  KVM_DEV_FLIC_APF_DISABLE_WAIT
-    Disables async page faults for the guest and waits until already pending
-    async page faults are done. This is necessary to trigger a completion interrupt
-    for every init interrupt before migrating the interrupt list.
-
-  KVM_DEV_FLIC_ADAPTER_REGISTER
-    Register an I/O adapter interrupt source. Takes a kvm_s390_io_adapter
-    describing the adapter to register:
-
-struct kvm_s390_io_adapter {
-       __u32 id;
-       __u8 isc;
-       __u8 maskable;
-       __u8 swap;
-       __u8 flags;
-};
-
-   id contains the unique id for the adapter, isc the I/O interruption subclass
-   to use, maskable whether this adapter may be masked (interrupts turned off),
-   swap whether the indicators need to be byte swapped, and flags contains
-   further characteristics of the adapter.
-   Currently defined values for 'flags' are:
-   - KVM_S390_ADAPTER_SUPPRESSIBLE: adapter is subject to AIS
-     (adapter-interrupt-suppression) facility. This flag only has an effect if
-     the AIS capability is enabled.
-   Unknown flag values are ignored.
-
-
-  KVM_DEV_FLIC_ADAPTER_MODIFY
-    Modifies attributes of an existing I/O adapter interrupt source. Takes
-    a kvm_s390_io_adapter_req specifying the adapter and the operation:
-
-struct kvm_s390_io_adapter_req {
-       __u32 id;
-       __u8 type;
-       __u8 mask;
-       __u16 pad0;
-       __u64 addr;
-};
-
-    id specifies the adapter and type the operation. The supported operations
-    are:
-
-    KVM_S390_IO_ADAPTER_MASK
-      mask or unmask the adapter, as specified in mask
-
-    KVM_S390_IO_ADAPTER_MAP
-      perform a gmap translation for the guest address provided in addr,
-      pin a userspace page for the translated address and add it to the
-      list of mappings
-      Note: A new mapping will be created unconditionally; therefore,
-            the calling code should avoid making duplicate mappings.
-
-    KVM_S390_IO_ADAPTER_UNMAP
-      release a userspace page for the translated address specified in addr
-      from the list of mappings
-
-  KVM_DEV_FLIC_AISM
-    modify the adapter-interruption-suppression mode for a given isc if the
-    AIS capability is enabled. Takes a kvm_s390_ais_req describing:
-
-struct kvm_s390_ais_req {
-       __u8 isc;
-       __u16 mode;
-};
-
-    isc contains the target I/O interruption subclass, mode the target
-    adapter-interruption-suppression mode. The following modes are
-    currently supported:
-    - KVM_S390_AIS_MODE_ALL: ALL-Interruptions Mode, i.e. airq injection
-      is always allowed;
-    - KVM_S390_AIS_MODE_SINGLE: SINGLE-Interruption Mode, i.e. airq
-      injection is only allowed once and the following adapter interrupts
-      will be suppressed until the mode is set again to ALL-Interruptions
-      or SINGLE-Interruption mode.
-
-  KVM_DEV_FLIC_AIRQ_INJECT
-    Inject adapter interrupts on a specified adapter.
-    attr->attr contains the unique id for the adapter, which allows for
-    adapter-specific checks and actions.
-    For adapters subject to AIS, handle the airq injection suppression for
-    an isc according to the adapter-interruption-suppression mode on condition
-    that the AIS capability is enabled.
-
-  KVM_DEV_FLIC_AISM_ALL
-    Gets or sets the adapter-interruption-suppression mode for all ISCs. Takes
-    a kvm_s390_ais_all describing:
-
-struct kvm_s390_ais_all {
-       __u8 simm; /* Single-Interruption-Mode mask */
-       __u8 nimm; /* No-Interruption-Mode mask *
-};
-
-    simm contains Single-Interruption-Mode mask for all ISCs, nimm contains
-    No-Interruption-Mode mask for all ISCs. Each bit in simm and nimm corresponds
-    to an ISC (MSB0 bit 0 to ISC 0 and so on). The combination of simm bit and
-    nimm bit presents AIS mode for a ISC.
-
-    KVM_DEV_FLIC_AISM_ALL is indicated by KVM_CAP_S390_AIS_MIGRATION.
-
-Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
-FLIC with an unknown group or attribute gives the error code EINVAL (instead of
-ENXIO, as specified in the API documentation). It is not possible to conclude
-that a FLIC operation is unavailable based on the error code resulting from a
-usage attempt.
-
-Note: The KVM_DEV_FLIC_CLEAR_IO_IRQ ioctl will return EINVAL in case a zero
-schid is specified.
diff --git a/Documentation/virtual/kvm/devices/vcpu.txt b/Documentation/virtual/kvm/devices/vcpu.txt
deleted file mode 100644 (file)
index 2b5dab1..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-Generic vcpu interface
-====================================
-
-The virtual cpu "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
-KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same struct
-kvm_device_attr as other devices, but targets VCPU-wide settings and controls.
-
-The groups and attributes per virtual cpu, if any, are architecture specific.
-
-1. GROUP: KVM_ARM_VCPU_PMU_V3_CTRL
-Architectures: ARM64
-
-1.1. ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_IRQ
-Parameters: in kvm_device_attr.addr the address for PMU overflow interrupt is a
-            pointer to an int
-Returns: -EBUSY: The PMU overflow interrupt is already set
-         -ENXIO: The overflow interrupt not set when attempting to get it
-         -ENODEV: PMUv3 not supported
-         -EINVAL: Invalid PMU overflow interrupt number supplied or
-                  trying to set the IRQ number without using an in-kernel
-                  irqchip.
-
-A value describing the PMUv3 (Performance Monitor Unit v3) overflow interrupt
-number for this vcpu. This interrupt could be a PPI or SPI, but the interrupt
-type must be same for each vcpu. As a PPI, the interrupt number is the same for
-all vcpus, while as an SPI it must be a separate number per vcpu.
-
-1.2 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_INIT
-Parameters: no additional parameter in kvm_device_attr.addr
-Returns: -ENODEV: PMUv3 not supported or GIC not initialized
-         -ENXIO: PMUv3 not properly configured or in-kernel irqchip not
-                 configured as required prior to calling this attribute
-         -EBUSY: PMUv3 already initialized
-
-Request the initialization of the PMUv3.  If using the PMUv3 with an in-kernel
-virtual GIC implementation, this must be done after initializing the in-kernel
-irqchip.
-
-
-2. GROUP: KVM_ARM_VCPU_TIMER_CTRL
-Architectures: ARM,ARM64
-
-2.1. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_VTIMER
-2.2. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_PTIMER
-Parameters: in kvm_device_attr.addr the address for the timer interrupt is a
-            pointer to an int
-Returns: -EINVAL: Invalid timer interrupt number
-         -EBUSY:  One or more VCPUs has already run
-
-A value describing the architected timer interrupt number when connected to an
-in-kernel virtual GIC.  These must be a PPI (16 <= intid < 32).  Setting the
-attribute overrides the default values (see below).
-
-KVM_ARM_VCPU_TIMER_IRQ_VTIMER: The EL1 virtual timer intid (default: 27)
-KVM_ARM_VCPU_TIMER_IRQ_PTIMER: The EL1 physical timer intid (default: 30)
-
-Setting the same PPI for different timers will prevent the VCPUs from running.
-Setting the interrupt number on a VCPU configures all VCPUs created at that
-time to use the number provided for a given timer, overwriting any previously
-configured values on other VCPUs.  Userspace should configure the interrupt
-numbers on at least one VCPU after creating all VCPUs and before running any
-VCPUs.
diff --git a/Documentation/virtual/kvm/devices/vfio.txt b/Documentation/virtual/kvm/devices/vfio.txt
deleted file mode 100644 (file)
index 528c77c..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-VFIO virtual device
-===================
-
-Device types supported:
-  KVM_DEV_TYPE_VFIO
-
-Only one VFIO instance may be created per VM.  The created device
-tracks VFIO groups in use by the VM and features of those groups
-important to the correctness and acceleration of the VM.  As groups
-are enabled and disabled for use by the VM, KVM should be updated
-about their presence.  When registered with KVM, a reference to the
-VFIO-group is held by KVM.
-
-Groups:
-  KVM_DEV_VFIO_GROUP
-
-KVM_DEV_VFIO_GROUP attributes:
-  KVM_DEV_VFIO_GROUP_ADD: Add a VFIO group to VFIO-KVM device tracking
-       kvm_device_attr.addr points to an int32_t file descriptor
-       for the VFIO group.
-  KVM_DEV_VFIO_GROUP_DEL: Remove a VFIO group from VFIO-KVM device tracking
-       kvm_device_attr.addr points to an int32_t file descriptor
-       for the VFIO group.
-  KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE: attaches a guest visible TCE table
-       allocated by sPAPR KVM.
-       kvm_device_attr.addr points to a struct:
-
-       struct kvm_vfio_spapr_tce {
-               __s32   groupfd;
-               __s32   tablefd;
-       };
-
-       where
-       @groupfd is a file descriptor for a VFIO group;
-       @tablefd is a file descriptor for a TCE table allocated via
-               KVM_CREATE_SPAPR_TCE.
diff --git a/Documentation/virtual/kvm/devices/vm.txt b/Documentation/virtual/kvm/devices/vm.txt
deleted file mode 100644 (file)
index 4ffb82b..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-Generic vm interface
-====================================
-
-The virtual machine "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
-KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same
-struct kvm_device_attr as other devices, but targets VM-wide settings
-and controls.
-
-The groups and attributes per virtual machine, if any, are architecture
-specific.
-
-1. GROUP: KVM_S390_VM_MEM_CTRL
-Architectures: s390
-
-1.1. ATTRIBUTE: KVM_S390_VM_MEM_ENABLE_CMMA
-Parameters: none
-Returns: -EBUSY if a vcpu is already defined, otherwise 0
-
-Enables Collaborative Memory Management Assist (CMMA) for the virtual machine.
-
-1.2. ATTRIBUTE: KVM_S390_VM_MEM_CLR_CMMA
-Parameters: none
-Returns: -EINVAL if CMMA was not enabled
-         0 otherwise
-
-Clear the CMMA status for all guest pages, so any pages the guest marked
-as unused are again used any may not be reclaimed by the host.
-
-1.3. ATTRIBUTE KVM_S390_VM_MEM_LIMIT_SIZE
-Parameters: in attr->addr the address for the new limit of guest memory
-Returns: -EFAULT if the given address is not accessible
-         -EINVAL if the virtual machine is of type UCONTROL
-         -E2BIG if the given guest memory is to big for that machine
-         -EBUSY if a vcpu is already defined
-         -ENOMEM if not enough memory is available for a new shadow guest mapping
-          0 otherwise
-
-Allows userspace to query the actual limit and set a new limit for
-the maximum guest memory size. The limit will be rounded up to
-2048 MB, 4096 GB, 8192 TB respectively, as this limit is governed by
-the number of page table levels. In the case that there is no limit we will set
-the limit to KVM_S390_NO_MEM_LIMIT (U64_MAX).
-
-2. GROUP: KVM_S390_VM_CPU_MODEL
-Architectures: s390
-
-2.1. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE (r/o)
-
-Allows user space to retrieve machine and kvm specific cpu related information:
-
-struct kvm_s390_vm_cpu_machine {
-       __u64 cpuid;           # CPUID of host
-       __u32 ibc;             # IBC level range offered by host
-       __u8  pad[4];
-       __u64 fac_mask[256];   # set of cpu facilities enabled by KVM
-       __u64 fac_list[256];   # set of cpu facilities offered by host
-}
-
-Parameters: address of buffer to store the machine related cpu data
-            of type struct kvm_s390_vm_cpu_machine*
-Returns:    -EFAULT if the given address is not accessible from kernel space
-           -ENOMEM if not enough memory is available to process the ioctl
-           0 in case of success
-
-2.2. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR (r/w)
-
-Allows user space to retrieve or request to change cpu related information for a vcpu:
-
-struct kvm_s390_vm_cpu_processor {
-       __u64 cpuid;           # CPUID currently (to be) used by this vcpu
-       __u16 ibc;             # IBC level currently (to be) used by this vcpu
-       __u8  pad[6];
-       __u64 fac_list[256];   # set of cpu facilities currently (to be) used
-                              # by this vcpu
-}
-
-KVM does not enforce or limit the cpu model data in any form. Take the information
-retrieved by means of KVM_S390_VM_CPU_MACHINE as hint for reasonable configuration
-setups. Instruction interceptions triggered by additionally set facility bits that
-are not handled by KVM need to by imlemented in the VM driver code.
-
-Parameters: address of buffer to store/set the processor related cpu
-           data of type struct kvm_s390_vm_cpu_processor*.
-Returns:    -EBUSY in case 1 or more vcpus are already activated (only in write case)
-           -EFAULT if the given address is not accessible from kernel space
-           -ENOMEM if not enough memory is available to process the ioctl
-           0 in case of success
-
-2.3. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE_FEAT (r/o)
-
-Allows user space to retrieve available cpu features. A feature is available if
-provided by the hardware and supported by kvm. In theory, cpu features could
-even be completely emulated by kvm.
-
-struct kvm_s390_vm_cpu_feat {
-        __u64 feat[16]; # Bitmap (1 = feature available), MSB 0 bit numbering
-};
-
-Parameters: address of a buffer to load the feature list from.
-Returns:    -EFAULT if the given address is not accessible from kernel space.
-           0 in case of success.
-
-2.4. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR_FEAT (r/w)
-
-Allows user space to retrieve or change enabled cpu features for all VCPUs of a
-VM. Features that are not available cannot be enabled.
-
-See 2.3. for a description of the parameter struct.
-
-Parameters: address of a buffer to store/load the feature list from.
-Returns:    -EFAULT if the given address is not accessible from kernel space.
-           -EINVAL if a cpu feature that is not available is to be enabled.
-           -EBUSY if at least one VCPU has already been defined.
-           0 in case of success.
-
-2.5. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE_SUBFUNC (r/o)
-
-Allows user space to retrieve available cpu subfunctions without any filtering
-done by a set IBC. These subfunctions are indicated to the guest VCPU via
-query or "test bit" subfunctions and used e.g. by cpacf functions, plo and ptff.
-
-A subfunction block is only valid if KVM_S390_VM_CPU_MACHINE contains the
-STFL(E) bit introducing the affected instruction. If the affected instruction
-indicates subfunctions via a "query subfunction", the response block is
-contained in the returned struct. If the affected instruction
-indicates subfunctions via a "test bit" mechanism, the subfunction codes are
-contained in the returned struct in MSB 0 bit numbering.
-
-struct kvm_s390_vm_cpu_subfunc {
-       u8 plo[32];           # always valid (ESA/390 feature)
-       u8 ptff[16];          # valid with TOD-clock steering
-       u8 kmac[16];          # valid with Message-Security-Assist
-       u8 kmc[16];           # valid with Message-Security-Assist
-       u8 km[16];            # valid with Message-Security-Assist
-       u8 kimd[16];          # valid with Message-Security-Assist
-       u8 klmd[16];          # valid with Message-Security-Assist
-       u8 pckmo[16];         # valid with Message-Security-Assist-Extension 3
-       u8 kmctr[16];         # valid with Message-Security-Assist-Extension 4
-       u8 kmf[16];           # valid with Message-Security-Assist-Extension 4
-       u8 kmo[16];           # valid with Message-Security-Assist-Extension 4
-       u8 pcc[16];           # valid with Message-Security-Assist-Extension 4
-       u8 ppno[16];          # valid with Message-Security-Assist-Extension 5
-       u8 kma[16];           # valid with Message-Security-Assist-Extension 8
-       u8 kdsa[16];          # valid with Message-Security-Assist-Extension 9
-       u8 reserved[1792];    # reserved for future instructions
-};
-
-Parameters: address of a buffer to load the subfunction blocks from.
-Returns:    -EFAULT if the given address is not accessible from kernel space.
-           0 in case of success.
-
-2.6. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR_SUBFUNC (r/w)
-
-Allows user space to retrieve or change cpu subfunctions to be indicated for
-all VCPUs of a VM. This attribute will only be available if kernel and
-hardware support are in place.
-
-The kernel uses the configured subfunction blocks for indication to
-the guest. A subfunction block will only be used if the associated STFL(E) bit
-has not been disabled by user space (so the instruction to be queried is
-actually available for the guest).
-
-As long as no data has been written, a read will fail. The IBC will be used
-to determine available subfunctions in this case, this will guarantee backward
-compatibility.
-
-See 2.5. for a description of the parameter struct.
-
-Parameters: address of a buffer to store/load the subfunction blocks from.
-Returns:    -EFAULT if the given address is not accessible from kernel space.
-           -EINVAL when reading, if there was no write yet.
-           -EBUSY if at least one VCPU has already been defined.
-           0 in case of success.
-
-3. GROUP: KVM_S390_VM_TOD
-Architectures: s390
-
-3.1. ATTRIBUTE: KVM_S390_VM_TOD_HIGH
-
-Allows user space to set/get the TOD clock extension (u8) (superseded by
-KVM_S390_VM_TOD_EXT).
-
-Parameters: address of a buffer in user space to store the data (u8) to
-Returns:    -EFAULT if the given address is not accessible from kernel space
-           -EINVAL if setting the TOD clock extension to != 0 is not supported
-
-3.2. ATTRIBUTE: KVM_S390_VM_TOD_LOW
-
-Allows user space to set/get bits 0-63 of the TOD clock register as defined in
-the POP (u64).
-
-Parameters: address of a buffer in user space to store the data (u64) to
-Returns:    -EFAULT if the given address is not accessible from kernel space
-
-3.3. ATTRIBUTE: KVM_S390_VM_TOD_EXT
-Allows user space to set/get bits 0-63 of the TOD clock register as defined in
-the POP (u64). If the guest CPU model supports the TOD clock extension (u8), it
-also allows user space to get/set it. If the guest CPU model does not support
-it, it is stored as 0 and not allowed to be set to a value != 0.
-
-Parameters: address of a buffer in user space to store the data
-            (kvm_s390_vm_tod_clock) to
-Returns:    -EFAULT if the given address is not accessible from kernel space
-           -EINVAL if setting the TOD clock extension to != 0 is not supported
-
-4. GROUP: KVM_S390_VM_CRYPTO
-Architectures: s390
-
-4.1. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_AES_KW (w/o)
-
-Allows user space to enable aes key wrapping, including generating a new
-wrapping key.
-
-Parameters: none
-Returns:    0
-
-4.2. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_DEA_KW (w/o)
-
-Allows user space to enable dea key wrapping, including generating a new
-wrapping key.
-
-Parameters: none
-Returns:    0
-
-4.3. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_AES_KW (w/o)
-
-Allows user space to disable aes key wrapping, clearing the wrapping key.
-
-Parameters: none
-Returns:    0
-
-4.4. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_DEA_KW (w/o)
-
-Allows user space to disable dea key wrapping, clearing the wrapping key.
-
-Parameters: none
-Returns:    0
-
-5. GROUP: KVM_S390_VM_MIGRATION
-Architectures: s390
-
-5.1. ATTRIBUTE: KVM_S390_VM_MIGRATION_STOP (w/o)
-
-Allows userspace to stop migration mode, needed for PGSTE migration.
-Setting this attribute when migration mode is not active will have no
-effects.
-
-Parameters: none
-Returns:    0
-
-5.2. ATTRIBUTE: KVM_S390_VM_MIGRATION_START (w/o)
-
-Allows userspace to start migration mode, needed for PGSTE migration.
-Setting this attribute when migration mode is already active will have
-no effects.
-
-Parameters: none
-Returns:    -ENOMEM if there is not enough free memory to start migration mode
-           -EINVAL if the state of the VM is invalid (e.g. no memory defined)
-           0 in case of success.
-
-5.3. ATTRIBUTE: KVM_S390_VM_MIGRATION_STATUS (r/o)
-
-Allows userspace to query the status of migration mode.
-
-Parameters: address of a buffer in user space to store the data (u64) to;
-           the data itself is either 0 if migration mode is disabled or 1
-           if it is enabled
-Returns:    -EFAULT if the given address is not accessible from kernel space
-           0 in case of success.
diff --git a/Documentation/virtual/kvm/devices/xics.txt b/Documentation/virtual/kvm/devices/xics.txt
deleted file mode 100644 (file)
index 4286493..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-XICS interrupt controller
-
-Device type supported: KVM_DEV_TYPE_XICS
-
-Groups:
-  KVM_DEV_XICS_SOURCES
-  Attributes: One per interrupt source, indexed by the source number.
-
-This device emulates the XICS (eXternal Interrupt Controller
-Specification) defined in PAPR.  The XICS has a set of interrupt
-sources, each identified by a 20-bit source number, and a set of
-Interrupt Control Presentation (ICP) entities, also called "servers",
-each associated with a virtual CPU.
-
-The ICP entities are created by enabling the KVM_CAP_IRQ_ARCH
-capability for each vcpu, specifying KVM_CAP_IRQ_XICS in args[0] and
-the interrupt server number (i.e. the vcpu number from the XICS's
-point of view) in args[1] of the kvm_enable_cap struct.  Each ICP has
-64 bits of state which can be read and written using the
-KVM_GET_ONE_REG and KVM_SET_ONE_REG ioctls on the vcpu.  The 64 bit
-state word has the following bitfields, starting at the
-least-significant end of the word:
-
-* Unused, 16 bits
-
-* Pending interrupt priority, 8 bits
-  Zero is the highest priority, 255 means no interrupt is pending.
-
-* Pending IPI (inter-processor interrupt) priority, 8 bits
-  Zero is the highest priority, 255 means no IPI is pending.
-
-* Pending interrupt source number, 24 bits
-  Zero means no interrupt pending, 2 means an IPI is pending
-
-* Current processor priority, 8 bits
-  Zero is the highest priority, meaning no interrupts can be
-  delivered, and 255 is the lowest priority.
-
-Each source has 64 bits of state that can be read and written using
-the KVM_GET_DEVICE_ATTR and KVM_SET_DEVICE_ATTR ioctls, specifying the
-KVM_DEV_XICS_SOURCES attribute group, with the attribute number being
-the interrupt source number.  The 64 bit state word has the following
-bitfields, starting from the least-significant end of the word:
-
-* Destination (server number), 32 bits
-  This specifies where the interrupt should be sent, and is the
-  interrupt server number specified for the destination vcpu.
-
-* Priority, 8 bits
-  This is the priority specified for this interrupt source, where 0 is
-  the highest priority and 255 is the lowest.  An interrupt with a
-  priority of 255 will never be delivered.
-
-* Level sensitive flag, 1 bit
-  This bit is 1 for a level-sensitive interrupt source, or 0 for
-  edge-sensitive (or MSI).
-
-* Masked flag, 1 bit
-  This bit is set to 1 if the interrupt is masked (cannot be delivered
-  regardless of its priority), for example by the ibm,int-off RTAS
-  call, or 0 if it is not masked.
-
-* Pending flag, 1 bit
-  This bit is 1 if the source has a pending interrupt, otherwise 0.
-
-Only one XICS instance may be created per VM.
diff --git a/Documentation/virtual/kvm/devices/xive.txt b/Documentation/virtual/kvm/devices/xive.txt
deleted file mode 100644 (file)
index 9a24a45..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-POWER9 eXternal Interrupt Virtualization Engine (XIVE Gen1)
-==========================================================
-
-Device types supported:
-  KVM_DEV_TYPE_XIVE     POWER9 XIVE Interrupt Controller generation 1
-
-This device acts as a VM interrupt controller. It provides the KVM
-interface to configure the interrupt sources of a VM in the underlying
-POWER9 XIVE interrupt controller.
-
-Only one XIVE instance may be instantiated. A guest XIVE device
-requires a POWER9 host and the guest OS should have support for the
-XIVE native exploitation interrupt mode. If not, it should run using
-the legacy interrupt mode, referred as XICS (POWER7/8).
-
-* Device Mappings
-
-  The KVM device exposes different MMIO ranges of the XIVE HW which
-  are required for interrupt management. These are exposed to the
-  guest in VMAs populated with a custom VM fault handler.
-
-  1. Thread Interrupt Management Area (TIMA)
-
-  Each thread has an associated Thread Interrupt Management context
-  composed of a set of registers. These registers let the thread
-  handle priority management and interrupt acknowledgment. The most
-  important are :
-
-      - Interrupt Pending Buffer     (IPB)
-      - Current Processor Priority   (CPPR)
-      - Notification Source Register (NSR)
-
-  They are exposed to software in four different pages each proposing
-  a view with a different privilege. The first page is for the
-  physical thread context and the second for the hypervisor. Only the
-  third (operating system) and the fourth (user level) are exposed the
-  guest.
-
-  2. Event State Buffer (ESB)
-
-  Each source is associated with an Event State Buffer (ESB) with
-  either a pair of even/odd pair of pages which provides commands to
-  manage the source: to trigger, to EOI, to turn off the source for
-  instance.
-
-  3. Device pass-through
-
-  When a device is passed-through into the guest, the source
-  interrupts are from a different HW controller (PHB4) and the ESB
-  pages exposed to the guest should accommadate this change.
-
-  The passthru_irq helpers, kvmppc_xive_set_mapped() and
-  kvmppc_xive_clr_mapped() are called when the device HW irqs are
-  mapped into or unmapped from the guest IRQ number space. The KVM
-  device extends these helpers to clear the ESB pages of the guest IRQ
-  number being mapped and then lets the VM fault handler repopulate.
-  The handler will insert the ESB page corresponding to the HW
-  interrupt of the device being passed-through or the initial IPI ESB
-  page if the device has being removed.
-
-  The ESB remapping is fully transparent to the guest and the OS
-  device driver. All handling is done within VFIO and the above
-  helpers in KVM-PPC.
-
-* Groups:
-
-  1. KVM_DEV_XIVE_GRP_CTRL
-  Provides global controls on the device
-  Attributes:
-    1.1 KVM_DEV_XIVE_RESET (write only)
-    Resets the interrupt controller configuration for sources and event
-    queues. To be used by kexec and kdump.
-    Errors: none
-
-    1.2 KVM_DEV_XIVE_EQ_SYNC (write only)
-    Sync all the sources and queues and mark the EQ pages dirty. This
-    to make sure that a consistent memory state is captured when
-    migrating the VM.
-    Errors: none
-
-  2. KVM_DEV_XIVE_GRP_SOURCE (write only)
-  Initializes a new source in the XIVE device and mask it.
-  Attributes:
-    Interrupt source number  (64-bit)
-  The kvm_device_attr.addr points to a __u64 value:
-  bits:     | 63   ....  2 |   1   |   0
-  values:   |    unused    | level | type
-  - type:  0:MSI 1:LSI
-  - level: assertion level in case of an LSI.
-  Errors:
-    -E2BIG:  Interrupt source number is out of range
-    -ENOMEM: Could not create a new source block
-    -EFAULT: Invalid user pointer for attr->addr.
-    -ENXIO:  Could not allocate underlying HW interrupt
-
-  3. KVM_DEV_XIVE_GRP_SOURCE_CONFIG (write only)
-  Configures source targeting
-  Attributes:
-    Interrupt source number  (64-bit)
-  The kvm_device_attr.addr points to a __u64 value:
-  bits:     | 63   ....  33 |  32  | 31 .. 3 |  2 .. 0
-  values:   |    eisn       | mask |  server | priority
-  - priority: 0-7 interrupt priority level
-  - server: CPU number chosen to handle the interrupt
-  - mask: mask flag (unused)
-  - eisn: Effective Interrupt Source Number
-  Errors:
-    -ENOENT: Unknown source number
-    -EINVAL: Not initialized source number
-    -EINVAL: Invalid priority
-    -EINVAL: Invalid CPU number.
-    -EFAULT: Invalid user pointer for attr->addr.
-    -ENXIO:  CPU event queues not configured or configuration of the
-             underlying HW interrupt failed
-    -EBUSY:  No CPU available to serve interrupt
-
-  4. KVM_DEV_XIVE_GRP_EQ_CONFIG (read-write)
-  Configures an event queue of a CPU
-  Attributes:
-    EQ descriptor identifier (64-bit)
-  The EQ descriptor identifier is a tuple (server, priority) :
-  bits:     | 63   ....  32 | 31 .. 3 |  2 .. 0
-  values:   |    unused     |  server | priority
-  The kvm_device_attr.addr points to :
-    struct kvm_ppc_xive_eq {
-       __u32 flags;
-       __u32 qshift;
-       __u64 qaddr;
-       __u32 qtoggle;
-       __u32 qindex;
-       __u8  pad[40];
-    };
-  - flags: queue flags
-    KVM_XIVE_EQ_ALWAYS_NOTIFY (required)
-       forces notification without using the coalescing mechanism
-       provided by the XIVE END ESBs.
-  - qshift: queue size (power of 2)
-  - qaddr: real address of queue
-  - qtoggle: current queue toggle bit
-  - qindex: current queue index
-  - pad: reserved for future use
-  Errors:
-    -ENOENT: Invalid CPU number
-    -EINVAL: Invalid priority
-    -EINVAL: Invalid flags
-    -EINVAL: Invalid queue size
-    -EINVAL: Invalid queue address
-    -EFAULT: Invalid user pointer for attr->addr.
-    -EIO:    Configuration of the underlying HW failed
-
-  5. KVM_DEV_XIVE_GRP_SOURCE_SYNC (write only)
-  Synchronize the source to flush event notifications
-  Attributes:
-    Interrupt source number  (64-bit)
-  Errors:
-    -ENOENT: Unknown source number
-    -EINVAL: Not initialized source number
-
-* VCPU state
-
-  The XIVE IC maintains VP interrupt state in an internal structure
-  called the NVT. When a VP is not dispatched on a HW processor
-  thread, this structure can be updated by HW if the VP is the target
-  of an event notification.
-
-  It is important for migration to capture the cached IPB from the NVT
-  as it synthesizes the priorities of the pending interrupts. We
-  capture a bit more to report debug information.
-
-  KVM_REG_PPC_VP_STATE (2 * 64bits)
-  bits:     |  63  ....  32  |  31  ....  0  |
-  values:   |   TIMA word0   |   TIMA word1  |
-  bits:     | 127       ..........       64  |
-  values:   |            unused              |
-
-* Migration:
-
-  Saving the state of a VM using the XIVE native exploitation mode
-  should follow a specific sequence. When the VM is stopped :
-
-  1. Mask all sources (PQ=01) to stop the flow of events.
-
-  2. Sync the XIVE device with the KVM control KVM_DEV_XIVE_EQ_SYNC to
-  flush any in-flight event notification and to stabilize the EQs. At
-  this stage, the EQ pages are marked dirty to make sure they are
-  transferred in the migration sequence.
-
-  3. Capture the state of the source targeting, the EQs configuration
-  and the state of thread interrupt context registers.
-
-  Restore is similar :
-
-  1. Restore the EQ configuration. As targeting depends on it.
-  2. Restore targeting
-  3. Restore the thread interrupt contexts
-  4. Restore the source states
-  5. Let the vCPU run
diff --git a/Documentation/virtual/kvm/halt-polling.txt b/Documentation/virtual/kvm/halt-polling.txt
deleted file mode 100644 (file)
index 4f791b1..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-The KVM halt polling system
-===========================
-
-The KVM halt polling system provides a feature within KVM whereby the latency
-of a guest can, under some circumstances, be reduced by polling in the host
-for some time period after the guest has elected to no longer run by cedeing.
-That is, when a guest vcpu has ceded, or in the case of powerpc when all of the
-vcpus of a single vcore have ceded, the host kernel polls for wakeup conditions
-before giving up the cpu to the scheduler in order to let something else run.
-
-Polling provides a latency advantage in cases where the guest can be run again
-very quickly by at least saving us a trip through the scheduler, normally on
-the order of a few micro-seconds, although performance benefits are workload
-dependant. In the event that no wakeup source arrives during the polling
-interval or some other task on the runqueue is runnable the scheduler is
-invoked. Thus halt polling is especially useful on workloads with very short
-wakeup periods where the time spent halt polling is minimised and the time
-savings of not invoking the scheduler are distinguishable.
-
-The generic halt polling code is implemented in:
-
-       virt/kvm/kvm_main.c: kvm_vcpu_block()
-
-The powerpc kvm-hv specific case is implemented in:
-
-       arch/powerpc/kvm/book3s_hv.c: kvmppc_vcore_blocked()
-
-Halt Polling Interval
-=====================
-
-The maximum time for which to poll before invoking the scheduler, referred to
-as the halt polling interval, is increased and decreased based on the perceived
-effectiveness of the polling in an attempt to limit pointless polling.
-This value is stored in either the vcpu struct:
-
-       kvm_vcpu->halt_poll_ns
-
-or in the case of powerpc kvm-hv, in the vcore struct:
-
-       kvmppc_vcore->halt_poll_ns
-
-Thus this is a per vcpu (or vcore) value.
-
-During polling if a wakeup source is received within the halt polling interval,
-the interval is left unchanged. In the event that a wakeup source isn't
-received during the polling interval (and thus schedule is invoked) there are
-two options, either the polling interval and total block time[0] were less than
-the global max polling interval (see module params below), or the total block
-time was greater than the global max polling interval.
-
-In the event that both the polling interval and total block time were less than
-the global max polling interval then the polling interval can be increased in
-the hope that next time during the longer polling interval the wake up source
-will be received while the host is polling and the latency benefits will be
-received. The polling interval is grown in the function grow_halt_poll_ns() and
-is multiplied by the module parameters halt_poll_ns_grow and
-halt_poll_ns_grow_start.
-
-In the event that the total block time was greater than the global max polling
-interval then the host will never poll for long enough (limited by the global
-max) to wakeup during the polling interval so it may as well be shrunk in order
-to avoid pointless polling. The polling interval is shrunk in the function
-shrink_halt_poll_ns() and is divided by the module parameter
-halt_poll_ns_shrink, or set to 0 iff halt_poll_ns_shrink == 0.
-
-It is worth noting that this adjustment process attempts to hone in on some
-steady state polling interval but will only really do a good job for wakeups
-which come at an approximately constant rate, otherwise there will be constant
-adjustment of the polling interval.
-
-[0] total block time: the time between when the halt polling function is
-                     invoked and a wakeup source received (irrespective of
-                     whether the scheduler is invoked within that function).
-
-Module Parameters
-=================
-
-The kvm module has 3 tuneable module parameters to adjust the global max
-polling interval as well as the rate at which the polling interval is grown and
-shrunk. These variables are defined in include/linux/kvm_host.h and as module
-parameters in virt/kvm/kvm_main.c, or arch/powerpc/kvm/book3s_hv.c in the
-powerpc kvm-hv case.
-
-Module Parameter       |   Description             |        Default Value
---------------------------------------------------------------------------------
-halt_poll_ns           | The global max polling    | KVM_HALT_POLL_NS_DEFAULT
-                       | interval which defines    |
-                       | the ceiling value of the  |
-                       | polling interval for      | (per arch value)
-                       | each vcpu.                |
---------------------------------------------------------------------------------
-halt_poll_ns_grow      | The value by which the    | 2
-                       | halt polling interval is  |
-                       | multiplied in the         |
-                       | grow_halt_poll_ns()       |
-                       | function.                 |
---------------------------------------------------------------------------------
-halt_poll_ns_grow_start | The initial value to grow | 10000
-                       | to from zero in the       |
-                       | grow_halt_poll_ns()       |
-                       | function.                 |
---------------------------------------------------------------------------------
-halt_poll_ns_shrink    | The value by which the    | 0
-                       | halt polling interval is  |
-                       | divided in the            |
-                       | shrink_halt_poll_ns()     |
-                       | function.                 |
---------------------------------------------------------------------------------
-
-These module parameters can be set from the debugfs files in:
-
-       /sys/module/kvm/parameters/
-
-Note: that these module parameters are system wide values and are not able to
-      be tuned on a per vm basis.
-
-Further Notes
-=============
-
-- Care should be taken when setting the halt_poll_ns module parameter as a
-large value has the potential to drive the cpu usage to 100% on a machine which
-would be almost entirely idle otherwise. This is because even if a guest has
-wakeups during which very little work is done and which are quite far apart, if
-the period is shorter than the global max polling interval (halt_poll_ns) then
-the host will always poll for the entire block time and thus cpu utilisation
-will go to 100%.
-
-- Halt polling essentially presents a trade off between power usage and latency
-and the module parameters should be used to tune the affinity for this. Idle
-cpu time is essentially converted to host kernel time with the aim of decreasing
-latency when entering the guest.
-
-- Halt polling will only be conducted by the host when no other tasks are
-runnable on that cpu, otherwise the polling will cease immediately and
-schedule will be invoked to allow that other task to run. Thus this doesn't
-allow a guest to denial of service the cpu.
diff --git a/Documentation/virtual/kvm/hypercalls.txt b/Documentation/virtual/kvm/hypercalls.txt
deleted file mode 100644 (file)
index da21065..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-Linux KVM Hypercall:
-===================
-X86:
- KVM Hypercalls have a three-byte sequence of either the vmcall or the vmmcall
- instruction. The hypervisor can replace it with instructions that are
- guaranteed to be supported.
-
- Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
- The hypercall number should be placed in rax and the return value will be
- placed in rax.  No other registers will be clobbered unless explicitly stated
- by the particular hypercall.
-
-S390:
-  R2-R7 are used for parameters 1-6. In addition, R1 is used for hypercall
-  number. The return value is written to R2.
-
-  S390 uses diagnose instruction as hypercall (0x500) along with hypercall
-  number in R1.
-
-  For further information on the S390 diagnose call as supported by KVM,
-  refer to Documentation/virtual/kvm/s390-diag.txt.
-
- PowerPC:
-  It uses R3-R10 and hypercall number in R11. R4-R11 are used as output registers.
-  Return value is placed in R3.
-
-  KVM hypercalls uses 4 byte opcode, that are patched with 'hypercall-instructions'
-  property inside the device tree's /hypervisor node.
-  For more information refer to Documentation/virtual/kvm/ppc-pv.txt
-
-MIPS:
-  KVM hypercalls use the HYPCALL instruction with code 0 and the hypercall
-  number in $2 (v0). Up to four arguments may be placed in $4-$7 (a0-a3) and
-  the return value is placed in $2 (v0).
-
-KVM Hypercalls Documentation
-===========================
-The template for each hypercall is:
-1. Hypercall name.
-2. Architecture(s)
-3. Status (deprecated, obsolete, active)
-4. Purpose
-
-1. KVM_HC_VAPIC_POLL_IRQ
-------------------------
-Architecture: x86
-Status: active
-Purpose: Trigger guest exit so that the host can check for pending
-interrupts on reentry.
-
-2. KVM_HC_MMU_OP
-------------------------
-Architecture: x86
-Status: deprecated.
-Purpose: Support MMU operations such as writing to PTE,
-flushing TLB, release PT.
-
-3. KVM_HC_FEATURES
-------------------------
-Architecture: PPC
-Status: active
-Purpose: Expose hypercall availability to the guest. On x86 platforms, cpuid
-used to enumerate which hypercalls are available. On PPC, either device tree
-based lookup ( which is also what EPAPR dictates) OR KVM specific enumeration
-mechanism (which is this hypercall) can be used.
-
-4. KVM_HC_PPC_MAP_MAGIC_PAGE
-------------------------
-Architecture: PPC
-Status: active
-Purpose: To enable communication between the hypervisor and guest there is a
-shared page that contains parts of supervisor visible register state.
-The guest can map this shared page to access its supervisor register through
-memory using this hypercall.
-
-5. KVM_HC_KICK_CPU
-------------------------
-Architecture: x86
-Status: active
-Purpose: Hypercall used to wakeup a vcpu from HLT state
-Usage example : A vcpu of a paravirtualized guest that is busywaiting in guest
-kernel mode for an event to occur (ex: a spinlock to become available) can
-execute HLT instruction once it has busy-waited for more than a threshold
-time-interval. Execution of HLT instruction would cause the hypervisor to put
-the vcpu to sleep until occurrence of an appropriate event. Another vcpu of the
-same guest can wakeup the sleeping vcpu by issuing KVM_HC_KICK_CPU hypercall,
-specifying APIC ID (a1) of the vcpu to be woken up. An additional argument (a0)
-is used in the hypercall for future use.
-
-
-6. KVM_HC_CLOCK_PAIRING
-------------------------
-Architecture: x86
-Status: active
-Purpose: Hypercall used to synchronize host and guest clocks.
-Usage:
-
-a0: guest physical address where host copies
-"struct kvm_clock_offset" structure.
-
-a1: clock_type, ATM only KVM_CLOCK_PAIRING_WALLCLOCK (0)
-is supported (corresponding to the host's CLOCK_REALTIME clock).
-
-               struct kvm_clock_pairing {
-                       __s64 sec;
-                       __s64 nsec;
-                       __u64 tsc;
-                       __u32 flags;
-                       __u32 pad[9];
-               };
-
-       Where:
-               * sec: seconds from clock_type clock.
-               * nsec: nanoseconds from clock_type clock.
-               * tsc: guest TSC value used to calculate sec/nsec pair
-               * flags: flags, unused (0) at the moment.
-
-The hypercall lets a guest compute a precise timestamp across
-host and guest.  The guest can use the returned TSC value to
-compute the CLOCK_REALTIME for its clock, at the same instant.
-
-Returns KVM_EOPNOTSUPP if the host does not use TSC clocksource,
-or if clock type is different than KVM_CLOCK_PAIRING_WALLCLOCK.
-
-6. KVM_HC_SEND_IPI
-------------------------
-Architecture: x86
-Status: active
-Purpose: Send IPIs to multiple vCPUs.
-
-a0: lower part of the bitmap of destination APIC IDs
-a1: higher part of the bitmap of destination APIC IDs
-a2: the lowest APIC ID in bitmap
-a3: APIC ICR
-
-The hypercall lets a guest send multicast IPIs, with at most 128
-128 destinations per hypercall in 64-bit mode and 64 vCPUs per
-hypercall in 32-bit mode.  The destinations are represented by a
-bitmap contained in the first two arguments (a0 and a1). Bit 0 of
-a0 corresponds to the APIC ID in the third argument (a2), bit 1
-corresponds to the APIC ID a2+1, and so on.
-
-Returns the number of CPUs to which the IPIs were delivered successfully.
-
-7. KVM_HC_SCHED_YIELD
-------------------------
-Architecture: x86
-Status: active
-Purpose: Hypercall used to yield if the IPI target vCPU is preempted
-
-a0: destination APIC ID
-
-Usage example: When sending a call-function IPI-many to vCPUs, yield if
-any of the IPI target vCPUs was preempted.
diff --git a/Documentation/virtual/kvm/index.rst b/Documentation/virtual/kvm/index.rst
deleted file mode 100644 (file)
index 0b206a0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===
-KVM
-===
-
-.. toctree::
-   :maxdepth: 2
-
-   amd-memory-encryption
-   cpuid
diff --git a/Documentation/virtual/kvm/locking.txt b/Documentation/virtual/kvm/locking.txt
deleted file mode 100644 (file)
index 635cd6e..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-KVM Lock Overview
-=================
-
-1. Acquisition Orders
----------------------
-
-The acquisition orders for mutexes are as follows:
-
-- kvm->lock is taken outside vcpu->mutex
-
-- kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock
-
-- kvm->slots_lock is taken outside kvm->irq_lock, though acquiring
-  them together is quite rare.
-
-On x86, vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock.
-
-Everything else is a leaf: no other lock is taken inside the critical
-sections.
-
-2: Exception
-------------
-
-Fast page fault:
-
-Fast page fault is the fast path which fixes the guest page fault out of
-the mmu-lock on x86. Currently, the page fault can be fast in one of the
-following two cases:
-
-1. Access Tracking: The SPTE is not present, but it is marked for access
-tracking i.e. the SPTE_SPECIAL_MASK is set. That means we need to
-restore the saved R/X bits. This is described in more detail later below.
-
-2. Write-Protection: The SPTE is present and the fault is
-caused by write-protect. That means we just need to change the W bit of the 
-spte.
-
-What we use to avoid all the race is the SPTE_HOST_WRITEABLE bit and
-SPTE_MMU_WRITEABLE bit on the spte:
-- SPTE_HOST_WRITEABLE means the gfn is writable on host.
-- SPTE_MMU_WRITEABLE means the gfn is writable on mmu. The bit is set when
-  the gfn is writable on guest mmu and it is not write-protected by shadow
-  page write-protection.
-
-On fast page fault path, we will use cmpxchg to atomically set the spte W
-bit if spte.SPTE_HOST_WRITEABLE = 1 and spte.SPTE_WRITE_PROTECT = 1, or 
-restore the saved R/X bits if VMX_EPT_TRACK_ACCESS mask is set, or both. This
-is safe because whenever changing these bits can be detected by cmpxchg.
-
-But we need carefully check these cases:
-1): The mapping from gfn to pfn
-The mapping from gfn to pfn may be changed since we can only ensure the pfn
-is not changed during cmpxchg. This is a ABA problem, for example, below case
-will happen:
-
-At the beginning:
-gpte = gfn1
-gfn1 is mapped to pfn1 on host
-spte is the shadow page table entry corresponding with gpte and
-spte = pfn1
-
-   VCPU 0                           VCPU0
-on fast page fault path:
-
-   old_spte = *spte;
-                                 pfn1 is swapped out:
-                                    spte = 0;
-
-                                 pfn1 is re-alloced for gfn2.
-
-                                 gpte is changed to point to
-                                 gfn2 by the guest:
-                                    spte = pfn1;
-
-   if (cmpxchg(spte, old_spte, old_spte+W)
-       mark_page_dirty(vcpu->kvm, gfn1)
-             OOPS!!!
-
-We dirty-log for gfn1, that means gfn2 is lost in dirty-bitmap.
-
-For direct sp, we can easily avoid it since the spte of direct sp is fixed
-to gfn. For indirect sp, before we do cmpxchg, we call gfn_to_pfn_atomic()
-to pin gfn to pfn, because after gfn_to_pfn_atomic():
-- We have held the refcount of pfn that means the pfn can not be freed and
-  be reused for another gfn.
-- The pfn is writable that means it can not be shared between different gfns
-  by KSM.
-
-Then, we can ensure the dirty bitmaps is correctly set for a gfn.
-
-Currently, to simplify the whole things, we disable fast page fault for
-indirect shadow page.
-
-2): Dirty bit tracking
-In the origin code, the spte can be fast updated (non-atomically) if the
-spte is read-only and the Accessed bit has already been set since the
-Accessed bit and Dirty bit can not be lost.
-
-But it is not true after fast page fault since the spte can be marked
-writable between reading spte and updating spte. Like below case:
-
-At the beginning:
-spte.W = 0
-spte.Accessed = 1
-
-   VCPU 0                                       VCPU0
-In mmu_spte_clear_track_bits():
-
-   old_spte = *spte;
-
-   /* 'if' condition is satisfied. */
-   if (old_spte.Accessed == 1 &&
-        old_spte.W == 0)
-      spte = 0ull;
-                                         on fast page fault path:
-                                             spte.W = 1
-                                         memory write on the spte:
-                                             spte.Dirty = 1
-
-
-   else
-      old_spte = xchg(spte, 0ull)
-
-
-   if (old_spte.Accessed == 1)
-      kvm_set_pfn_accessed(spte.pfn);
-   if (old_spte.Dirty == 1)
-      kvm_set_pfn_dirty(spte.pfn);
-      OOPS!!!
-
-The Dirty bit is lost in this case.
-
-In order to avoid this kind of issue, we always treat the spte as "volatile"
-if it can be updated out of mmu-lock, see spte_has_volatile_bits(), it means,
-the spte is always atomically updated in this case.
-
-3): flush tlbs due to spte updated
-If the spte is updated from writable to readonly, we should flush all TLBs,
-otherwise rmap_write_protect will find a read-only spte, even though the
-writable spte might be cached on a CPU's TLB.
-
-As mentioned before, the spte can be updated to writable out of mmu-lock on
-fast page fault path, in order to easily audit the path, we see if TLBs need
-be flushed caused by this reason in mmu_spte_update() since this is a common
-function to update spte (present -> present).
-
-Since the spte is "volatile" if it can be updated out of mmu-lock, we always
-atomically update the spte, the race caused by fast page fault can be avoided,
-See the comments in spte_has_volatile_bits() and mmu_spte_update().
-
-Lockless Access Tracking:
-
-This is used for Intel CPUs that are using EPT but do not support the EPT A/D
-bits. In this case, when the KVM MMU notifier is called to track accesses to a
-page (via kvm_mmu_notifier_clear_flush_young), it marks the PTE as not-present
-by clearing the RWX bits in the PTE and storing the original R & X bits in
-some unused/ignored bits. In addition, the SPTE_SPECIAL_MASK is also set on the
-PTE (using the ignored bit 62). When the VM tries to access the page later on,
-a fault is generated and the fast page fault mechanism described above is used
-to atomically restore the PTE to a Present state. The W bit is not saved when
-the PTE is marked for access tracking and during restoration to the Present
-state, the W bit is set depending on whether or not it was a write access. If
-it wasn't, then the W bit will remain clear until a write access happens, at 
-which time it will be set using the Dirty tracking mechanism described above.
-
-3. Reference
-------------
-
-Name:          kvm_lock
-Type:          mutex
-Arch:          any
-Protects:      - vm_list
-
-Name:          kvm_count_lock
-Type:          raw_spinlock_t
-Arch:          any
-Protects:      - hardware virtualization enable/disable
-Comment:       'raw' because hardware enabling/disabling must be atomic /wrt
-               migration.
-
-Name:          kvm_arch::tsc_write_lock
-Type:          raw_spinlock
-Arch:          x86
-Protects:      - kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}
-               - tsc offset in vmcb
-Comment:       'raw' because updating the tsc offsets must not be preempted.
-
-Name:          kvm->mmu_lock
-Type:          spinlock_t
-Arch:          any
-Protects:      -shadow page/shadow tlb entry
-Comment:       it is a spinlock since it is used in mmu notifier.
-
-Name:          kvm->srcu
-Type:          srcu lock
-Arch:          any
-Protects:      - kvm->memslots
-               - kvm->buses
-Comment:       The srcu read lock must be held while accessing memslots (e.g.
-               when using gfn_to_* functions) and while accessing in-kernel
-               MMIO/PIO address->device structure mapping (kvm->buses).
-               The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
-               if it is needed by multiple functions.
-
-Name:          blocked_vcpu_on_cpu_lock
-Type:          spinlock_t
-Arch:          x86
-Protects:      blocked_vcpu_on_cpu
-Comment:       This is a per-CPU lock and it is used for VT-d posted-interrupts.
-               When VT-d posted-interrupts is supported and the VM has assigned
-               devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu
-               protected by blocked_vcpu_on_cpu_lock, when VT-d hardware issues
-               wakeup notification event since external interrupts from the
-               assigned devices happens, we will find the vCPU on the list to
-               wakeup.
diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt
deleted file mode 100644 (file)
index 2efe0ef..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-The x86 kvm shadow mmu
-======================
-
-The mmu (in arch/x86/kvm, files mmu.[ch] and paging_tmpl.h) is responsible
-for presenting a standard x86 mmu to the guest, while translating guest
-physical addresses to host physical addresses.
-
-The mmu code attempts to satisfy the following requirements:
-
-- correctness: the guest should not be able to determine that it is running
-               on an emulated mmu except for timing (we attempt to comply
-               with the specification, not emulate the characteristics of
-               a particular implementation such as tlb size)
-- security:    the guest must not be able to touch host memory not assigned
-               to it
-- performance: minimize the performance penalty imposed by the mmu
-- scaling:     need to scale to large memory and large vcpu guests
-- hardware:    support the full range of x86 virtualization hardware
-- integration: Linux memory management code must be in control of guest memory
-               so that swapping, page migration, page merging, transparent
-               hugepages, and similar features work without change
-- dirty tracking: report writes to guest memory to enable live migration
-               and framebuffer-based displays
-- footprint:   keep the amount of pinned kernel memory low (most memory
-               should be shrinkable)
-- reliability:  avoid multipage or GFP_ATOMIC allocations
-
-Acronyms
-========
-
-pfn   host page frame number
-hpa   host physical address
-hva   host virtual address
-gfn   guest frame number
-gpa   guest physical address
-gva   guest virtual address
-ngpa  nested guest physical address
-ngva  nested guest virtual address
-pte   page table entry (used also to refer generically to paging structure
-      entries)
-gpte  guest pte (referring to gfns)
-spte  shadow pte (referring to pfns)
-tdp   two dimensional paging (vendor neutral term for NPT and EPT)
-
-Virtual and real hardware supported
-===================================
-
-The mmu supports first-generation mmu hardware, which allows an atomic switch
-of the current paging mode and cr3 during guest entry, as well as
-two-dimensional paging (AMD's NPT and Intel's EPT).  The emulated hardware
-it exposes is the traditional 2/3/4 level x86 mmu, with support for global
-pages, pae, pse, pse36, cr0.wp, and 1GB pages. Emulated hardware also
-able to expose NPT capable hardware on NPT capable hosts.
-
-Translation
-===========
-
-The primary job of the mmu is to program the processor's mmu to translate
-addresses for the guest.  Different translations are required at different
-times:
-
-- when guest paging is disabled, we translate guest physical addresses to
-  host physical addresses (gpa->hpa)
-- when guest paging is enabled, we translate guest virtual addresses, to
-  guest physical addresses, to host physical addresses (gva->gpa->hpa)
-- when the guest launches a guest of its own, we translate nested guest
-  virtual addresses, to nested guest physical addresses, to guest physical
-  addresses, to host physical addresses (ngva->ngpa->gpa->hpa)
-
-The primary challenge is to encode between 1 and 3 translations into hardware
-that support only 1 (traditional) and 2 (tdp) translations.  When the
-number of required translations matches the hardware, the mmu operates in
-direct mode; otherwise it operates in shadow mode (see below).
-
-Memory
-======
-
-Guest memory (gpa) is part of the user address space of the process that is
-using kvm.  Userspace defines the translation between guest addresses and user
-addresses (gpa->hva); note that two gpas may alias to the same hva, but not
-vice versa.
-
-These hvas may be backed using any method available to the host: anonymous
-memory, file backed memory, and device memory.  Memory might be paged by the
-host at any time.
-
-Events
-======
-
-The mmu is driven by events, some from the guest, some from the host.
-
-Guest generated events:
-- writes to control registers (especially cr3)
-- invlpg/invlpga instruction execution
-- access to missing or protected translations
-
-Host generated events:
-- changes in the gpa->hpa translation (either through gpa->hva changes or
-  through hva->hpa changes)
-- memory pressure (the shrinker)
-
-Shadow pages
-============
-
-The principal data structure is the shadow page, 'struct kvm_mmu_page'.  A
-shadow page contains 512 sptes, which can be either leaf or nonleaf sptes.  A
-shadow page may contain a mix of leaf and nonleaf sptes.
-
-A nonleaf spte allows the hardware mmu to reach the leaf pages and
-is not related to a translation directly.  It points to other shadow pages.
-
-A leaf spte corresponds to either one or two translations encoded into
-one paging structure entry.  These are always the lowest level of the
-translation stack, with optional higher level translations left to NPT/EPT.
-Leaf ptes point at guest pages.
-
-The following table shows translations encoded by leaf ptes, with higher-level
-translations in parentheses:
-
- Non-nested guests:
-  nonpaging:     gpa->hpa
-  paging:        gva->gpa->hpa
-  paging, tdp:   (gva->)gpa->hpa
- Nested guests:
-  non-tdp:       ngva->gpa->hpa  (*)
-  tdp:           (ngva->)ngpa->gpa->hpa
-
-(*) the guest hypervisor will encode the ngva->gpa translation into its page
-    tables if npt is not present
-
-Shadow pages contain the following information:
-  role.level:
-    The level in the shadow paging hierarchy that this shadow page belongs to.
-    1=4k sptes, 2=2M sptes, 3=1G sptes, etc.
-  role.direct:
-    If set, leaf sptes reachable from this page are for a linear range.
-    Examples include real mode translation, large guest pages backed by small
-    host pages, and gpa->hpa translations when NPT or EPT is active.
-    The linear range starts at (gfn << PAGE_SHIFT) and its size is determined
-    by role.level (2MB for first level, 1GB for second level, 0.5TB for third
-    level, 256TB for fourth level)
-    If clear, this page corresponds to a guest page table denoted by the gfn
-    field.
-  role.quadrant:
-    When role.gpte_is_8_bytes=0, the guest uses 32-bit gptes while the host uses 64-bit
-    sptes.  That means a guest page table contains more ptes than the host,
-    so multiple shadow pages are needed to shadow one guest page.
-    For first-level shadow pages, role.quadrant can be 0 or 1 and denotes the
-    first or second 512-gpte block in the guest page table.  For second-level
-    page tables, each 32-bit gpte is converted to two 64-bit sptes
-    (since each first-level guest page is shadowed by two first-level
-    shadow pages) so role.quadrant takes values in the range 0..3.  Each
-    quadrant maps 1GB virtual address space.
-  role.access:
-    Inherited guest access permissions in the form uwx.  Note execute
-    permission is positive, not negative.
-  role.invalid:
-    The page is invalid and should not be used.  It is a root page that is
-    currently pinned (by a cpu hardware register pointing to it); once it is
-    unpinned it will be destroyed.
-  role.gpte_is_8_bytes:
-    Reflects the size of the guest PTE for which the page is valid, i.e. '1'
-    if 64-bit gptes are in use, '0' if 32-bit gptes are in use.
-  role.nxe:
-    Contains the value of efer.nxe for which the page is valid.
-  role.cr0_wp:
-    Contains the value of cr0.wp for which the page is valid.
-  role.smep_andnot_wp:
-    Contains the value of cr4.smep && !cr0.wp for which the page is valid
-    (pages for which this is true are different from other pages; see the
-    treatment of cr0.wp=0 below).
-  role.smap_andnot_wp:
-    Contains the value of cr4.smap && !cr0.wp for which the page is valid
-    (pages for which this is true are different from other pages; see the
-    treatment of cr0.wp=0 below).
-  role.ept_sp:
-    This is a virtual flag to denote a shadowed nested EPT page.  ept_sp
-    is true if "cr0_wp && smap_andnot_wp", an otherwise invalid combination.
-  role.smm:
-    Is 1 if the page is valid in system management mode.  This field
-    determines which of the kvm_memslots array was used to build this
-    shadow page; it is also used to go back from a struct kvm_mmu_page
-    to a memslot, through the kvm_memslots_for_spte_role macro and
-    __gfn_to_memslot.
-  role.ad_disabled:
-    Is 1 if the MMU instance cannot use A/D bits.  EPT did not have A/D
-    bits before Haswell; shadow EPT page tables also cannot use A/D bits
-    if the L1 hypervisor does not enable them.
-  gfn:
-    Either the guest page table containing the translations shadowed by this
-    page, or the base page frame for linear translations.  See role.direct.
-  spt:
-    A pageful of 64-bit sptes containing the translations for this page.
-    Accessed by both kvm and hardware.
-    The page pointed to by spt will have its page->private pointing back
-    at the shadow page structure.
-    sptes in spt point either at guest pages, or at lower-level shadow pages.
-    Specifically, if sp1 and sp2 are shadow pages, then sp1->spt[n] may point
-    at __pa(sp2->spt).  sp2 will point back at sp1 through parent_pte.
-    The spt array forms a DAG structure with the shadow page as a node, and
-    guest pages as leaves.
-  gfns:
-    An array of 512 guest frame numbers, one for each present pte.  Used to
-    perform a reverse map from a pte to a gfn. When role.direct is set, any
-    element of this array can be calculated from the gfn field when used, in
-    this case, the array of gfns is not allocated. See role.direct and gfn.
-  root_count:
-    A counter keeping track of how many hardware registers (guest cr3 or
-    pdptrs) are now pointing at the page.  While this counter is nonzero, the
-    page cannot be destroyed.  See role.invalid.
-  parent_ptes:
-    The reverse mapping for the pte/ptes pointing at this page's spt. If
-    parent_ptes bit 0 is zero, only one spte points at this page and
-    parent_ptes points at this single spte, otherwise, there exists multiple
-    sptes pointing at this page and (parent_ptes & ~0x1) points at a data
-    structure with a list of parent sptes.
-  unsync:
-    If true, then the translations in this page may not match the guest's
-    translation.  This is equivalent to the state of the tlb when a pte is
-    changed but before the tlb entry is flushed.  Accordingly, unsync ptes
-    are synchronized when the guest executes invlpg or flushes its tlb by
-    other means.  Valid for leaf pages.
-  unsync_children:
-    How many sptes in the page point at pages that are unsync (or have
-    unsynchronized children).
-  unsync_child_bitmap:
-    A bitmap indicating which sptes in spt point (directly or indirectly) at
-    pages that may be unsynchronized.  Used to quickly locate all unsychronized
-    pages reachable from a given page.
-  clear_spte_count:
-    Only present on 32-bit hosts, where a 64-bit spte cannot be written
-    atomically.  The reader uses this while running out of the MMU lock
-    to detect in-progress updates and retry them until the writer has
-    finished the write.
-  write_flooding_count:
-    A guest may write to a page table many times, causing a lot of
-    emulations if the page needs to be write-protected (see "Synchronized
-    and unsynchronized pages" below).  Leaf pages can be unsynchronized
-    so that they do not trigger frequent emulation, but this is not
-    possible for non-leafs.  This field counts the number of emulations
-    since the last time the page table was actually used; if emulation
-    is triggered too frequently on this page, KVM will unmap the page
-    to avoid emulation in the future.
-
-Reverse map
-===========
-
-The mmu maintains a reverse mapping whereby all ptes mapping a page can be
-reached given its gfn.  This is used, for example, when swapping out a page.
-
-Synchronized and unsynchronized pages
-=====================================
-
-The guest uses two events to synchronize its tlb and page tables: tlb flushes
-and page invalidations (invlpg).
-
-A tlb flush means that we need to synchronize all sptes reachable from the
-guest's cr3.  This is expensive, so we keep all guest page tables write
-protected, and synchronize sptes to gptes when a gpte is written.
-
-A special case is when a guest page table is reachable from the current
-guest cr3.  In this case, the guest is obliged to issue an invlpg instruction
-before using the translation.  We take advantage of that by removing write
-protection from the guest page, and allowing the guest to modify it freely.
-We synchronize modified gptes when the guest invokes invlpg.  This reduces
-the amount of emulation we have to do when the guest modifies multiple gptes,
-or when the a guest page is no longer used as a page table and is used for
-random guest data.
-
-As a side effect we have to resynchronize all reachable unsynchronized shadow
-pages on a tlb flush.
-
-
-Reaction to events
-==================
-
-- guest page fault (or npt page fault, or ept violation)
-
-This is the most complicated event.  The cause of a page fault can be:
-
-  - a true guest fault (the guest translation won't allow the access) (*)
-  - access to a missing translation
-  - access to a protected translation
-    - when logging dirty pages, memory is write protected
-    - synchronized shadow pages are write protected (*)
-  - access to untranslatable memory (mmio)
-
-  (*) not applicable in direct mode
-
-Handling a page fault is performed as follows:
-
- - if the RSV bit of the error code is set, the page fault is caused by guest
-   accessing MMIO and cached MMIO information is available.
-   - walk shadow page table
-   - check for valid generation number in the spte (see "Fast invalidation of
-     MMIO sptes" below)
-   - cache the information to vcpu->arch.mmio_gva, vcpu->arch.access and
-     vcpu->arch.mmio_gfn, and call the emulator
- - If both P bit and R/W bit of error code are set, this could possibly
-   be handled as a "fast page fault" (fixed without taking the MMU lock).  See
-   the description in Documentation/virtual/kvm/locking.txt.
- - if needed, walk the guest page tables to determine the guest translation
-   (gva->gpa or ngpa->gpa)
-   - if permissions are insufficient, reflect the fault back to the guest
- - determine the host page
-   - if this is an mmio request, there is no host page; cache the info to
-     vcpu->arch.mmio_gva, vcpu->arch.access and vcpu->arch.mmio_gfn
- - walk the shadow page table to find the spte for the translation,
-   instantiating missing intermediate page tables as necessary
-   - If this is an mmio request, cache the mmio info to the spte and set some
-     reserved bit on the spte (see callers of kvm_mmu_set_mmio_spte_mask)
- - try to unsynchronize the page
-   - if successful, we can let the guest continue and modify the gpte
- - emulate the instruction
-   - if failed, unshadow the page and let the guest continue
- - update any translations that were modified by the instruction
-
-invlpg handling:
-
-  - walk the shadow page hierarchy and drop affected translations
-  - try to reinstantiate the indicated translation in the hope that the
-    guest will use it in the near future
-
-Guest control register updates:
-
-- mov to cr3
-  - look up new shadow roots
-  - synchronize newly reachable shadow pages
-
-- mov to cr0/cr4/efer
-  - set up mmu context for new paging mode
-  - look up new shadow roots
-  - synchronize newly reachable shadow pages
-
-Host translation updates:
-
-  - mmu notifier called with updated hva
-  - look up affected sptes through reverse map
-  - drop (or update) translations
-
-Emulating cr0.wp
-================
-
-If tdp is not enabled, the host must keep cr0.wp=1 so page write protection
-works for the guest kernel, not guest guest userspace.  When the guest
-cr0.wp=1, this does not present a problem.  However when the guest cr0.wp=0,
-we cannot map the permissions for gpte.u=1, gpte.w=0 to any spte (the
-semantics require allowing any guest kernel access plus user read access).
-
-We handle this by mapping the permissions to two possible sptes, depending
-on fault type:
-
-- kernel write fault: spte.u=0, spte.w=1 (allows full kernel access,
-  disallows user access)
-- read fault: spte.u=1, spte.w=0 (allows full read access, disallows kernel
-  write access)
-
-(user write faults generate a #PF)
-
-In the first case there are two additional complications:
-- if CR4.SMEP is enabled: since we've turned the page into a kernel page,
-  the kernel may now execute it.  We handle this by also setting spte.nx.
-  If we get a user fetch or read fault, we'll change spte.u=1 and
-  spte.nx=gpte.nx back.  For this to work, KVM forces EFER.NX to 1 when
-  shadow paging is in use.
-- if CR4.SMAP is disabled: since the page has been changed to a kernel
-  page, it can not be reused when CR4.SMAP is enabled. We set
-  CR4.SMAP && !CR0.WP into shadow page's role to avoid this case. Note,
-  here we do not care the case that CR4.SMAP is enabled since KVM will
-  directly inject #PF to guest due to failed permission check.
-
-To prevent an spte that was converted into a kernel page with cr0.wp=0
-from being written by the kernel after cr0.wp has changed to 1, we make
-the value of cr0.wp part of the page role.  This means that an spte created
-with one value of cr0.wp cannot be used when cr0.wp has a different value -
-it will simply be missed by the shadow page lookup code.  A similar issue
-exists when an spte created with cr0.wp=0 and cr4.smep=0 is used after
-changing cr4.smep to 1.  To avoid this, the value of !cr0.wp && cr4.smep
-is also made a part of the page role.
-
-Large pages
-===========
-
-The mmu supports all combinations of large and small guest and host pages.
-Supported page sizes include 4k, 2M, 4M, and 1G.  4M pages are treated as
-two separate 2M pages, on both guest and host, since the mmu always uses PAE
-paging.
-
-To instantiate a large spte, four constraints must be satisfied:
-
-- the spte must point to a large host page
-- the guest pte must be a large pte of at least equivalent size (if tdp is
-  enabled, there is no guest pte and this condition is satisfied)
-- if the spte will be writeable, the large page frame may not overlap any
-  write-protected pages
-- the guest page must be wholly contained by a single memory slot
-
-To check the last two conditions, the mmu maintains a ->disallow_lpage set of
-arrays for each memory slot and large page size.  Every write protected page
-causes its disallow_lpage to be incremented, thus preventing instantiation of
-a large spte.  The frames at the end of an unaligned memory slot have
-artificially inflated ->disallow_lpages so they can never be instantiated.
-
-Fast invalidation of MMIO sptes
-===============================
-
-As mentioned in "Reaction to events" above, kvm will cache MMIO
-information in leaf sptes.  When a new memslot is added or an existing
-memslot is changed, this information may become stale and needs to be
-invalidated.  This also needs to hold the MMU lock while walking all
-shadow pages, and is made more scalable with a similar technique.
-
-MMIO sptes have a few spare bits, which are used to store a
-generation number.  The global generation number is stored in
-kvm_memslots(kvm)->generation, and increased whenever guest memory info
-changes.
-
-When KVM finds an MMIO spte, it checks the generation number of the spte.
-If the generation number of the spte does not equal the global generation
-number, it will ignore the cached MMIO information and handle the page
-fault through the slow path.
-
-Since only 19 bits are used to store generation-number on mmio spte, all
-pages are zapped when there is an overflow.
-
-Unfortunately, a single memory access might access kvm_memslots(kvm) multiple
-times, the last one happening when the generation number is retrieved and
-stored into the MMIO spte.  Thus, the MMIO spte might be created based on
-out-of-date information, but with an up-to-date generation number.
-
-To avoid this, the generation number is incremented again after synchronize_srcu
-returns; thus, bit 63 of kvm_memslots(kvm)->generation set to 1 only during a
-memslot update, while some SRCU readers might be using the old copy.  We do not
-want to use an MMIO sptes created with an odd generation number, and we can do
-this without losing a bit in the MMIO spte.  The "update in-progress" bit of the
-generation is not stored in MMIO spte, and is so is implicitly zero when the
-generation is extracted out of the spte.  If KVM is unlucky and creates an MMIO
-spte while an update is in-progress, the next access to the spte will always be
-a cache miss.  For example, a subsequent access during the update window will
-miss due to the in-progress flag diverging, while an access after the update
-window closes will have a higher generation number (as compared to the spte).
-
-
-Further reading
-===============
-
-- NPT presentation from KVM Forum 2008
-  http://www.linux-kvm.org/images/c/c8/KvmForum2008%24kdf2008_21.pdf
-
diff --git a/Documentation/virtual/kvm/msr.txt b/Documentation/virtual/kvm/msr.txt
deleted file mode 100644 (file)
index df1f433..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-KVM-specific MSRs.
-Glauber Costa <glommer@redhat.com>, Red Hat Inc, 2010
-=====================================================
-
-KVM makes use of some custom MSRs to service some requests.
-
-Custom MSRs have a range reserved for them, that goes from
-0x4b564d00 to 0x4b564dff. There are MSRs outside this area,
-but they are deprecated and their use is discouraged.
-
-Custom MSR list
---------
-
-The current supported Custom MSR list is:
-
-MSR_KVM_WALL_CLOCK_NEW:   0x4b564d00
-
-       data: 4-byte alignment physical address of a memory area which must be
-       in guest RAM. This memory is expected to hold a copy of the following
-       structure:
-
-       struct pvclock_wall_clock {
-               u32   version;
-               u32   sec;
-               u32   nsec;
-       } __attribute__((__packed__));
-
-       whose data will be filled in by the hypervisor. The hypervisor is only
-       guaranteed to update this data at the moment of MSR write.
-       Users that want to reliably query this information more than once have
-       to write more than once to this MSR. Fields have the following meanings:
-
-               version: guest has to check version before and after grabbing
-               time information and check that they are both equal and even.
-               An odd version indicates an in-progress update.
-
-               sec: number of seconds for wallclock at time of boot.
-
-               nsec: number of nanoseconds for wallclock at time of boot.
-
-       In order to get the current wallclock time, the system_time from
-       MSR_KVM_SYSTEM_TIME_NEW needs to be added.
-
-       Note that although MSRs are per-CPU entities, the effect of this
-       particular MSR is global.
-
-       Availability of this MSR must be checked via bit 3 in 0x4000001 cpuid
-       leaf prior to usage.
-
-MSR_KVM_SYSTEM_TIME_NEW:  0x4b564d01
-
-       data: 4-byte aligned physical address of a memory area which must be in
-       guest RAM, plus an enable bit in bit 0. This memory is expected to hold
-       a copy of the following structure:
-
-       struct pvclock_vcpu_time_info {
-               u32   version;
-               u32   pad0;
-               u64   tsc_timestamp;
-               u64   system_time;
-               u32   tsc_to_system_mul;
-               s8    tsc_shift;
-               u8    flags;
-               u8    pad[2];
-       } __attribute__((__packed__)); /* 32 bytes */
-
-       whose data will be filled in by the hypervisor periodically. Only one
-       write, or registration, is needed for each VCPU. The interval between
-       updates of this structure is arbitrary and implementation-dependent.
-       The hypervisor may update this structure at any time it sees fit until
-       anything with bit0 == 0 is written to it.
-
-       Fields have the following meanings:
-
-               version: guest has to check version before and after grabbing
-               time information and check that they are both equal and even.
-               An odd version indicates an in-progress update.
-
-               tsc_timestamp: the tsc value at the current VCPU at the time
-               of the update of this structure. Guests can subtract this value
-               from current tsc to derive a notion of elapsed time since the
-               structure update.
-
-               system_time: a host notion of monotonic time, including sleep
-               time at the time this structure was last updated. Unit is
-               nanoseconds.
-
-               tsc_to_system_mul: multiplier to be used when converting
-               tsc-related quantity to nanoseconds
-
-               tsc_shift: shift to be used when converting tsc-related
-               quantity to nanoseconds. This shift will ensure that
-               multiplication with tsc_to_system_mul does not overflow.
-               A positive value denotes a left shift, a negative value
-               a right shift.
-
-               The conversion from tsc to nanoseconds involves an additional
-               right shift by 32 bits. With this information, guests can
-               derive per-CPU time by doing:
-
-                       time = (current_tsc - tsc_timestamp)
-                       if (tsc_shift >= 0)
-                               time <<= tsc_shift;
-                       else
-                               time >>= -tsc_shift;
-                       time = (time * tsc_to_system_mul) >> 32
-                       time = time + system_time
-
-               flags: bits in this field indicate extended capabilities
-               coordinated between the guest and the hypervisor. Availability
-               of specific flags has to be checked in 0x40000001 cpuid leaf.
-               Current flags are:
-
-                flag bit   | cpuid bit    | meaning
-               -------------------------------------------------------------
-                           |              | time measures taken across
-                    0      |      24      | multiple cpus are guaranteed to
-                           |              | be monotonic
-               -------------------------------------------------------------
-                           |              | guest vcpu has been paused by
-                    1      |     N/A      | the host
-                           |              | See 4.70 in api.txt
-               -------------------------------------------------------------
-
-       Availability of this MSR must be checked via bit 3 in 0x4000001 cpuid
-       leaf prior to usage.
-
-
-MSR_KVM_WALL_CLOCK:  0x11
-
-       data and functioning: same as MSR_KVM_WALL_CLOCK_NEW. Use that instead.
-
-       This MSR falls outside the reserved KVM range and may be removed in the
-       future. Its usage is deprecated.
-
-       Availability of this MSR must be checked via bit 0 in 0x4000001 cpuid
-       leaf prior to usage.
-
-MSR_KVM_SYSTEM_TIME: 0x12
-
-       data and functioning: same as MSR_KVM_SYSTEM_TIME_NEW. Use that instead.
-
-       This MSR falls outside the reserved KVM range and may be removed in the
-       future. Its usage is deprecated.
-
-       Availability of this MSR must be checked via bit 0 in 0x4000001 cpuid
-       leaf prior to usage.
-
-       The suggested algorithm for detecting kvmclock presence is then:
-
-               if (!kvm_para_available())    /* refer to cpuid.txt */
-                       return NON_PRESENT;
-
-               flags = cpuid_eax(0x40000001);
-               if (flags & 3) {
-                       msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
-                       msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;
-                       return PRESENT;
-               } else if (flags & 0) {
-                       msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
-                       msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
-                       return PRESENT;
-               } else
-                       return NON_PRESENT;
-
-MSR_KVM_ASYNC_PF_EN: 0x4b564d02
-       data: Bits 63-6 hold 64-byte aligned physical address of a
-       64 byte memory area which must be in guest RAM and must be
-       zeroed. Bits 5-3 are reserved and should be zero. Bit 0 is 1
-       when asynchronous page faults are enabled on the vcpu 0 when
-       disabled. Bit 1 is 1 if asynchronous page faults can be injected
-       when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
-       are delivered to L1 as #PF vmexits.  Bit 2 can be set only if
-       KVM_FEATURE_ASYNC_PF_VMEXIT is present in CPUID.
-
-       First 4 byte of 64 byte memory location will be written to by
-       the hypervisor at the time of asynchronous page fault (APF)
-       injection to indicate type of asynchronous page fault. Value
-       of 1 means that the page referred to by the page fault is not
-       present. Value 2 means that the page is now available. Disabling
-       interrupt inhibits APFs. Guest must not enable interrupt
-       before the reason is read, or it may be overwritten by another
-       APF. Since APF uses the same exception vector as regular page
-       fault guest must reset the reason to 0 before it does
-       something that can generate normal page fault.  If during page
-       fault APF reason is 0 it means that this is regular page
-       fault.
-
-       During delivery of type 1 APF cr2 contains a token that will
-       be used to notify a guest when missing page becomes
-       available. When page becomes available type 2 APF is sent with
-       cr2 set to the token associated with the page. There is special
-       kind of token 0xffffffff which tells vcpu that it should wake
-       up all processes waiting for APFs and no individual type 2 APFs
-       will be sent.
-
-       If APF is disabled while there are outstanding APFs, they will
-       not be delivered.
-
-       Currently type 2 APF will be always delivered on the same vcpu as
-       type 1 was, but guest should not rely on that.
-
-MSR_KVM_STEAL_TIME: 0x4b564d03
-
-       data: 64-byte alignment physical address of a memory area which must be
-       in guest RAM, plus an enable bit in bit 0. This memory is expected to
-       hold a copy of the following structure:
-
-       struct kvm_steal_time {
-               __u64 steal;
-               __u32 version;
-               __u32 flags;
-               __u8  preempted;
-               __u8  u8_pad[3];
-               __u32 pad[11];
-       }
-
-       whose data will be filled in by the hypervisor periodically. Only one
-       write, or registration, is needed for each VCPU. The interval between
-       updates of this structure is arbitrary and implementation-dependent.
-       The hypervisor may update this structure at any time it sees fit until
-       anything with bit0 == 0 is written to it. Guest is required to make sure
-       this structure is initialized to zero.
-
-       Fields have the following meanings:
-
-               version: a sequence counter. In other words, guest has to check
-               this field before and after grabbing time information and make
-               sure they are both equal and even. An odd version indicates an
-               in-progress update.
-
-               flags: At this point, always zero. May be used to indicate
-               changes in this structure in the future.
-
-               steal: the amount of time in which this vCPU did not run, in
-               nanoseconds. Time during which the vcpu is idle, will not be
-               reported as steal time.
-
-               preempted: indicate the vCPU who owns this struct is running or
-               not. Non-zero values mean the vCPU has been preempted. Zero
-               means the vCPU is not preempted. NOTE, it is always zero if the
-               the hypervisor doesn't support this field.
-
-MSR_KVM_EOI_EN: 0x4b564d04
-       data: Bit 0 is 1 when PV end of interrupt is enabled on the vcpu; 0
-       when disabled.  Bit 1 is reserved and must be zero.  When PV end of
-       interrupt is enabled (bit 0 set), bits 63-2 hold a 4-byte aligned
-       physical address of a 4 byte memory area which must be in guest RAM and
-       must be zeroed.
-
-       The first, least significant bit of 4 byte memory location will be
-       written to by the hypervisor, typically at the time of interrupt
-       injection.  Value of 1 means that guest can skip writing EOI to the apic
-       (using MSR or MMIO write); instead, it is sufficient to signal
-       EOI by clearing the bit in guest memory - this location will
-       later be polled by the hypervisor.
-       Value of 0 means that the EOI write is required.
-
-       It is always safe for the guest to ignore the optimization and perform
-       the APIC EOI write anyway.
-
-       Hypervisor is guaranteed to only modify this least
-       significant bit while in the current VCPU context, this means that
-       guest does not need to use either lock prefix or memory ordering
-       primitives to synchronise with the hypervisor.
-
-       However, hypervisor can set and clear this memory bit at any time:
-       therefore to make sure hypervisor does not interrupt the
-       guest and clear the least significant bit in the memory area
-       in the window between guest testing it to detect
-       whether it can skip EOI apic write and between guest
-       clearing it to signal EOI to the hypervisor,
-       guest must both read the least significant bit in the memory area and
-       clear it using a single CPU instruction, such as test and clear, or
-       compare and exchange.
-
-MSR_KVM_POLL_CONTROL: 0x4b564d05
-       Control host-side polling.
-
-       data: Bit 0 enables (1) or disables (0) host-side HLT polling logic.
-
-       KVM guests can request the host not to poll on HLT, for example if
-       they are performing polling themselves.
-
diff --git a/Documentation/virtual/kvm/nested-vmx.txt b/Documentation/virtual/kvm/nested-vmx.txt
deleted file mode 100644 (file)
index 97eb135..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-Nested VMX
-==========
-
-Overview
----------
-
-On Intel processors, KVM uses Intel's VMX (Virtual-Machine eXtensions)
-to easily and efficiently run guest operating systems. Normally, these guests
-*cannot* themselves be hypervisors running their own guests, because in VMX,
-guests cannot use VMX instructions.
-
-The "Nested VMX" feature adds this missing capability - of running guest
-hypervisors (which use VMX) with their own nested guests. It does so by
-allowing a guest to use VMX instructions, and correctly and efficiently
-emulating them using the single level of VMX available in the hardware.
-
-We describe in much greater detail the theory behind the nested VMX feature,
-its implementation and its performance characteristics, in the OSDI 2010 paper
-"The Turtles Project: Design and Implementation of Nested Virtualization",
-available at:
-
-       http://www.usenix.org/events/osdi10/tech/full_papers/Ben-Yehuda.pdf
-
-
-Terminology
------------
-
-Single-level virtualization has two levels - the host (KVM) and the guests.
-In nested virtualization, we have three levels: The host (KVM), which we call
-L0, the guest hypervisor, which we call L1, and its nested guest, which we
-call L2.
-
-
-Running nested VMX
-------------------
-
-The nested VMX feature is disabled by default. It can be enabled by giving
-the "nested=1" option to the kvm-intel module.
-
-No modifications are required to user space (qemu). However, qemu's default
-emulated CPU type (qemu64) does not list the "VMX" CPU feature, so it must be
-explicitly enabled, by giving qemu one of the following options:
-
-     -cpu host              (emulated CPU has all features of the real CPU)
-
-     -cpu qemu64,+vmx       (add just the vmx feature to a named CPU type)
-
-
-ABIs
-----
-
-Nested VMX aims to present a standard and (eventually) fully-functional VMX
-implementation for the a guest hypervisor to use. As such, the official
-specification of the ABI that it provides is Intel's VMX specification,
-namely volume 3B of their "Intel 64 and IA-32 Architectures Software
-Developer's Manual". Not all of VMX's features are currently fully supported,
-but the goal is to eventually support them all, starting with the VMX features
-which are used in practice by popular hypervisors (KVM and others).
-
-As a VMX implementation, nested VMX presents a VMCS structure to L1.
-As mandated by the spec, other than the two fields revision_id and abort,
-this structure is *opaque* to its user, who is not supposed to know or care
-about its internal structure. Rather, the structure is accessed through the
-VMREAD and VMWRITE instructions.
-Still, for debugging purposes, KVM developers might be interested to know the
-internals of this structure; This is struct vmcs12 from arch/x86/kvm/vmx.c.
-
-The name "vmcs12" refers to the VMCS that L1 builds for L2. In the code we
-also have "vmcs01", the VMCS that L0 built for L1, and "vmcs02" is the VMCS
-which L0 builds to actually run L2 - how this is done is explained in the
-aforementioned paper.
-
-For convenience, we repeat the content of struct vmcs12 here. If the internals
-of this structure changes, this can break live migration across KVM versions.
-VMCS12_REVISION (from vmx.c) should be changed if struct vmcs12 or its inner
-struct shadow_vmcs is ever changed.
-
-       typedef u64 natural_width;
-       struct __packed vmcs12 {
-               /* According to the Intel spec, a VMCS region must start with
-                * these two user-visible fields */
-               u32 revision_id;
-               u32 abort;
-
-               u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
-               u32 padding[7]; /* room for future expansion */
-
-               u64 io_bitmap_a;
-               u64 io_bitmap_b;
-               u64 msr_bitmap;
-               u64 vm_exit_msr_store_addr;
-               u64 vm_exit_msr_load_addr;
-               u64 vm_entry_msr_load_addr;
-               u64 tsc_offset;
-               u64 virtual_apic_page_addr;
-               u64 apic_access_addr;
-               u64 ept_pointer;
-               u64 guest_physical_address;
-               u64 vmcs_link_pointer;
-               u64 guest_ia32_debugctl;
-               u64 guest_ia32_pat;
-               u64 guest_ia32_efer;
-               u64 guest_pdptr0;
-               u64 guest_pdptr1;
-               u64 guest_pdptr2;
-               u64 guest_pdptr3;
-               u64 host_ia32_pat;
-               u64 host_ia32_efer;
-               u64 padding64[8]; /* room for future expansion */
-               natural_width cr0_guest_host_mask;
-               natural_width cr4_guest_host_mask;
-               natural_width cr0_read_shadow;
-               natural_width cr4_read_shadow;
-               natural_width cr3_target_value0;
-               natural_width cr3_target_value1;
-               natural_width cr3_target_value2;
-               natural_width cr3_target_value3;
-               natural_width exit_qualification;
-               natural_width guest_linear_address;
-               natural_width guest_cr0;
-               natural_width guest_cr3;
-               natural_width guest_cr4;
-               natural_width guest_es_base;
-               natural_width guest_cs_base;
-               natural_width guest_ss_base;
-               natural_width guest_ds_base;
-               natural_width guest_fs_base;
-               natural_width guest_gs_base;
-               natural_width guest_ldtr_base;
-               natural_width guest_tr_base;
-               natural_width guest_gdtr_base;
-               natural_width guest_idtr_base;
-               natural_width guest_dr7;
-               natural_width guest_rsp;
-               natural_width guest_rip;
-               natural_width guest_rflags;
-               natural_width guest_pending_dbg_exceptions;
-               natural_width guest_sysenter_esp;
-               natural_width guest_sysenter_eip;
-               natural_width host_cr0;
-               natural_width host_cr3;
-               natural_width host_cr4;
-               natural_width host_fs_base;
-               natural_width host_gs_base;
-               natural_width host_tr_base;
-               natural_width host_gdtr_base;
-               natural_width host_idtr_base;
-               natural_width host_ia32_sysenter_esp;
-               natural_width host_ia32_sysenter_eip;
-               natural_width host_rsp;
-               natural_width host_rip;
-               natural_width paddingl[8]; /* room for future expansion */
-               u32 pin_based_vm_exec_control;
-               u32 cpu_based_vm_exec_control;
-               u32 exception_bitmap;
-               u32 page_fault_error_code_mask;
-               u32 page_fault_error_code_match;
-               u32 cr3_target_count;
-               u32 vm_exit_controls;
-               u32 vm_exit_msr_store_count;
-               u32 vm_exit_msr_load_count;
-               u32 vm_entry_controls;
-               u32 vm_entry_msr_load_count;
-               u32 vm_entry_intr_info_field;
-               u32 vm_entry_exception_error_code;
-               u32 vm_entry_instruction_len;
-               u32 tpr_threshold;
-               u32 secondary_vm_exec_control;
-               u32 vm_instruction_error;
-               u32 vm_exit_reason;
-               u32 vm_exit_intr_info;
-               u32 vm_exit_intr_error_code;
-               u32 idt_vectoring_info_field;
-               u32 idt_vectoring_error_code;
-               u32 vm_exit_instruction_len;
-               u32 vmx_instruction_info;
-               u32 guest_es_limit;
-               u32 guest_cs_limit;
-               u32 guest_ss_limit;
-               u32 guest_ds_limit;
-               u32 guest_fs_limit;
-               u32 guest_gs_limit;
-               u32 guest_ldtr_limit;
-               u32 guest_tr_limit;
-               u32 guest_gdtr_limit;
-               u32 guest_idtr_limit;
-               u32 guest_es_ar_bytes;
-               u32 guest_cs_ar_bytes;
-               u32 guest_ss_ar_bytes;
-               u32 guest_ds_ar_bytes;
-               u32 guest_fs_ar_bytes;
-               u32 guest_gs_ar_bytes;
-               u32 guest_ldtr_ar_bytes;
-               u32 guest_tr_ar_bytes;
-               u32 guest_interruptibility_info;
-               u32 guest_activity_state;
-               u32 guest_sysenter_cs;
-               u32 host_ia32_sysenter_cs;
-               u32 padding32[8]; /* room for future expansion */
-               u16 virtual_processor_id;
-               u16 guest_es_selector;
-               u16 guest_cs_selector;
-               u16 guest_ss_selector;
-               u16 guest_ds_selector;
-               u16 guest_fs_selector;
-               u16 guest_gs_selector;
-               u16 guest_ldtr_selector;
-               u16 guest_tr_selector;
-               u16 host_es_selector;
-               u16 host_cs_selector;
-               u16 host_ss_selector;
-               u16 host_ds_selector;
-               u16 host_fs_selector;
-               u16 host_gs_selector;
-               u16 host_tr_selector;
-       };
-
-
-Authors
--------
-
-These patches were written by:
-     Abel Gordon, abelg <at> il.ibm.com
-     Nadav Har'El, nyh <at> il.ibm.com
-     Orit Wasserman, oritw <at> il.ibm.com
-     Ben-Ami Yassor, benami <at> il.ibm.com
-     Muli Ben-Yehuda, muli <at> il.ibm.com
-
-With contributions by:
-     Anthony Liguori, aliguori <at> us.ibm.com
-     Mike Day, mdday <at> us.ibm.com
-     Michael Factor, factor <at> il.ibm.com
-     Zvi Dubitzky, dubi <at> il.ibm.com
-
-And valuable reviews by:
-     Avi Kivity, avi <at> redhat.com
-     Gleb Natapov, gleb <at> redhat.com
-     Marcelo Tosatti, mtosatti <at> redhat.com
-     Kevin Tian, kevin.tian <at> intel.com
-     and others.
diff --git a/Documentation/virtual/kvm/ppc-pv.txt b/Documentation/virtual/kvm/ppc-pv.txt
deleted file mode 100644 (file)
index e26115c..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-The PPC KVM paravirtual interface
-=================================
-
-The basic execution principle by which KVM on PowerPC works is to run all kernel
-space code in PR=1 which is user space. This way we trap all privileged
-instructions and can emulate them accordingly.
-
-Unfortunately that is also the downfall. There are quite some privileged
-instructions that needlessly return us to the hypervisor even though they
-could be handled differently.
-
-This is what the PPC PV interface helps with. It takes privileged instructions
-and transforms them into unprivileged ones with some help from the hypervisor.
-This cuts down virtualization costs by about 50% on some of my benchmarks.
-
-The code for that interface can be found in arch/powerpc/kernel/kvm*
-
-Querying for existence
-======================
-
-To find out if we're running on KVM or not, we leverage the device tree. When
-Linux is running on KVM, a node /hypervisor exists. That node contains a
-compatible property with the value "linux,kvm".
-
-Once you determined you're running under a PV capable KVM, you can now use
-hypercalls as described below.
-
-KVM hypercalls
-==============
-
-Inside the device tree's /hypervisor node there's a property called
-'hypercall-instructions'. This property contains at most 4 opcodes that make
-up the hypercall. To call a hypercall, just call these instructions.
-
-The parameters are as follows:
-
-       Register        IN                      OUT
-
-       r0              -                       volatile
-       r3              1st parameter           Return code
-       r4              2nd parameter           1st output value
-       r5              3rd parameter           2nd output value
-       r6              4th parameter           3rd output value
-       r7              5th parameter           4th output value
-       r8              6th parameter           5th output value
-       r9              7th parameter           6th output value
-       r10             8th parameter           7th output value
-       r11             hypercall number        8th output value
-       r12             -                       volatile
-
-Hypercall definitions are shared in generic code, so the same hypercall numbers
-apply for x86 and powerpc alike with the exception that each KVM hypercall
-also needs to be ORed with the KVM vendor code which is (42 << 16).
-
-Return codes can be as follows:
-
-       Code            Meaning
-
-       0               Success
-       12              Hypercall not implemented
-       <0              Error
-
-The magic page
-==============
-
-To enable communication between the hypervisor and guest there is a new shared
-page that contains parts of supervisor visible register state. The guest can
-map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
-
-With this hypercall issued the guest always gets the magic page mapped at the
-desired location. The first parameter indicates the effective address when the
-MMU is enabled. The second parameter indicates the address in real mode, if
-applicable to the target. For now, we always map the page to -4096. This way we
-can access it using absolute load and store functions. The following
-instruction reads the first field of the magic page:
-
-       ld      rX, -4096(0)
-
-The interface is designed to be extensible should there be need later to add
-additional registers to the magic page. If you add fields to the magic page,
-also define a new hypercall feature to indicate that the host can give you more
-registers. Only if the host supports the additional features, make use of them.
-
-The magic page layout is described by struct kvm_vcpu_arch_shared
-in arch/powerpc/include/asm/kvm_para.h.
-
-Magic page features
-===================
-
-When mapping the magic page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE,
-a second return value is passed to the guest. This second return value contains
-a bitmap of available features inside the magic page.
-
-The following enhancements to the magic page are currently available:
-
-  KVM_MAGIC_FEAT_SR            Maps SR registers r/w in the magic page
-  KVM_MAGIC_FEAT_MAS0_TO_SPRG7 Maps MASn, ESR, PIR and high SPRGs
-
-For enhanced features in the magic page, please check for the existence of the
-feature before using them!
-
-Magic page flags
-================
-
-In addition to features that indicate whether a host is capable of a particular
-feature we also have a channel for a guest to tell the guest whether it's capable
-of something. This is what we call "flags".
-
-Flags are passed to the host in the low 12 bits of the Effective Address.
-
-The following flags are currently available for a guest to expose:
-
-  MAGIC_PAGE_FLAG_NOT_MAPPED_NX Guest handles NX bits correctly wrt magic page
-
-MSR bits
-========
-
-The MSR contains bits that require hypervisor intervention and bits that do
-not require direct hypervisor intervention because they only get interpreted
-when entering the guest or don't have any impact on the hypervisor's behavior.
-
-The following bits are safe to be set inside the guest:
-
-  MSR_EE
-  MSR_RI
-
-If any other bit changes in the MSR, please still use mtmsr(d).
-
-Patched instructions
-====================
-
-The "ld" and "std" instructions are transformed to "lwz" and "stw" instructions
-respectively on 32 bit systems with an added offset of 4 to accommodate for big
-endianness.
-
-The following is a list of mapping the Linux kernel performs when running as
-guest. Implementing any of those mappings is optional, as the instruction traps
-also act on the shared page. So calling privileged instructions still works as
-before.
-
-From                   To
-====                   ==
-
-mfmsr  rX              ld      rX, magic_page->msr
-mfsprg rX, 0           ld      rX, magic_page->sprg0
-mfsprg rX, 1           ld      rX, magic_page->sprg1
-mfsprg rX, 2           ld      rX, magic_page->sprg2
-mfsprg rX, 3           ld      rX, magic_page->sprg3
-mfsrr0 rX              ld      rX, magic_page->srr0
-mfsrr1 rX              ld      rX, magic_page->srr1
-mfdar  rX              ld      rX, magic_page->dar
-mfdsisr        rX              lwz     rX, magic_page->dsisr
-
-mtmsr  rX              std     rX, magic_page->msr
-mtsprg 0, rX           std     rX, magic_page->sprg0
-mtsprg 1, rX           std     rX, magic_page->sprg1
-mtsprg 2, rX           std     rX, magic_page->sprg2
-mtsprg 3, rX           std     rX, magic_page->sprg3
-mtsrr0 rX              std     rX, magic_page->srr0
-mtsrr1 rX              std     rX, magic_page->srr1
-mtdar  rX              std     rX, magic_page->dar
-mtdsisr        rX              stw     rX, magic_page->dsisr
-
-tlbsync                        nop
-
-mtmsrd rX, 0           b       <special mtmsr section>
-mtmsr  rX              b       <special mtmsr section>
-
-mtmsrd rX, 1           b       <special mtmsrd section>
-
-[Book3S only]
-mtsrin rX, rY          b       <special mtsrin section>
-
-[BookE only]
-wrteei [0|1]           b       <special wrteei section>
-
-
-Some instructions require more logic to determine what's going on than a load
-or store instruction can deliver. To enable patching of those, we keep some
-RAM around where we can live translate instructions to. What happens is the
-following:
-
-       1) copy emulation code to memory
-       2) patch that code to fit the emulated instruction
-       3) patch that code to return to the original pc + 4
-       4) patch the original instruction to branch to the new code
-
-That way we can inject an arbitrary amount of code as replacement for a single
-instruction. This allows us to check for pending interrupts when setting EE=1
-for example.
-
-Hypercall ABIs in KVM on PowerPC
-=================================
-1) KVM hypercalls (ePAPR)
-
-These are ePAPR compliant hypercall implementation (mentioned above). Even
-generic hypercalls are implemented here, like the ePAPR idle hcall. These are
-available on all targets.
-
-2) PAPR hypercalls
-
-PAPR hypercalls are needed to run server PowerPC PAPR guests (-M pseries in QEMU).
-These are the same hypercalls that pHyp, the POWER hypervisor implements. Some of
-them are handled in the kernel, some are handled in user space. This is only
-available on book3s_64.
-
-3) OSI hypercalls
-
-Mac-on-Linux is another user of KVM on PowerPC, which has its own hypercall (long
-before KVM). This is supported to maintain compatibility. All these hypercalls get
-forwarded to user space. This is only useful on book3s_32, but can be used with
-book3s_64 as well.
diff --git a/Documentation/virtual/kvm/review-checklist.txt b/Documentation/virtual/kvm/review-checklist.txt
deleted file mode 100644 (file)
index a83b276..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-Review checklist for kvm patches
-================================
-
-1.  The patch must follow Documentation/process/coding-style.rst and
-    Documentation/process/submitting-patches.rst.
-
-2.  Patches should be against kvm.git master branch.
-
-3.  If the patch introduces or modifies a new userspace API:
-    - the API must be documented in Documentation/virtual/kvm/api.txt
-    - the API must be discoverable using KVM_CHECK_EXTENSION
-
-4.  New state must include support for save/restore.
-
-5.  New features must default to off (userspace should explicitly request them).
-    Performance improvements can and should default to on.
-
-6.  New cpu features should be exposed via KVM_GET_SUPPORTED_CPUID2
-
-7.  Emulator changes should be accompanied by unit tests for qemu-kvm.git
-    kvm/test directory.
-
-8.  Changes should be vendor neutral when possible.  Changes to common code
-    are better than duplicating changes to vendor code.
-
-9.  Similarly, prefer changes to arch independent code than to arch dependent
-    code.
-
-10. User/kernel interfaces and guest/host interfaces must be 64-bit clean
-    (all variables and sizes naturally aligned on 64-bit; use specific types
-    only - u64 rather than ulong).
-
-11. New guest visible features must either be documented in a hardware manual
-    or be accompanied by documentation.
-
-12. Features must be robust against reset and kexec - for example, shared
-    host/guest memory must be unshared to prevent the host from writing to
-    guest memory that the guest has not reserved for this purpose.
diff --git a/Documentation/virtual/kvm/s390-diag.txt b/Documentation/virtual/kvm/s390-diag.txt
deleted file mode 100644 (file)
index 7c52e5f..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-The s390 DIAGNOSE call on KVM
-=============================
-
-KVM on s390 supports the DIAGNOSE call for making hypercalls, both for
-native hypercalls and for selected hypercalls found on other s390
-hypervisors.
-
-Note that bits are numbered as by the usual s390 convention (most significant
-bit on the left).
-
-
-General remarks
----------------
-
-DIAGNOSE calls by the guest cause a mandatory intercept. This implies
-all supported DIAGNOSE calls need to be handled by either KVM or its
-userspace.
-
-All DIAGNOSE calls supported by KVM use the RS-a format:
-
---------------------------------------
-|  '83'  | R1 | R3 | B2 |     D2     |
---------------------------------------
-0        8    12   16   20           31
-
-The second-operand address (obtained by the base/displacement calculation)
-is not used to address data. Instead, bits 48-63 of this address specify
-the function code, and bits 0-47 are ignored.
-
-The supported DIAGNOSE function codes vary by the userspace used. For
-DIAGNOSE function codes not specific to KVM, please refer to the
-documentation for the s390 hypervisors defining them.
-
-
-DIAGNOSE function code 'X'500' - KVM virtio functions
------------------------------------------------------
-
-If the function code specifies 0x500, various virtio-related functions
-are performed.
-
-General register 1 contains the virtio subfunction code. Supported
-virtio subfunctions depend on KVM's userspace. Generally, userspace
-provides either s390-virtio (subcodes 0-2) or virtio-ccw (subcode 3).
-
-Upon completion of the DIAGNOSE instruction, general register 2 contains
-the function's return code, which is either a return code or a subcode
-specific value.
-
-Subcode 0 - s390-virtio notification and early console printk
-    Handled by userspace.
-
-Subcode 1 - s390-virtio reset
-    Handled by userspace.
-
-Subcode 2 - s390-virtio set status
-    Handled by userspace.
-
-Subcode 3 - virtio-ccw notification
-    Handled by either userspace or KVM (ioeventfd case).
-
-    General register 2 contains a subchannel-identification word denoting
-    the subchannel of the virtio-ccw proxy device to be notified.
-
-    General register 3 contains the number of the virtqueue to be notified.
-
-    General register 4 contains a 64bit identifier for KVM usage (the
-    kvm_io_bus cookie). If general register 4 does not contain a valid
-    identifier, it is ignored.
-
-    After completion of the DIAGNOSE call, general register 2 may contain
-    a 64bit identifier (in the kvm_io_bus cookie case), or a negative
-    error value, if an internal error occurred.
-
-    See also the virtio standard for a discussion of this hypercall.
-
-
-DIAGNOSE function code 'X'501 - KVM breakpoint
-----------------------------------------------
-
-If the function code specifies 0x501, breakpoint functions may be performed.
-This function code is handled by userspace.
-
-This diagnose function code has no subfunctions and uses no parameters.
diff --git a/Documentation/virtual/kvm/timekeeping.txt b/Documentation/virtual/kvm/timekeeping.txt
deleted file mode 100644 (file)
index 76808a1..0000000
+++ /dev/null
@@ -1,612 +0,0 @@
-
-       Timekeeping Virtualization for X86-Based Architectures
-
-       Zachary Amsden <zamsden@redhat.com>
-       Copyright (c) 2010, Red Hat.  All rights reserved.
-
-1) Overview
-2) Timing Devices
-3) TSC Hardware
-4) Virtualization Problems
-
-=========================================================================
-
-1) Overview
-
-One of the most complicated parts of the X86 platform, and specifically,
-the virtualization of this platform is the plethora of timing devices available
-and the complexity of emulating those devices.  In addition, virtualization of
-time introduces a new set of challenges because it introduces a multiplexed
-division of time beyond the control of the guest CPU.
-
-First, we will describe the various timekeeping hardware available, then
-present some of the problems which arise and solutions available, giving
-specific recommendations for certain classes of KVM guests.
-
-The purpose of this document is to collect data and information relevant to
-timekeeping which may be difficult to find elsewhere, specifically,
-information relevant to KVM and hardware-based virtualization.
-
-=========================================================================
-
-2) Timing Devices
-
-First we discuss the basic hardware devices available.  TSC and the related
-KVM clock are special enough to warrant a full exposition and are described in
-the following section.
-
-2.1) i8254 - PIT
-
-One of the first timer devices available is the programmable interrupt timer,
-or PIT.  The PIT has a fixed frequency 1.193182 MHz base clock and three
-channels which can be programmed to deliver periodic or one-shot interrupts.
-These three channels can be configured in different modes and have individual
-counters.  Channel 1 and 2 were not available for general use in the original
-IBM PC, and historically were connected to control RAM refresh and the PC
-speaker.  Now the PIT is typically integrated as part of an emulated chipset
-and a separate physical PIT is not used.
-
-The PIT uses I/O ports 0x40 - 0x43.  Access to the 16-bit counters is done
-using single or multiple byte access to the I/O ports.  There are 6 modes
-available, but not all modes are available to all timers, as only timer 2
-has a connected gate input, required for modes 1 and 5.  The gate line is
-controlled by port 61h, bit 0, as illustrated in the following diagram.
-
- --------------             ----------------
-|              |           |                |
-|  1.1932 MHz  |---------->| CLOCK      OUT | ---------> IRQ 0
-|    Clock     |   |       |                |
- --------------    |    +->| GATE  TIMER 0  |
-                   |        ----------------
-                   |
-                   |        ----------------
-                   |       |                |
-                   |------>| CLOCK      OUT | ---------> 66.3 KHZ DRAM
-                   |       |                |            (aka /dev/null)
-                   |    +->| GATE  TIMER 1  |
-                   |        ----------------
-                   |
-                   |        ----------------
-                   |       |                |
-                   |------>| CLOCK      OUT | ---------> Port 61h, bit 5
-                           |                |      |
-Port 61h, bit 0 ---------->| GATE  TIMER 2  |       \_.----   ____
-                            ----------------         _|    )--|LPF|---Speaker
-                                                    / *----   \___/
-Port 61h, bit 1 -----------------------------------/
-
-The timer modes are now described.
-
-Mode 0: Single Timeout.   This is a one-shot software timeout that counts down
- when the gate is high (always true for timers 0 and 1).  When the count
- reaches zero, the output goes high.
-
-Mode 1: Triggered One-shot.  The output is initially set high.  When the gate
- line is set high, a countdown is initiated (which does not stop if the gate is
- lowered), during which the output is set low.  When the count reaches zero,
- the output goes high.
-
-Mode 2: Rate Generator.  The output is initially set high.  When the countdown
- reaches 1, the output goes low for one count and then returns high.  The value
- is reloaded and the countdown automatically resumes.  If the gate line goes
- low, the count is halted.  If the output is low when the gate is lowered, the
- output automatically goes high (this only affects timer 2).
-
-Mode 3: Square Wave.   This generates a high / low square wave.  The count
- determines the length of the pulse, which alternates between high and low
- when zero is reached.  The count only proceeds when gate is high and is
- automatically reloaded on reaching zero.  The count is decremented twice at
- each clock to generate a full high / low cycle at the full periodic rate.
- If the count is even, the clock remains high for N/2 counts and low for N/2
- counts; if the clock is odd, the clock is high for (N+1)/2 counts and low
- for (N-1)/2 counts.  Only even values are latched by the counter, so odd
- values are not observed when reading.  This is the intended mode for timer 2,
- which generates sine-like tones by low-pass filtering the square wave output.
-
-Mode 4: Software Strobe.  After programming this mode and loading the counter,
- the output remains high until the counter reaches zero.  Then the output
- goes low for 1 clock cycle and returns high.  The counter is not reloaded.
- Counting only occurs when gate is high.
-
-Mode 5: Hardware Strobe.  After programming and loading the counter, the
- output remains high.  When the gate is raised, a countdown is initiated
- (which does not stop if the gate is lowered).  When the counter reaches zero,
- the output goes low for 1 clock cycle and then returns high.  The counter is
- not reloaded.
-
-In addition to normal binary counting, the PIT supports BCD counting.  The
-command port, 0x43 is used to set the counter and mode for each of the three
-timers.
-
-PIT commands, issued to port 0x43, using the following bit encoding:
-
-Bit 7-4: Command (See table below)
-Bit 3-1: Mode (000 = Mode 0, 101 = Mode 5, 11X = undefined)
-Bit 0  : Binary (0) / BCD (1)
-
-Command table:
-
-0000 - Latch Timer 0 count for port 0x40
-       sample and hold the count to be read in port 0x40;
-       additional commands ignored until counter is read;
-       mode bits ignored.
-
-0001 - Set Timer 0 LSB mode for port 0x40
-       set timer to read LSB only and force MSB to zero;
-       mode bits set timer mode
-
-0010 - Set Timer 0 MSB mode for port 0x40
-       set timer to read MSB only and force LSB to zero;
-       mode bits set timer mode
-
-0011 - Set Timer 0 16-bit mode for port 0x40
-       set timer to read / write LSB first, then MSB;
-       mode bits set timer mode
-
-0100 - Latch Timer 1 count for port 0x41 - as described above
-0101 - Set Timer 1 LSB mode for port 0x41 - as described above
-0110 - Set Timer 1 MSB mode for port 0x41 - as described above
-0111 - Set Timer 1 16-bit mode for port 0x41 - as described above
-
-1000 - Latch Timer 2 count for port 0x42 - as described above
-1001 - Set Timer 2 LSB mode for port 0x42 - as described above
-1010 - Set Timer 2 MSB mode for port 0x42 - as described above
-1011 - Set Timer 2 16-bit mode for port 0x42 as described above
-
-1101 - General counter latch
-       Latch combination of counters into corresponding ports
-       Bit 3 = Counter 2
-       Bit 2 = Counter 1
-       Bit 1 = Counter 0
-       Bit 0 = Unused
-
-1110 - Latch timer status
-       Latch combination of counter mode into corresponding ports
-       Bit 3 = Counter 2
-       Bit 2 = Counter 1
-       Bit 1 = Counter 0
-
-       The output of ports 0x40-0x42 following this command will be:
-
-       Bit 7 = Output pin
-       Bit 6 = Count loaded (0 if timer has expired)
-       Bit 5-4 = Read / Write mode
-           01 = MSB only
-           10 = LSB only
-           11 = LSB / MSB (16-bit)
-       Bit 3-1 = Mode
-       Bit 0 = Binary (0) / BCD mode (1)
-
-2.2) RTC
-
-The second device which was available in the original PC was the MC146818 real
-time clock.  The original device is now obsolete, and usually emulated by the
-system chipset, sometimes by an HPET and some frankenstein IRQ routing.
-
-The RTC is accessed through CMOS variables, which uses an index register to
-control which bytes are read.  Since there is only one index register, read
-of the CMOS and read of the RTC require lock protection (in addition, it is
-dangerous to allow userspace utilities such as hwclock to have direct RTC
-access, as they could corrupt kernel reads and writes of CMOS memory).
-
-The RTC generates an interrupt which is usually routed to IRQ 8.  The interrupt
-can function as a periodic timer, an additional once a day alarm, and can issue
-interrupts after an update of the CMOS registers by the MC146818 is complete.
-The type of interrupt is signalled in the RTC status registers.
-
-The RTC will update the current time fields by battery power even while the
-system is off.  The current time fields should not be read while an update is
-in progress, as indicated in the status register.
-
-The clock uses a 32.768kHz crystal, so bits 6-4 of register A should be
-programmed to a 32kHz divider if the RTC is to count seconds.
-
-This is the RAM map originally used for the RTC/CMOS:
-
-Location    Size    Description
-------------------------------------------
-00h         byte    Current second (BCD)
-01h         byte    Seconds alarm (BCD)
-02h         byte    Current minute (BCD)
-03h         byte    Minutes alarm (BCD)
-04h         byte    Current hour (BCD)
-05h         byte    Hours alarm (BCD)
-06h         byte    Current day of week (BCD)
-07h         byte    Current day of month (BCD)
-08h         byte    Current month (BCD)
-09h         byte    Current year (BCD)
-0Ah         byte    Register A
-                       bit 7   = Update in progress
-                       bit 6-4 = Divider for clock
-                                  000 = 4.194 MHz
-                                  001 = 1.049 MHz
-                                  010 = 32 kHz
-                                  10X = test modes
-                                  110 = reset / disable
-                                  111 = reset / disable
-                       bit 3-0 = Rate selection for periodic interrupt
-                                  000 = periodic timer disabled
-                                  001 = 3.90625 uS
-                                  010 = 7.8125 uS
-                                  011 = .122070 mS
-                                  100 = .244141 mS
-                                     ...
-                                 1101 = 125 mS
-                                 1110 = 250 mS
-                                 1111 = 500 mS
-0Bh         byte    Register B
-                       bit 7   = Run (0) / Halt (1)
-                       bit 6   = Periodic interrupt enable
-                       bit 5   = Alarm interrupt enable
-                       bit 4   = Update-ended interrupt enable
-                       bit 3   = Square wave interrupt enable
-                       bit 2   = BCD calendar (0) / Binary (1)
-                       bit 1   = 12-hour mode (0) / 24-hour mode (1)
-                       bit 0   = 0 (DST off) / 1 (DST enabled)
-OCh         byte    Register C (read only)
-                       bit 7   = interrupt request flag (IRQF)
-                       bit 6   = periodic interrupt flag (PF)
-                       bit 5   = alarm interrupt flag (AF)
-                       bit 4   = update interrupt flag (UF)
-                       bit 3-0 = reserved
-ODh         byte    Register D (read only)
-                       bit 7   = RTC has power
-                       bit 6-0 = reserved
-32h         byte    Current century BCD (*)
-  (*) location vendor specific and now determined from ACPI global tables
-
-2.3) APIC
-
-On Pentium and later processors, an on-board timer is available to each CPU
-as part of the Advanced Programmable Interrupt Controller.  The APIC is
-accessed through memory-mapped registers and provides interrupt service to each
-CPU, used for IPIs and local timer interrupts.
-
-Although in theory the APIC is a safe and stable source for local interrupts,
-in practice, many bugs and glitches have occurred due to the special nature of
-the APIC CPU-local memory-mapped hardware.  Beware that CPU errata may affect
-the use of the APIC and that workarounds may be required.  In addition, some of
-these workarounds pose unique constraints for virtualization - requiring either
-extra overhead incurred from extra reads of memory-mapped I/O or additional
-functionality that may be more computationally expensive to implement.
-
-Since the APIC is documented quite well in the Intel and AMD manuals, we will
-avoid repetition of the detail here.  It should be pointed out that the APIC
-timer is programmed through the LVT (local vector timer) register, is capable
-of one-shot or periodic operation, and is based on the bus clock divided down
-by the programmable divider register.
-
-2.4) HPET
-
-HPET is quite complex, and was originally intended to replace the PIT / RTC
-support of the X86 PC.  It remains to be seen whether that will be the case, as
-the de facto standard of PC hardware is to emulate these older devices.  Some
-systems designated as legacy free may support only the HPET as a hardware timer
-device.
-
-The HPET spec is rather loose and vague, requiring at least 3 hardware timers,
-but allowing implementation freedom to support many more.  It also imposes no
-fixed rate on the timer frequency, but does impose some extremal values on
-frequency, error and slew.
-
-In general, the HPET is recommended as a high precision (compared to PIT /RTC)
-time source which is independent of local variation (as there is only one HPET
-in any given system).  The HPET is also memory-mapped, and its presence is
-indicated through ACPI tables by the BIOS.
-
-Detailed specification of the HPET is beyond the current scope of this
-document, as it is also very well documented elsewhere.
-
-2.5) Offboard Timers
-
-Several cards, both proprietary (watchdog boards) and commonplace (e1000) have
-timing chips built into the cards which may have registers which are accessible
-to kernel or user drivers.  To the author's knowledge, using these to generate
-a clocksource for a Linux or other kernel has not yet been attempted and is in
-general frowned upon as not playing by the agreed rules of the game.  Such a
-timer device would require additional support to be virtualized properly and is
-not considered important at this time as no known operating system does this.
-
-=========================================================================
-
-3) TSC Hardware
-
-The TSC or time stamp counter is relatively simple in theory; it counts
-instruction cycles issued by the processor, which can be used as a measure of
-time.  In practice, due to a number of problems, it is the most complicated
-timekeeping device to use.
-
-The TSC is represented internally as a 64-bit MSR which can be read with the
-RDMSR, RDTSC, or RDTSCP (when available) instructions.  In the past, hardware
-limitations made it possible to write the TSC, but generally on old hardware it
-was only possible to write the low 32-bits of the 64-bit counter, and the upper
-32-bits of the counter were cleared.  Now, however, on Intel processors family
-0Fh, for models 3, 4 and 6, and family 06h, models e and f, this restriction
-has been lifted and all 64-bits are writable.  On AMD systems, the ability to
-write the TSC MSR is not an architectural guarantee.
-
-The TSC is accessible from CPL-0 and conditionally, for CPL > 0 software by
-means of the CR4.TSD bit, which when enabled, disables CPL > 0 TSC access.
-
-Some vendors have implemented an additional instruction, RDTSCP, which returns
-atomically not just the TSC, but an indicator which corresponds to the
-processor number.  This can be used to index into an array of TSC variables to
-determine offset information in SMP systems where TSCs are not synchronized.
-The presence of this instruction must be determined by consulting CPUID feature
-bits.
-
-Both VMX and SVM provide extension fields in the virtualization hardware which
-allows the guest visible TSC to be offset by a constant.  Newer implementations
-promise to allow the TSC to additionally be scaled, but this hardware is not
-yet widely available.
-
-3.1) TSC synchronization
-
-The TSC is a CPU-local clock in most implementations.  This means, on SMP
-platforms, the TSCs of different CPUs may start at different times depending
-on when the CPUs are powered on.  Generally, CPUs on the same die will share
-the same clock, however, this is not always the case.
-
-The BIOS may attempt to resynchronize the TSCs during the poweron process and
-the operating system or other system software may attempt to do this as well.
-Several hardware limitations make the problem worse - if it is not possible to
-write the full 64-bits of the TSC, it may be impossible to match the TSC in
-newly arriving CPUs to that of the rest of the system, resulting in
-unsynchronized TSCs.  This may be done by BIOS or system software, but in
-practice, getting a perfectly synchronized TSC will not be possible unless all
-values are read from the same clock, which generally only is possible on single
-socket systems or those with special hardware support.
-
-3.2) TSC and CPU hotplug
-
-As touched on already, CPUs which arrive later than the boot time of the system
-may not have a TSC value that is synchronized with the rest of the system.
-Either system software, BIOS, or SMM code may actually try to establish the TSC
-to a value matching the rest of the system, but a perfect match is usually not
-a guarantee.  This can have the effect of bringing a system from a state where
-TSC is synchronized back to a state where TSC synchronization flaws, however
-small, may be exposed to the OS and any virtualization environment.
-
-3.3) TSC and multi-socket / NUMA
-
-Multi-socket systems, especially large multi-socket systems are likely to have
-individual clocksources rather than a single, universally distributed clock.
-Since these clocks are driven by different crystals, they will not have
-perfectly matched frequency, and temperature and electrical variations will
-cause the CPU clocks, and thus the TSCs to drift over time.  Depending on the
-exact clock and bus design, the drift may or may not be fixed in absolute
-error, and may accumulate over time.
-
-In addition, very large systems may deliberately slew the clocks of individual
-cores.  This technique, known as spread-spectrum clocking, reduces EMI at the
-clock frequency and harmonics of it, which may be required to pass FCC
-standards for telecommunications and computer equipment.
-
-It is recommended not to trust the TSCs to remain synchronized on NUMA or
-multiple socket systems for these reasons.
-
-3.4) TSC and C-states
-
-C-states, or idling states of the processor, especially C1E and deeper sleep
-states may be problematic for TSC as well.  The TSC may stop advancing in such
-a state, resulting in a TSC which is behind that of other CPUs when execution
-is resumed.  Such CPUs must be detected and flagged by the operating system
-based on CPU and chipset identifications.
-
-The TSC in such a case may be corrected by catching it up to a known external
-clocksource.
-
-3.5) TSC frequency change / P-states
-
-To make things slightly more interesting, some CPUs may change frequency.  They
-may or may not run the TSC at the same rate, and because the frequency change
-may be staggered or slewed, at some points in time, the TSC rate may not be
-known other than falling within a range of values.  In this case, the TSC will
-not be a stable time source, and must be calibrated against a known, stable,
-external clock to be a usable source of time.
-
-Whether the TSC runs at a constant rate or scales with the P-state is model
-dependent and must be determined by inspecting CPUID, chipset or vendor
-specific MSR fields.
-
-In addition, some vendors have known bugs where the P-state is actually
-compensated for properly during normal operation, but when the processor is
-inactive, the P-state may be raised temporarily to service cache misses from
-other processors.  In such cases, the TSC on halted CPUs could advance faster
-than that of non-halted processors.  AMD Turion processors are known to have
-this problem.
-
-3.6) TSC and STPCLK / T-states
-
-External signals given to the processor may also have the effect of stopping
-the TSC.  This is typically done for thermal emergency power control to prevent
-an overheating condition, and typically, there is no way to detect that this
-condition has happened.
-
-3.7) TSC virtualization - VMX
-
-VMX provides conditional trapping of RDTSC, RDMSR, WRMSR and RDTSCP
-instructions, which is enough for full virtualization of TSC in any manner.  In
-addition, VMX allows passing through the host TSC plus an additional TSC_OFFSET
-field specified in the VMCS.  Special instructions must be used to read and
-write the VMCS field.
-
-3.8) TSC virtualization - SVM
-
-SVM provides conditional trapping of RDTSC, RDMSR, WRMSR and RDTSCP
-instructions, which is enough for full virtualization of TSC in any manner.  In
-addition, SVM allows passing through the host TSC plus an additional offset
-field specified in the SVM control block.
-
-3.9) TSC feature bits in Linux
-
-In summary, there is no way to guarantee the TSC remains in perfect
-synchronization unless it is explicitly guaranteed by the architecture.  Even
-if so, the TSCs in multi-sockets or NUMA systems may still run independently
-despite being locally consistent.
-
-The following feature bits are used by Linux to signal various TSC attributes,
-but they can only be taken to be meaningful for UP or single node systems.
-
-X86_FEATURE_TSC                : The TSC is available in hardware
-X86_FEATURE_RDTSCP             : The RDTSCP instruction is available
-X86_FEATURE_CONSTANT_TSC       : The TSC rate is unchanged with P-states
-X86_FEATURE_NONSTOP_TSC                : The TSC does not stop in C-states
-X86_FEATURE_TSC_RELIABLE       : TSC sync checks are skipped (VMware)
-
-4) Virtualization Problems
-
-Timekeeping is especially problematic for virtualization because a number of
-challenges arise.  The most obvious problem is that time is now shared between
-the host and, potentially, a number of virtual machines.  Thus the virtual
-operating system does not run with 100% usage of the CPU, despite the fact that
-it may very well make that assumption.  It may expect it to remain true to very
-exacting bounds when interrupt sources are disabled, but in reality only its
-virtual interrupt sources are disabled, and the machine may still be preempted
-at any time.  This causes problems as the passage of real time, the injection
-of machine interrupts and the associated clock sources are no longer completely
-synchronized with real time.
-
-This same problem can occur on native hardware to a degree, as SMM mode may
-steal cycles from the naturally on X86 systems when SMM mode is used by the
-BIOS, but not in such an extreme fashion.  However, the fact that SMM mode may
-cause similar problems to virtualization makes it a good justification for
-solving many of these problems on bare metal.
-
-4.1) Interrupt clocking
-
-One of the most immediate problems that occurs with legacy operating systems
-is that the system timekeeping routines are often designed to keep track of
-time by counting periodic interrupts.  These interrupts may come from the PIT
-or the RTC, but the problem is the same: the host virtualization engine may not
-be able to deliver the proper number of interrupts per second, and so guest
-time may fall behind.  This is especially problematic if a high interrupt rate
-is selected, such as 1000 HZ, which is unfortunately the default for many Linux
-guests.
-
-There are three approaches to solving this problem; first, it may be possible
-to simply ignore it.  Guests which have a separate time source for tracking
-'wall clock' or 'real time' may not need any adjustment of their interrupts to
-maintain proper time.  If this is not sufficient, it may be necessary to inject
-additional interrupts into the guest in order to increase the effective
-interrupt rate.  This approach leads to complications in extreme conditions,
-where host load or guest lag is too much to compensate for, and thus another
-solution to the problem has risen: the guest may need to become aware of lost
-ticks and compensate for them internally.  Although promising in theory, the
-implementation of this policy in Linux has been extremely error prone, and a
-number of buggy variants of lost tick compensation are distributed across
-commonly used Linux systems.
-
-Windows uses periodic RTC clocking as a means of keeping time internally, and
-thus requires interrupt slewing to keep proper time.  It does use a low enough
-rate (ed: is it 18.2 Hz?) however that it has not yet been a problem in
-practice.
-
-4.2) TSC sampling and serialization
-
-As the highest precision time source available, the cycle counter of the CPU
-has aroused much interest from developers.  As explained above, this timer has
-many problems unique to its nature as a local, potentially unstable and
-potentially unsynchronized source.  One issue which is not unique to the TSC,
-but is highlighted because of its very precise nature is sampling delay.  By
-definition, the counter, once read is already old.  However, it is also
-possible for the counter to be read ahead of the actual use of the result.
-This is a consequence of the superscalar execution of the instruction stream,
-which may execute instructions out of order.  Such execution is called
-non-serialized.  Forcing serialized execution is necessary for precise
-measurement with the TSC, and requires a serializing instruction, such as CPUID
-or an MSR read.
-
-Since CPUID may actually be virtualized by a trap and emulate mechanism, this
-serialization can pose a performance issue for hardware virtualization.  An
-accurate time stamp counter reading may therefore not always be available, and
-it may be necessary for an implementation to guard against "backwards" reads of
-the TSC as seen from other CPUs, even in an otherwise perfectly synchronized
-system.
-
-4.3) Timespec aliasing
-
-Additionally, this lack of serialization from the TSC poses another challenge
-when using results of the TSC when measured against another time source.  As
-the TSC is much higher precision, many possible values of the TSC may be read
-while another clock is still expressing the same value.
-
-That is, you may read (T,T+10) while external clock C maintains the same value.
-Due to non-serialized reads, you may actually end up with a range which
-fluctuates - from (T-1.. T+10).  Thus, any time calculated from a TSC, but
-calibrated against an external value may have a range of valid values.
-Re-calibrating this computation may actually cause time, as computed after the
-calibration, to go backwards, compared with time computed before the
-calibration.
-
-This problem is particularly pronounced with an internal time source in Linux,
-the kernel time, which is expressed in the theoretically high resolution
-timespec - but which advances in much larger granularity intervals, sometimes
-at the rate of jiffies, and possibly in catchup modes, at a much larger step.
-
-This aliasing requires care in the computation and recalibration of kvmclock
-and any other values derived from TSC computation (such as TSC virtualization
-itself).
-
-4.4) Migration
-
-Migration of a virtual machine raises problems for timekeeping in two ways.
-First, the migration itself may take time, during which interrupts cannot be
-delivered, and after which, the guest time may need to be caught up.  NTP may
-be able to help to some degree here, as the clock correction required is
-typically small enough to fall in the NTP-correctable window.
-
-An additional concern is that timers based off the TSC (or HPET, if the raw bus
-clock is exposed) may now be running at different rates, requiring compensation
-in some way in the hypervisor by virtualizing these timers.  In addition,
-migrating to a faster machine may preclude the use of a passthrough TSC, as a
-faster clock cannot be made visible to a guest without the potential of time
-advancing faster than usual.  A slower clock is less of a problem, as it can
-always be caught up to the original rate.  KVM clock avoids these problems by
-simply storing multipliers and offsets against the TSC for the guest to convert
-back into nanosecond resolution values.
-
-4.5) Scheduling
-
-Since scheduling may be based on precise timing and firing of interrupts, the
-scheduling algorithms of an operating system may be adversely affected by
-virtualization.  In theory, the effect is random and should be universally
-distributed, but in contrived as well as real scenarios (guest device access,
-causes of virtualization exits, possible context switch), this may not always
-be the case.  The effect of this has not been well studied.
-
-In an attempt to work around this, several implementations have provided a
-paravirtualized scheduler clock, which reveals the true amount of CPU time for
-which a virtual machine has been running.
-
-4.6) Watchdogs
-
-Watchdog timers, such as the lock detector in Linux may fire accidentally when
-running under hardware virtualization due to timer interrupts being delayed or
-misinterpretation of the passage of real time.  Usually, these warnings are
-spurious and can be ignored, but in some circumstances it may be necessary to
-disable such detection.
-
-4.7) Delays and precision timing
-
-Precise timing and delays may not be possible in a virtualized system.  This
-can happen if the system is controlling physical hardware, or issues delays to
-compensate for slower I/O to and from devices.  The first issue is not solvable
-in general for a virtualized system; hardware control software can't be
-adequately virtualized without a full real-time operating system, which would
-require an RT aware virtualization platform.
-
-The second issue may cause performance problems, but this is unlikely to be a
-significant issue.  In many cases these delays may be eliminated through
-configuration or paravirtualization.
-
-4.8) Covert channels and leaks
-
-In addition to the above problems, time information will inevitably leak to the
-guest about the host in anything but a perfect implementation of virtualized
-time.  This may allow the guest to infer the presence of a hypervisor (as in a
-red-pill type detection), and it may allow information to leak between guests
-by using CPU utilization itself as a signalling channel.  Preventing such
-problems would require completely isolated virtual time which may not track
-real time any longer.  This may be useful in certain security or QA contexts,
-but in general isn't recommended for real-world deployment scenarios.
diff --git a/Documentation/virtual/kvm/vcpu-requests.rst b/Documentation/virtual/kvm/vcpu-requests.rst
deleted file mode 100644 (file)
index 5feb370..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-=================
-KVM VCPU Requests
-=================
-
-Overview
-========
-
-KVM supports an internal API enabling threads to request a VCPU thread to
-perform some activity.  For example, a thread may request a VCPU to flush
-its TLB with a VCPU request.  The API consists of the following functions::
-
-  /* Check if any requests are pending for VCPU @vcpu. */
-  bool kvm_request_pending(struct kvm_vcpu *vcpu);
-
-  /* Check if VCPU @vcpu has request @req pending. */
-  bool kvm_test_request(int req, struct kvm_vcpu *vcpu);
-
-  /* Clear request @req for VCPU @vcpu. */
-  void kvm_clear_request(int req, struct kvm_vcpu *vcpu);
-
-  /*
-   * Check if VCPU @vcpu has request @req pending. When the request is
-   * pending it will be cleared and a memory barrier, which pairs with
-   * another in kvm_make_request(), will be issued.
-   */
-  bool kvm_check_request(int req, struct kvm_vcpu *vcpu);
-
-  /*
-   * Make request @req of VCPU @vcpu. Issues a memory barrier, which pairs
-   * with another in kvm_check_request(), prior to setting the request.
-   */
-  void kvm_make_request(int req, struct kvm_vcpu *vcpu);
-
-  /* Make request @req of all VCPUs of the VM with struct kvm @kvm. */
-  bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
-
-Typically a requester wants the VCPU to perform the activity as soon
-as possible after making the request.  This means most requests
-(kvm_make_request() calls) are followed by a call to kvm_vcpu_kick(),
-and kvm_make_all_cpus_request() has the kicking of all VCPUs built
-into it.
-
-VCPU Kicks
-----------
-
-The goal of a VCPU kick is to bring a VCPU thread out of guest mode in
-order to perform some KVM maintenance.  To do so, an IPI is sent, forcing
-a guest mode exit.  However, a VCPU thread may not be in guest mode at the
-time of the kick.  Therefore, depending on the mode and state of the VCPU
-thread, there are two other actions a kick may take.  All three actions
-are listed below:
-
-1) Send an IPI.  This forces a guest mode exit.
-2) Waking a sleeping VCPU.  Sleeping VCPUs are VCPU threads outside guest
-   mode that wait on waitqueues.  Waking them removes the threads from
-   the waitqueues, allowing the threads to run again.  This behavior
-   may be suppressed, see KVM_REQUEST_NO_WAKEUP below.
-3) Nothing.  When the VCPU is not in guest mode and the VCPU thread is not
-   sleeping, then there is nothing to do.
-
-VCPU Mode
----------
-
-VCPUs have a mode state, ``vcpu->mode``, that is used to track whether the
-guest is running in guest mode or not, as well as some specific
-outside guest mode states.  The architecture may use ``vcpu->mode`` to
-ensure VCPU requests are seen by VCPUs (see "Ensuring Requests Are Seen"),
-as well as to avoid sending unnecessary IPIs (see "IPI Reduction"), and
-even to ensure IPI acknowledgements are waited upon (see "Waiting for
-Acknowledgements").  The following modes are defined:
-
-OUTSIDE_GUEST_MODE
-
-  The VCPU thread is outside guest mode.
-
-IN_GUEST_MODE
-
-  The VCPU thread is in guest mode.
-
-EXITING_GUEST_MODE
-
-  The VCPU thread is transitioning from IN_GUEST_MODE to
-  OUTSIDE_GUEST_MODE.
-
-READING_SHADOW_PAGE_TABLES
-
-  The VCPU thread is outside guest mode, but it wants the sender of
-  certain VCPU requests, namely KVM_REQ_TLB_FLUSH, to wait until the VCPU
-  thread is done reading the page tables.
-
-VCPU Request Internals
-======================
-
-VCPU requests are simply bit indices of the ``vcpu->requests`` bitmap.
-This means general bitops, like those documented in [atomic-ops]_ could
-also be used, e.g. ::
-
-  clear_bit(KVM_REQ_UNHALT & KVM_REQUEST_MASK, &vcpu->requests);
-
-However, VCPU request users should refrain from doing so, as it would
-break the abstraction.  The first 8 bits are reserved for architecture
-independent requests, all additional bits are available for architecture
-dependent requests.
-
-Architecture Independent Requests
----------------------------------
-
-KVM_REQ_TLB_FLUSH
-
-  KVM's common MMU notifier may need to flush all of a guest's TLB
-  entries, calling kvm_flush_remote_tlbs() to do so.  Architectures that
-  choose to use the common kvm_flush_remote_tlbs() implementation will
-  need to handle this VCPU request.
-
-KVM_REQ_MMU_RELOAD
-
-  When shadow page tables are used and memory slots are removed it's
-  necessary to inform each VCPU to completely refresh the tables.  This
-  request is used for that.
-
-KVM_REQ_PENDING_TIMER
-
-  This request may be made from a timer handler run on the host on behalf
-  of a VCPU.  It informs the VCPU thread to inject a timer interrupt.
-
-KVM_REQ_UNHALT
-
-  This request may be made from the KVM common function kvm_vcpu_block(),
-  which is used to emulate an instruction that causes a CPU to halt until
-  one of an architectural specific set of events and/or interrupts is
-  received (determined by checking kvm_arch_vcpu_runnable()).  When that
-  event or interrupt arrives kvm_vcpu_block() makes the request.  This is
-  in contrast to when kvm_vcpu_block() returns due to any other reason,
-  such as a pending signal, which does not indicate the VCPU's halt
-  emulation should stop, and therefore does not make the request.
-
-KVM_REQUEST_MASK
-----------------
-
-VCPU requests should be masked by KVM_REQUEST_MASK before using them with
-bitops.  This is because only the lower 8 bits are used to represent the
-request's number.  The upper bits are used as flags.  Currently only two
-flags are defined.
-
-VCPU Request Flags
-------------------
-
-KVM_REQUEST_NO_WAKEUP
-
-  This flag is applied to requests that only need immediate attention
-  from VCPUs running in guest mode.  That is, sleeping VCPUs do not need
-  to be awaken for these requests.  Sleeping VCPUs will handle the
-  requests when they are awaken later for some other reason.
-
-KVM_REQUEST_WAIT
-
-  When requests with this flag are made with kvm_make_all_cpus_request(),
-  then the caller will wait for each VCPU to acknowledge its IPI before
-  proceeding.  This flag only applies to VCPUs that would receive IPIs.
-  If, for example, the VCPU is sleeping, so no IPI is necessary, then
-  the requesting thread does not wait.  This means that this flag may be
-  safely combined with KVM_REQUEST_NO_WAKEUP.  See "Waiting for
-  Acknowledgements" for more information about requests with
-  KVM_REQUEST_WAIT.
-
-VCPU Requests with Associated State
-===================================
-
-Requesters that want the receiving VCPU to handle new state need to ensure
-the newly written state is observable to the receiving VCPU thread's CPU
-by the time it observes the request.  This means a write memory barrier
-must be inserted after writing the new state and before setting the VCPU
-request bit.  Additionally, on the receiving VCPU thread's side, a
-corresponding read barrier must be inserted after reading the request bit
-and before proceeding to read the new state associated with it.  See
-scenario 3, Message and Flag, of [lwn-mb]_ and the kernel documentation
-[memory-barriers]_.
-
-The pair of functions, kvm_check_request() and kvm_make_request(), provide
-the memory barriers, allowing this requirement to be handled internally by
-the API.
-
-Ensuring Requests Are Seen
-==========================
-
-When making requests to VCPUs, we want to avoid the receiving VCPU
-executing in guest mode for an arbitrary long time without handling the
-request.  We can be sure this won't happen as long as we ensure the VCPU
-thread checks kvm_request_pending() before entering guest mode and that a
-kick will send an IPI to force an exit from guest mode when necessary.
-Extra care must be taken to cover the period after the VCPU thread's last
-kvm_request_pending() check and before it has entered guest mode, as kick
-IPIs will only trigger guest mode exits for VCPU threads that are in guest
-mode or at least have already disabled interrupts in order to prepare to
-enter guest mode.  This means that an optimized implementation (see "IPI
-Reduction") must be certain when it's safe to not send the IPI.  One
-solution, which all architectures except s390 apply, is to:
-
-- set ``vcpu->mode`` to IN_GUEST_MODE between disabling the interrupts and
-  the last kvm_request_pending() check;
-- enable interrupts atomically when entering the guest.
-
-This solution also requires memory barriers to be placed carefully in both
-the requesting thread and the receiving VCPU.  With the memory barriers we
-can exclude the possibility of a VCPU thread observing
-!kvm_request_pending() on its last check and then not receiving an IPI for
-the next request made of it, even if the request is made immediately after
-the check.  This is done by way of the Dekker memory barrier pattern
-(scenario 10 of [lwn-mb]_).  As the Dekker pattern requires two variables,
-this solution pairs ``vcpu->mode`` with ``vcpu->requests``.  Substituting
-them into the pattern gives::
-
-  CPU1                                    CPU2
-  =================                       =================
-  local_irq_disable();
-  WRITE_ONCE(vcpu->mode, IN_GUEST_MODE);  kvm_make_request(REQ, vcpu);
-  smp_mb();                               smp_mb();
-  if (kvm_request_pending(vcpu)) {        if (READ_ONCE(vcpu->mode) ==
-                                              IN_GUEST_MODE) {
-      ...abort guest entry...                 ...send IPI...
-  }                                       }
-
-As stated above, the IPI is only useful for VCPU threads in guest mode or
-that have already disabled interrupts.  This is why this specific case of
-the Dekker pattern has been extended to disable interrupts before setting
-``vcpu->mode`` to IN_GUEST_MODE.  WRITE_ONCE() and READ_ONCE() are used to
-pedantically implement the memory barrier pattern, guaranteeing the
-compiler doesn't interfere with ``vcpu->mode``'s carefully planned
-accesses.
-
-IPI Reduction
--------------
-
-As only one IPI is needed to get a VCPU to check for any/all requests,
-then they may be coalesced.  This is easily done by having the first IPI
-sending kick also change the VCPU mode to something !IN_GUEST_MODE.  The
-transitional state, EXITING_GUEST_MODE, is used for this purpose.
-
-Waiting for Acknowledgements
-----------------------------
-
-Some requests, those with the KVM_REQUEST_WAIT flag set, require IPIs to
-be sent, and the acknowledgements to be waited upon, even when the target
-VCPU threads are in modes other than IN_GUEST_MODE.  For example, one case
-is when a target VCPU thread is in READING_SHADOW_PAGE_TABLES mode, which
-is set after disabling interrupts.  To support these cases, the
-KVM_REQUEST_WAIT flag changes the condition for sending an IPI from
-checking that the VCPU is IN_GUEST_MODE to checking that it is not
-OUTSIDE_GUEST_MODE.
-
-Request-less VCPU Kicks
------------------------
-
-As the determination of whether or not to send an IPI depends on the
-two-variable Dekker memory barrier pattern, then it's clear that
-request-less VCPU kicks are almost never correct.  Without the assurance
-that a non-IPI generating kick will still result in an action by the
-receiving VCPU, as the final kvm_request_pending() check does for
-request-accompanying kicks, then the kick may not do anything useful at
-all.  If, for instance, a request-less kick was made to a VCPU that was
-just about to set its mode to IN_GUEST_MODE, meaning no IPI is sent, then
-the VCPU thread may continue its entry without actually having done
-whatever it was the kick was meant to initiate.
-
-One exception is x86's posted interrupt mechanism.  In this case, however,
-even the request-less VCPU kick is coupled with the same
-local_irq_disable() + smp_mb() pattern described above; the ON bit
-(Outstanding Notification) in the posted interrupt descriptor takes the
-role of ``vcpu->requests``.  When sending a posted interrupt, PIR.ON is
-set before reading ``vcpu->mode``; dually, in the VCPU thread,
-vmx_sync_pir_to_irr() reads PIR after setting ``vcpu->mode`` to
-IN_GUEST_MODE.
-
-Additional Considerations
-=========================
-
-Sleeping VCPUs
---------------
-
-VCPU threads may need to consider requests before and/or after calling
-functions that may put them to sleep, e.g. kvm_vcpu_block().  Whether they
-do or not, and, if they do, which requests need consideration, is
-architecture dependent.  kvm_vcpu_block() calls kvm_arch_vcpu_runnable()
-to check if it should awaken.  One reason to do so is to provide
-architectures a function where requests may be checked if necessary.
-
-Clearing Requests
------------------
-
-Generally it only makes sense for the receiving VCPU thread to clear a
-request.  However, in some circumstances, such as when the requesting
-thread and the receiving VCPU thread are executed serially, such as when
-they are the same thread, or when they are using some form of concurrency
-control to temporarily execute synchronously, then it's possible to know
-that the request may be cleared immediately, rather than waiting for the
-receiving VCPU thread to handle the request in VCPU RUN.  The only current
-examples of this are kvm_vcpu_block() calls made by VCPUs to block
-themselves.  A possible side-effect of that call is to make the
-KVM_REQ_UNHALT request, which may then be cleared immediately when the
-VCPU returns from the call.
-
-References
-==========
-
-.. [atomic-ops] Documentation/core-api/atomic_ops.rst
-.. [memory-barriers] Documentation/memory-barriers.txt
-.. [lwn-mb] https://lwn.net/Articles/573436/
diff --git a/Documentation/virtual/paravirt_ops.rst b/Documentation/virtual/paravirt_ops.rst
deleted file mode 100644 (file)
index 6b789d2..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============
-Paravirt_ops
-============
-
-Linux provides support for different hypervisor virtualization technologies.
-Historically different binary kernels would be required in order to support
-different hypervisors, this restriction was removed with pv_ops.
-Linux pv_ops is a virtualization API which enables support for different
-hypervisors. It allows each hypervisor to override critical operations and
-allows a single kernel binary to run on all supported execution environments
-including native machine -- without any hypervisors.
-
-pv_ops provides a set of function pointers which represent operations
-corresponding to low level critical instructions and high level
-functionalities in various areas. pv-ops allows for optimizations at run
-time by enabling binary patching of the low-ops critical operations
-at boot time.
-
-pv_ops operations are classified into three categories:
-
-- simple indirect call
-   These operations correspond to high level functionality where it is
-   known that the overhead of indirect call isn't very important.
-
-- indirect call which allows optimization with binary patch
-   Usually these operations correspond to low level critical instructions. They
-   are called frequently and are performance critical. The overhead is
-   very important.
-
-- a set of macros for hand written assembly code
-   Hand written assembly codes (.S files) also need paravirtualization
-   because they include sensitive instructions or some of code paths in
-   them are very performance critical.
diff --git a/Documentation/virtual/uml/UserModeLinux-HOWTO.txt b/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
deleted file mode 100644 (file)
index 87b80f5..0000000
+++ /dev/null
@@ -1,4589 +0,0 @@
-  User Mode Linux HOWTO
-  User Mode Linux Core Team
-  Mon Nov 18 14:16:16 EST 2002
-
-  This document describes the use and abuse of Jeff Dike's User Mode
-  Linux: a port of the Linux kernel as a normal Intel Linux process.
-  ______________________________________________________________________
-
-  Table of Contents
-
-  1. Introduction
-
-     1.1 How is User Mode Linux Different?
-     1.2 Why Would I Want User Mode Linux?
-
-  2. Compiling the kernel and modules
-
-     2.1 Compiling the kernel
-     2.2 Compiling and installing kernel modules
-     2.3 Compiling and installing uml_utilities
-
-  3. Running UML and logging in
-
-     3.1 Running UML
-     3.2 Logging in
-     3.3 Examples
-
-  4. UML on 2G/2G hosts
-
-     4.1 Introduction
-     4.2 The problem
-     4.3 The solution
-
-  5. Setting up serial lines and consoles
-
-     5.1 Specifying the device
-     5.2 Specifying the channel
-     5.3 Examples
-
-  6. Setting up the network
-
-     6.1 General setup
-     6.2 Userspace daemons
-     6.3 Specifying ethernet addresses
-     6.4 UML interface setup
-     6.5 Multicast
-     6.6 TUN/TAP with the uml_net helper
-     6.7 TUN/TAP with a preconfigured tap device
-     6.8 Ethertap
-     6.9 The switch daemon
-     6.10 Slip
-     6.11 Slirp
-     6.12 pcap
-     6.13 Setting up the host yourself
-
-  7. Sharing Filesystems between Virtual Machines
-
-     7.1 A warning
-     7.2 Using layered block devices
-     7.3 Note!
-     7.4 Another warning
-     7.5 uml_moo : Merging a COW file with its backing file
-
-  8. Creating filesystems
-
-     8.1 Create the filesystem file
-     8.2 Assign the file to a UML device
-     8.3 Creating and mounting the filesystem
-
-  9. Host file access
-
-     9.1 Using hostfs
-     9.2 hostfs as the root filesystem
-     9.3 Building hostfs
-
-  10. The Management Console
-     10.1 version
-     10.2 halt and reboot
-     10.3 config
-     10.4 remove
-     10.5 sysrq
-     10.6 help
-     10.7 cad
-     10.8 stop
-     10.9 go
-
-  11. Kernel debugging
-
-     11.1 Starting the kernel under gdb
-     11.2 Examining sleeping processes
-     11.3 Running ddd on UML
-     11.4 Debugging modules
-     11.5 Attaching gdb to the kernel
-     11.6 Using alternate debuggers
-
-  12. Kernel debugging examples
-
-     12.1 The case of the hung fsck
-     12.2 Episode 2: The case of the hung fsck
-
-  13. What to do when UML doesn't work
-
-     13.1 Strange compilation errors when you build from source
-     13.2 (obsolete)
-     13.3 A variety of panics and hangs with /tmp on a reiserfs  filesystem
-     13.4 The compile fails with errors about conflicting types for 'open', 'dup', and 'waitpid'
-     13.5 UML doesn't work when /tmp is an NFS filesystem
-     13.6 UML hangs on boot when compiled with gprof support
-     13.7 syslogd dies with a SIGTERM on startup
-     13.8 TUN/TAP networking doesn't work on a 2.4 host
-     13.9 You can network to the host but not to other machines on the net
-     13.10 I have no root and I want to scream
-     13.11 UML build conflict between ptrace.h and ucontext.h
-     13.12 The UML BogoMips is exactly half the host's BogoMips
-     13.13 When you run UML, it immediately segfaults
-     13.14 xterms appear, then immediately disappear
-     13.15 Any other panic, hang, or strange behavior
-
-  14. Diagnosing Problems
-
-     14.1 Case 1 : Normal kernel panics
-     14.2 Case 2 : Tracing thread panics
-     14.3 Case 3 : Tracing thread panics caused by other threads
-     14.4 Case 4 : Hangs
-
-  15. Thanks
-
-     15.1 Code and Documentation
-     15.2 Flushing out bugs
-     15.3 Buglets and clean-ups
-     15.4 Case Studies
-     15.5 Other contributions
-
-
-  ______________________________________________________________________
-
-  1.  Introduction
-
-  Welcome to User Mode Linux.  It's going to be fun.
-
-
-
-  1.1.  How is User Mode Linux Different?
-
-  Normally, the Linux Kernel talks straight to your hardware (video
-  card, keyboard, hard drives, etc), and any programs which run ask the
-  kernel to operate the hardware, like so:
-
-
-
-         +-----------+-----------+----+
-         | Process 1 | Process 2 | ...|
-         +-----------+-----------+----+
-         |       Linux Kernel         |
-         +----------------------------+
-         |         Hardware           |
-         +----------------------------+
-
-
-
-
-  The User Mode Linux Kernel is different; instead of talking to the
-  hardware, it talks to a `real' Linux kernel (called the `host kernel'
-  from now on), like any other program.  Programs can then run inside
-  User-Mode Linux as if they were running under a normal kernel, like
-  so:
-
-
-
-                     +----------------+
-                     | Process 2 | ...|
-         +-----------+----------------+
-         | Process 1 | User-Mode Linux|
-         +----------------------------+
-         |       Linux Kernel         |
-         +----------------------------+
-         |         Hardware           |
-         +----------------------------+
-
-
-
-
-
-  1.2.  Why Would I Want User Mode Linux?
-
-
-  1. If User Mode Linux crashes, your host kernel is still fine.
-
-  2. You can run a usermode kernel as a non-root user.
-
-  3. You can debug the User Mode Linux like any normal process.
-
-  4. You can run gprof (profiling) and gcov (coverage testing).
-
-  5. You can play with your kernel without breaking things.
-
-  6. You can use it as a sandbox for testing new apps.
-
-  7. You can try new development kernels safely.
-
-  8. You can run different distributions simultaneously.
-
-  9. It's extremely fun.
-
-
-
-
-
-  2.  Compiling the kernel and modules
-
-
-
-
-  2.1.  Compiling the kernel
-
-
-  Compiling the user mode kernel is just like compiling any other
-  kernel.  Let's go through the steps, using 2.4.0-prerelease (current
-  as of this writing) as an example:
-
-
-  1. Download the latest UML patch from
-
-     the download page <http://user-mode-linux.sourceforge.net/
-
-     In this example, the file is uml-patch-2.4.0-prerelease.bz2.
-
-
-  2. Download the matching kernel from your favourite kernel mirror,
-     such as:
-
-     ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2
-     <ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2>
-     .
-
-
-  3. Make a directory and unpack the kernel into it.
-
-
-
-       host%
-       mkdir ~/uml
-
-
-
-
-
-
-       host%
-       cd ~/uml
-
-
-
-
-
-
-       host%
-       tar -xzvf linux-2.4.0-prerelease.tar.bz2
-
-
-
-
-
-
-  4. Apply the patch using
-
-
-
-       host%
-       cd ~/uml/linux
-
-
-
-       host%
-       bzcat uml-patch-2.4.0-prerelease.bz2 | patch -p1
-
-
-
-
-
-
-  5. Run your favorite config; `make xconfig ARCH=um' is the most
-     convenient.  `make config ARCH=um' and 'make menuconfig ARCH=um'
-     will work as well.  The defaults will give you a useful kernel.  If
-     you want to change something, go ahead, it probably won't hurt
-     anything.
-
-
-     Note:  If the host is configured with a 2G/2G address space split
-     rather than the usual 3G/1G split, then the packaged UML binaries
-     will not run.  They will immediately segfault.  See ``UML on 2G/2G
-     hosts''  for the scoop on running UML on your system.
-
-
-
-  6. Finish with `make linux ARCH=um': the result is a file called
-     `linux' in the top directory of your source tree.
-
-  Make sure that you don't build this kernel in /usr/src/linux.  On some
-  distributions, /usr/include/asm is a link into this pool.  The user-
-  mode build changes the other end of that link, and things that include
-  <asm/anything.h> stop compiling.
-
-  The sources are also available from cvs at the project's cvs page,
-  which has directions on getting the sources. You can also browse the
-  CVS pool from there.
-
-  If you get the CVS sources, you will have to check them out into an
-  empty directory. You will then have to copy each file into the
-  corresponding directory in the appropriate kernel pool.
-
-  If you don't have the latest kernel pool, you can get the
-  corresponding user-mode sources with
-
-
-       host% cvs co -r v_2_3_x linux
-
-
-
-
-  where 'x' is the version in your pool. Note that you will not get the
-  bug fixes and enhancements that have gone into subsequent releases.
-
-
-  2.2.  Compiling and installing kernel modules
-
-  UML modules are built in the same way as the native kernel (with the
-  exception of the 'ARCH=um' that you always need for UML):
-
-
-       host% make modules ARCH=um
-
-
-
-
-  Any modules that you want to load into this kernel need to be built in
-  the user-mode pool.  Modules from the native kernel won't work.
-
-  You can install them by using ftp or something to copy them into the
-  virtual machine and dropping them into /lib/modules/`uname -r`.
-
-  You can also get the kernel build process to install them as follows:
-
-  1. with the kernel not booted, mount the root filesystem in the top
-     level of the kernel pool:
-
-
-       host% mount root_fs mnt -o loop
-
-
-
-
-
-
-  2. run
-
-
-       host%
-       make modules_install INSTALL_MOD_PATH=`pwd`/mnt ARCH=um
-
-
-
-
-
-
-  3. unmount the filesystem
-
-
-       host% umount mnt
-
-
-
-
-
-
-  4. boot the kernel on it
-
-
-  When the system is booted, you can use insmod as usual to get the
-  modules into the kernel.  A number of things have been loaded into UML
-  as modules, especially filesystems and network protocols and filters,
-  so most symbols which need to be exported probably already are.
-  However, if you do find symbols that need exporting, let  us
-  <http://user-mode-linux.sourceforge.net/>  know, and
-  they'll be "taken care of".
-
-
-
-  2.3.  Compiling and installing uml_utilities
-
-  Many features of the UML kernel require a user-space helper program,
-  so a uml_utilities package is distributed separately from the kernel
-  patch which provides these helpers. Included within this is:
-
-  o  port-helper - Used by consoles which connect to xterms or ports
-
-  o  tunctl - Configuration tool to create and delete tap devices
-
-  o  uml_net - Setuid binary for automatic tap device configuration
-
-  o  uml_switch - User-space virtual switch required for daemon
-     transport
-
-     The uml_utilities tree is compiled with:
-
-
-       host#
-       make && make install
-
-
-
-
-  Note that UML kernel patches may require a specific version of the
-  uml_utilities distribution. If you don't keep up with the mailing
-  lists, ensure that you have the latest release of uml_utilities if you
-  are experiencing problems with your UML kernel, particularly when
-  dealing with consoles or command-line switches to the helper programs
-
-
-
-
-
-
-
-
-  3.  Running UML and logging in
-
-
-
-  3.1.  Running UML
-
-  It runs on 2.2.15 or later, and all 2.4 kernels.
-
-
-  Booting UML is straightforward.  Simply run 'linux': it will try to
-  mount the file `root_fs' in the current directory.  You do not need to
-  run it as root.  If your root filesystem is not named `root_fs', then
-  you need to put a `ubd0=root_fs_whatever' switch on the linux command
-  line.
-
-
-  You will need a filesystem to boot UML from.  There are a number
-  available for download from  here  <http://user-mode-
-  linux.sourceforge.net/> .  There are also  several tools
-  <http://user-mode-linux.sourceforge.net/>  which can be
-  used to generate UML-compatible filesystem images from media.
-  The kernel will boot up and present you with a login prompt.
-
-
-  Note:  If the host is configured with a 2G/2G address space split
-  rather than the usual 3G/1G split, then the packaged UML binaries will
-  not run.  They will immediately segfault.  See ``UML on 2G/2G hosts''
-  for the scoop on running UML on your system.
-
-
-
-  3.2.  Logging in
-
-
-
-  The prepackaged filesystems have a root account with password 'root'
-  and a user account with password 'user'.  The login banner will
-  generally tell you how to log in.  So, you log in and you will find
-  yourself inside a little virtual machine. Our filesystems have a
-  variety of commands and utilities installed (and it is fairly easy to
-  add more), so you will have a lot of tools with which to poke around
-  the system.
-
-  There are a couple of other ways to log in:
-
-  o  On a virtual console
-
-
-
-     Each virtual console that is configured (i.e. the device exists in
-     /dev and /etc/inittab runs a getty on it) will come up in its own
-     xterm.  If you get tired of the xterms, read ``Setting up serial
-     lines and consoles''  to see how to attach the consoles to
-     something else, like host ptys.
-
-
-
-  o  Over the serial line
-
-
-     In the boot output, find a line that looks like:
-
-
-
-       serial line 0 assigned pty /dev/ptyp1
-
-
-
-
-  Attach your favorite terminal program to the corresponding tty.  I.e.
-  for minicom, the command would be
-
-
-       host% minicom -o -p /dev/ttyp1
-
-
-
-
-
-
-  o  Over the net
-
-
-     If the network is running, then you can telnet to the virtual
-     machine and log in to it.  See ``Setting up the network''  to learn
-     about setting up a virtual network.
-
-  When you're done using it, run halt, and the kernel will bring itself
-  down and the process will exit.
-
-
-  3.3.  Examples
-
-  Here are some examples of UML in action:
-
-  o  A login session <http://user-mode-linux.sourceforge.net/login.html>
-
-  o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
-
-
-
-
-
-
-
-  4.  UML on 2G/2G hosts
-
-
-
-
-  4.1.  Introduction
-
-
-  Most Linux machines are configured so that the kernel occupies the
-  upper 1G (0xc0000000 - 0xffffffff) of the 4G address space and
-  processes use the lower 3G (0x00000000 - 0xbfffffff).  However, some
-  machine are configured with a 2G/2G split, with the kernel occupying
-  the upper 2G (0x80000000 - 0xffffffff) and processes using the lower
-  2G (0x00000000 - 0x7fffffff).
-
-
-
-
-  4.2.  The problem
-
-
-  The prebuilt UML binaries on this site will not run on 2G/2G hosts
-  because UML occupies the upper .5G of the 3G process address space
-  (0xa0000000 - 0xbfffffff).  Obviously, on 2G/2G hosts, this is right
-  in the middle of the kernel address space, so UML won't even load - it
-  will immediately segfault.
-
-
-
-
-  4.3.  The solution
-
-
-  The fix for this is to rebuild UML from source after enabling
-  CONFIG_HOST_2G_2G (under 'General Setup').  This will cause UML to
-  load itself in the top .5G of that smaller process address space,
-  where it will run fine.  See ``Compiling the kernel and modules''  if
-  you need help building UML from source.
-
-
-
-
-
-
-
-
-
-
-  5.  Setting up serial lines and consoles
-
-
-  It is possible to attach UML serial lines and consoles to many types
-  of host I/O channels by specifying them on the command line.
-
-
-  You can attach them to host ptys, ttys, file descriptors, and ports.
-  This allows you to do things like
-
-  o  have a UML console appear on an unused host console,
-
-  o  hook two virtual machines together by having one attach to a pty
-     and having the other attach to the corresponding tty
-
-  o  make a virtual machine accessible from the net by attaching a
-     console to a port on the host.
-
-
-  The general format of the command line option is device=channel.
-
-
-
-  5.1.  Specifying the device
-
-  Devices are specified with "con" or "ssl" (console or serial line,
-  respectively), optionally with a device number if you are talking
-  about a specific device.
-
-
-  Using just "con" or "ssl" describes all of the consoles or serial
-  lines.  If you want to talk about console #3 or serial line #10, they
-  would be "con3" and "ssl10", respectively.
-
-
-  A specific device name will override a less general "con=" or "ssl=".
-  So, for example, you can assign a pty to each of the serial lines
-  except for the first two like this:
-
-
-        ssl=pty ssl0=tty:/dev/tty0 ssl1=tty:/dev/tty1
-
-
-
-
-  The specificity of the device name is all that matters; order on the
-  command line is irrelevant.
-
-
-
-  5.2.  Specifying the channel
-
-  There are a number of different types of channels to attach a UML
-  device to, each with a different way of specifying exactly what to
-  attach to.
-
-  o  pseudo-terminals - device=pty pts terminals - device=pts
-
-
-     This will cause UML to allocate a free host pseudo-terminal for the
-     device.  The terminal that it got will be announced in the boot
-     log.  You access it by attaching a terminal program to the
-     corresponding tty:
-
-  o  screen /dev/pts/n
-
-  o  screen /dev/ttyxx
-
-  o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
-     devices
-
-  o  kermit - start it up, 'open' the device, then 'connect'
-
-
-
-
-
-  o  terminals - device=tty:tty device file
-
-
-     This will make UML attach the device to the specified tty (i.e
-
-
-        con1=tty:/dev/tty3
-
-
-
-
-  will attach UML's console 1 to the host's /dev/tty3).  If the tty that
-  you specify is the slave end of a tty/pty pair, something else must
-  have already opened the corresponding pty in order for this to work.
-
-
-
-
-
-  o  xterms - device=xterm
-
-
-     UML will run an xterm and the device will be attached to it.
-
-
-
-
-
-  o  Port - device=port:port number
-
-
-     This will attach the UML devices to the specified host port.
-     Attaching console 1 to the host's port 9000 would be done like
-     this:
-
-
-        con1=port:9000
-
-
-
-
-  Attaching all the serial lines to that port would be done similarly:
-
-
-        ssl=port:9000
-
-
-
-
-  You access these devices by telnetting to that port.  Each active tel-
-  net session gets a different device.  If there are more telnets to a
-  port than UML devices attached to it, then the extra telnet sessions
-  will block until an existing telnet detaches, or until another device
-  becomes active (i.e. by being activated in /etc/inittab).
-
-  This channel has the advantage that you can both attach multiple UML
-  devices to it and know how to access them without reading the UML boot
-  log.  It is also unique in allowing access to a UML from remote
-  machines without requiring that the UML be networked.  This could be
-  useful in allowing public access to UMLs because they would be
-  accessible from the net, but wouldn't need any kind of network
-  filtering or access control because they would have no network access.
-
-
-  If you attach the main console to a portal, then the UML boot will
-  appear to hang.  In reality, it's waiting for a telnet to connect, at
-  which point the boot will proceed.
-
-
-
-
-
-  o  already-existing file descriptors - device=file descriptor
-
-
-     If you set up a file descriptor on the UML command line, you can
-     attach a UML device to it.  This is most commonly used to put the
-     main console back on stdin and stdout after assigning all the other
-     consoles to something else:
-
-
-        con0=fd:0,fd:1 con=pts
-
-
-
-
-
-
-
-
-  o  Nothing - device=null
-
-
-     This allows the device to be opened, in contrast to 'none', but
-     reads will block, and writes will succeed and the data will be
-     thrown out.
-
-
-
-
-
-  o  None - device=none
-
-
-     This causes the device to disappear.
-
-
-
-  You can also specify different input and output channels for a device
-  by putting a comma between them:
-
-
-        ssl3=tty:/dev/tty2,xterm
-
-
-
-
-  will cause serial line 3 to accept input on the host's /dev/tty2 and
-  display output on an xterm.  That's a silly example - the most common
-  use of this syntax is to reattach the main console to stdin and stdout
-  as shown above.
-
-
-  If you decide to move the main console away from stdin/stdout, the
-  initial boot output will appear in the terminal that you're running
-  UML in.  However, once the console driver has been officially
-  initialized, then the boot output will start appearing wherever you
-  specified that console 0 should be.  That device will receive all
-  subsequent output.
-
-
-
-  5.3.  Examples
-
-  There are a number of interesting things you can do with this
-  capability.
-
-
-  First, this is how you get rid of those bleeding console xterms by
-  attaching them to host ptys:
-
-
-        con=pty con0=fd:0,fd:1
-
-
-
-
-  This will make a UML console take over an unused host virtual console,
-  so that when you switch to it, you will see the UML login prompt
-  rather than the host login prompt:
-
-
-        con1=tty:/dev/tty6
-
-
-
-
-  You can attach two virtual machines together with what amounts to a
-  serial line as follows:
-
-  Run one UML with a serial line attached to a pty -
-
-
-        ssl1=pty
-
-
-
-
-  Look at the boot log to see what pty it got (this example will assume
-  that it got /dev/ptyp1).
-
-  Boot the other UML with a serial line attached to the corresponding
-  tty -
-
-
-        ssl1=tty:/dev/ttyp1
-
-
-
-
-  Log in, make sure that it has no getty on that serial line, attach a
-  terminal program like minicom to it, and you should see the login
-  prompt of the other virtual machine.
-
-
-  6.  Setting up the network
-
-
-
-  This page describes how to set up the various transports and to
-  provide a UML instance with network access to the host, other machines
-  on the local net, and the rest of the net.
-
-
-  As of 2.4.5, UML networking has been completely redone to make it much
-  easier to set up, fix bugs, and add new features.
-
-
-  There is a new helper, uml_net, which does the host setup that
-  requires root privileges.
-
-
-  There are currently five transport types available for a UML virtual
-  machine to exchange packets with other hosts:
-
-  o  ethertap
-
-  o  TUN/TAP
-
-  o  Multicast
-
-  o  a switch daemon
-
-  o  slip
-
-  o  slirp
-
-  o  pcap
-
-     The TUN/TAP, ethertap, slip, and slirp transports allow a UML
-     instance to exchange packets with the host.  They may be directed
-     to the host or the host may just act as a router to provide access
-     to other physical or virtual machines.
-
-
-  The pcap transport is a synthetic read-only interface, using the
-  libpcap binary to collect packets from interfaces on the host and
-  filter them.  This is useful for building preconfigured traffic
-  monitors or sniffers.
-
-
-  The daemon and multicast transports provide a completely virtual
-  network to other virtual machines.  This network is completely
-  disconnected from the physical network unless one of the virtual
-  machines on it is acting as a gateway.
-
-
-  With so many host transports, which one should you use?  Here's when
-  you should use each one:
-
-  o  ethertap - if you want access to the host networking and it is
-     running 2.2
-
-  o  TUN/TAP - if you want access to the host networking and it is
-     running 2.4.  Also, the TUN/TAP transport is able to use a
-     preconfigured device, allowing it to avoid using the setuid uml_net
-     helper, which is a security advantage.
-
-  o  Multicast - if you want a purely virtual network and you don't want
-     to set up anything but the UML
-
-  o  a switch daemon - if you want a purely virtual network and you
-     don't mind running the daemon in order to get somewhat better
-     performance
-
-  o  slip - there is no particular reason to run the slip backend unless
-     ethertap and TUN/TAP are just not available for some reason
-
-  o  slirp - if you don't have root access on the host to setup
-     networking, or if you don't want to allocate an IP to your UML
-
-  o  pcap - not much use for actual network connectivity, but great for
-     monitoring traffic on the host
-
-     Ethertap is available on 2.4 and works fine.  TUN/TAP is preferred
-     to it because it has better performance and ethertap is officially
-     considered obsolete in 2.4.  Also, the root helper only needs to
-     run occasionally for TUN/TAP, rather than handling every packet, as
-     it does with ethertap.  This is a slight security advantage since
-     it provides fewer opportunities for a nasty UML user to somehow
-     exploit the helper's root privileges.
-
-
-  6.1.  General setup
-
-  First, you must have the virtual network enabled in your UML.  If are
-  running a prebuilt kernel from this site, everything is already
-  enabled.  If you build the kernel yourself, under the "Network device
-  support" menu, enable "Network device support", and then the three
-  transports.
-
-
-  The next step is to provide a network device to the virtual machine.
-  This is done by describing it on the kernel command line.
-
-  The general format is
-
-
-       eth <n> = <transport> , <transport args>
-
-
-
-
-  For example, a virtual ethernet device may be attached to a host
-  ethertap device as follows:
-
-
-       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
-
-
-
-
-  This sets up eth0 inside the virtual machine to attach itself to the
-  host /dev/tap0, assigns it an ethernet address, and assigns the host
-  tap0 interface an IP address.
-
-
-
-  Note that the IP address you assign to the host end of the tap device
-  must be different than the IP you assign to the eth device inside UML.
-  If you are short on IPs and don't want to consume two per UML, then
-  you can reuse the host's eth IP address for the host ends of the tap
-  devices.  Internally, the UMLs must still get unique IPs for their eth
-  devices.  You can also give the UMLs non-routable IPs (192.168.x.x or
-  10.x.x.x) and have the host masquerade them.  This will let outgoing
-  connections work, but incoming connections won't without more work,
-  such as port forwarding from the host.
-  Also note that when you configure the host side of an interface, it is
-  only acting as a gateway.  It will respond to pings sent to it
-  locally, but is not useful to do that since it's a host interface.
-  You are not talking to the UML when you ping that interface and get a
-  response.
-
-
-  You can also add devices to a UML and remove them at runtime.  See the
-  ``The Management Console''  page for details.
-
-
-  The sections below describe this in more detail.
-
-
-  Once you've decided how you're going to set up the devices, you boot
-  UML, log in, configure the UML side of the devices, and set up routes
-  to the outside world.  At that point, you will be able to talk to any
-  other machines, physical or virtual, on the net.
-
-
-  If ifconfig inside UML fails and the network refuses to come up, run
-  tell you what went wrong.
-
-
-
-  6.2.  Userspace daemons
-
-  You will likely need the setuid helper, or the switch daemon, or both.
-  They are both installed with the RPM and deb, so if you've installed
-  either, you can skip the rest of this section.
-
-
-  If not, then you need to check them out of CVS, build them, and
-  install them.  The helper is uml_net, in CVS /tools/uml_net, and the
-  daemon is uml_switch, in CVS /tools/uml_router.  They are both built
-  with a plain 'make'.  Both need to be installed in a directory that's
-  in your path - /usr/bin is recommend.  On top of that, uml_net needs
-  to be setuid root.
-
-
-
-  6.3.  Specifying ethernet addresses
-
-  Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
-  allow you to specify hardware addresses for the virtual ethernet
-  devices.  This is generally not necessary.  If you don't have a
-  specific reason to do it, you probably shouldn't.  If one is not
-  specified on the command line, the driver will assign one based on the
-  device IP address.  It will provide the address fe:fd:nn:nn:nn:nn
-  where nn.nn.nn.nn is the device IP address.  This is nearly always
-  sufficient to guarantee a unique hardware address for the device.  A
-  couple of exceptions are:
-
-  o  Another set of virtual ethernet devices are on the same network and
-     they are assigned hardware addresses using a different scheme which
-     may conflict with the UML IP address-based scheme
-
-  o  You aren't going to use the device for IP networking, so you don't
-     assign the device an IP address
-
-     If you let the driver provide the hardware address, you should make
-     sure that the device IP address is known before the interface is
-     brought up.  So, inside UML, this will guarantee that:
-
-
-
-  UML#
-  ifconfig eth0 192.168.0.250 up
-
-
-
-
-  If you decide to assign the hardware address yourself, make sure that
-  the first byte of the address is even.  Addresses with an odd first
-  byte are broadcast addresses, which you don't want assigned to a
-  device.
-
-
-
-  6.4.  UML interface setup
-
-  Once the network devices have been described on the command line, you
-  should boot UML and log in.
-
-
-  The first thing to do is bring the interface up:
-
-
-       UML# ifconfig ethn ip-address up
-
-
-
-
-  You should be able to ping the host at this point.
-
-
-  To reach the rest of the world, you should set a default route to the
-  host:
-
-
-       UML# route add default gw host ip
-
-
-
-
-  Again, with host ip of 192.168.0.4:
-
-
-       UML# route add default gw 192.168.0.4
-
-
-
-
-  This page used to recommend setting a network route to your local net.
-  This is wrong, because it will cause UML to try to figure out hardware
-  addresses of the local machines by arping on the interface to the
-  host.  Since that interface is basically a single strand of ethernet
-  with two nodes on it (UML and the host) and arp requests don't cross
-  networks, they will fail to elicit any responses.  So, what you want
-  is for UML to just blindly throw all packets at the host and let it
-  figure out what to do with them, which is what leaving out the network
-  route and adding the default route does.
-
-
-  Note: If you can't communicate with other hosts on your physical
-  ethernet, it's probably because of a network route that's
-  automatically set up.  If you run 'route -n' and see a route that
-  looks like this:
-
-
-
-
-  Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
-  192.168.0.0     0.0.0.0         255.255.255.0   U     0      0      0   eth0
-
-
-
-
-  with a mask that's not 255.255.255.255, then replace it with a route
-  to your host:
-
-
-       UML#
-       route del -net 192.168.0.0 dev eth0 netmask 255.255.255.0
-
-
-
-
-
-
-       UML#
-       route add -host 192.168.0.4 dev eth0
-
-
-
-
-  This, plus the default route to the host, will allow UML to exchange
-  packets with any machine on your ethernet.
-
-
-
-  6.5.  Multicast
-
-  The simplest way to set up a virtual network between multiple UMLs is
-  to use the mcast transport.  This was written by Harald Welte and is
-  present in UML version 2.4.5-5um and later.  Your system must have
-  multicast enabled in the kernel and there must be a multicast-capable
-  network device on the host.  Normally, this is eth0, but if there is
-  no ethernet card on the host, then you will likely get strange error
-  messages when you bring the device up inside UML.
-
-
-  To use it, run two UMLs with
-
-
-        eth0=mcast
-
-
-
-
-  on their command lines.  Log in, configure the ethernet device in each
-  machine with different IP addresses:
-
-
-       UML1# ifconfig eth0 192.168.0.254
-
-
-
-
-
-
-       UML2# ifconfig eth0 192.168.0.253
-
-
-
-
-  and they should be able to talk to each other.
-
-  The full set of command line options for this transport are
-
-
-
-       ethn=mcast,ethernet address,multicast
-       address,multicast port,ttl
-
-
-
-
-  Harald's original README is here <http://user-mode-linux.source-
-  forge.net/>  and explains these in detail, as well as
-  some other issues.
-
-  There is also a related point-to-point only "ucast" transport.
-  This is useful when your network does not support multicast, and
-  all network connections are simple point to point links.
-
-  The full set of command line options for this transport are
-
-
-       ethn=ucast,ethernet address,remote address,listen port,remote port
-
-
-
-
-  6.6.  TUN/TAP with the uml_net helper
-
-  TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
-  host.  The TUN/TAP backend has been in UML since 2.4.9-3um.
-
-
-  The easiest way to get up and running is to let the setuid uml_net
-  helper do the host setup for you.  This involves insmod-ing the tun.o
-  module if necessary, configuring the device, and setting up IP
-  forwarding, routing, and proxy arp.  If you are new to UML networking,
-  do this first.  If you're concerned about the security implications of
-  the setuid helper, use it to get up and running, then read the next
-  section to see how to have UML use a preconfigured tap device, which
-  avoids the use of uml_net.
-
-
-  If you specify an IP address for the host side of the device, the
-  uml_net helper will do all necessary setup on the host - the only
-  requirement is that TUN/TAP be available, either built in to the host
-  kernel or as the tun.o module.
-
-  The format of the command line switch to attach a device to a TUN/TAP
-  device is
-
-
-       eth <n> =tuntap,,, <IP address>
-
-
-
-
-  For example, this argument will attach the UML's eth0 to the next
-  available tap device and assign an ethernet address to it based on its
-  IP address
-
-
-       eth0=tuntap,,,192.168.0.254
-
-
-
-
-
-
-  Note that the IP address that must be used for the eth device inside
-  UML is fixed by the routing and proxy arp that is set up on the
-  TUN/TAP device on the host.  You can use a different one, but it won't
-  work because reply packets won't reach the UML.  This is a feature.
-  It prevents a nasty UML user from doing things like setting the UML IP
-  to the same as the network's nameserver or mail server.
-
-
-  There are a couple potential problems with running the TUN/TAP
-  transport on a 2.4 host kernel
-
-  o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
-     kernel or use the ethertap transport.
-
-  o  With an upgraded kernel, TUN/TAP may fail with
-
-
-       File descriptor in bad state
-
-
-
-
-  This is due to a header mismatch between the upgraded kernel and the
-  kernel that was originally installed on the machine.  The fix is to
-  make sure that /usr/src/linux points to the headers for the running
-  kernel.
-
-  These were pointed out by Tim Robinson <timro at trkr dot net> in
-  <http://www.geocrawler.com/> name="this uml-
-  user post"> .
-
-
-
-  6.7.  TUN/TAP with a preconfigured tap device
-
-  If you prefer not to have UML use uml_net (which is somewhat
-  insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
-  beforehand.  The setup needs to be done as root, but once that's done,
-  there is no need for root assistance.  Setting up the device is done
-  as follows:
-
-  o  Create the device with tunctl (available from the UML utilities
-     tarball)
-
-
-
-
-       host#  tunctl -u uid
-
-
-
-
-  where uid is the user id or username that UML will be run as.  This
-  will tell you what device was created.
-
-  o  Configure the device IP (change IP addresses and device name to
-     suit)
-
-
-
-
-       host#  ifconfig tap0 192.168.0.254 up
-
-
-
-
-
-  o  Set up routing and arping if desired - this is my recipe, there are
-     other ways of doing the same thing
-
-
-       host#
-       bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
-
-       host#
-       route add -host 192.168.0.253 dev tap0
-
-
-
-
-
-
-       host#
-       bash -c 'echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp'
-
-
-
-
-
-
-       host#
-       arp -Ds 192.168.0.253 eth0 pub
-
-
-
-
-  Note that this must be done every time the host boots - this configu-
-  ration is not stored across host reboots.  So, it's probably a good
-  idea to stick it in an rc file.  An even better idea would be a little
-  utility which reads the information from a config file and sets up
-  devices at boot time.
-
-  o  Rather than using up two IPs and ARPing for one of them, you can
-     also provide direct access to your LAN by the UML by using a
-     bridge.
-
-
-       host#
-       brctl addbr br0
-
-
-
-
-
-
-       host#
-       ifconfig eth0 0.0.0.0 promisc up
-
-
-
-
-
-
-       host#
-       ifconfig tap0 0.0.0.0 promisc up
-
-
-
-
-
-
-       host#
-       ifconfig br0 192.168.0.1 netmask 255.255.255.0 up
-
-
-
-
-
-
-
-  host#
-  brctl stp br0 off
-
-
-
-
-
-
-       host#
-       brctl setfd br0 1
-
-
-
-
-
-
-       host#
-       brctl sethello br0 1
-
-
-
-
-
-
-       host#
-       brctl addif br0 eth0
-
-
-
-
-
-
-       host#
-       brctl addif br0 tap0
-
-
-
-
-  Note that 'br0' should be setup using ifconfig with the existing IP
-  address of eth0, as eth0 no longer has its own IP.
-
-  o
-
-
-     Also, the /dev/net/tun device must be writable by the user running
-     UML in order for the UML to use the device that's been configured
-     for it.  The simplest thing to do is
-
-
-       host#  chmod 666 /dev/net/tun
-
-
-
-
-  Making it world-writable looks bad, but it seems not to be
-  exploitable as a security hole.  However, it does allow anyone to cre-
-  ate useless tap devices (useless because they can't configure them),
-  which is a DOS attack.  A somewhat more secure alternative would to be
-  to create a group containing all the users who have preconfigured tap
-  devices and chgrp /dev/net/tun to that group with mode 664 or 660.
-
-
-  o  Once the device is set up, run UML with 'eth0=tuntap,device name'
-     (i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
-     mconsole config command).
-
-  o  Bring the eth device up in UML and you're in business.
-
-     If you don't want that tap device any more, you can make it non-
-     persistent with
-
-
-       host#  tunctl -d tap device
-
-
-
-
-  Finally, tunctl has a -b (for brief mode) switch which causes it to
-  output only the name of the tap device it created.  This makes it
-  suitable for capture by a script:
-
-
-       host#  TAP=`tunctl -u 1000 -b`
-
-
-
-
-
-
-  6.8.  Ethertap
-
-  Ethertap is the general mechanism on 2.2 for userspace processes to
-  exchange packets with the kernel.
-
-
-
-  To use this transport, you need to describe the virtual network device
-  on the UML command line.  The general format for this is
-
-
-       eth <n> =ethertap, <device> , <ethernet address> , <tap IP address>
-
-
-
-
-  So, the previous example
-
-
-       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
-
-
-
-
-  attaches the UML eth0 device to the host /dev/tap0, assigns it the
-  ethernet address fe:fd:0:0:0:1, and assigns the IP address
-  192.168.0.254 to the tap device.
-
-
-
-  The tap device is mandatory, but the others are optional.  If the
-  ethernet address is omitted, one will be assigned to it.
-
-
-  The presence of the tap IP address will cause the helper to run and do
-  whatever host setup is needed to allow the virtual machine to
-  communicate with the outside world.  If you're not sure you know what
-  you're doing, this is the way to go.
-
-
-  If it is absent, then you must configure the tap device and whatever
-  arping and routing you will need on the host.  However, even in this
-  case, the uml_net helper still needs to be in your path and it must be
-  setuid root if you're not running UML as root.  This is because the
-  tap device doesn't support SIGIO, which UML needs in order to use
-  something as a source of input.  So, the helper is used as a
-  convenient asynchronous IO thread.
-
-  If you're using the uml_net helper, you can ignore the following host
-  setup - uml_net will do it for you.  You just need to make sure you
-  have ethertap available, either built in to the host kernel or
-  available as a module.
-
-
-  If you want to set things up yourself, you need to make sure that the
-  appropriate /dev entry exists.  If it doesn't, become root and create
-  it as follows:
-
-
-       mknod /dev/tap <minor>  c 36  <minor>  + 16
-
-
-
-
-  For example, this is how to create /dev/tap0:
-
-
-       mknod /dev/tap0 c 36 0 + 16
-
-
-
-
-  You also need to make sure that the host kernel has ethertap support.
-  If ethertap is enabled as a module, you apparently need to insmod
-  ethertap once for each ethertap device you want to enable.  So,
-
-
-       host#
-       insmod ethertap
-
-
-
-
-  will give you the tap0 interface.  To get the tap1 interface, you need
-  to run
-
-
-       host#
-       insmod ethertap unit=1 -o ethertap1
-
-
-
-
-
-
-
-  6.9.  The switch daemon
-
-  Note: This is the daemon formerly known as uml_router, but which was
-  renamed so the network weenies of the world would stop growling at me.
-
-
-  The switch daemon, uml_switch, provides a mechanism for creating a
-  totally virtual network.  By default, it provides no connection to the
-  host network (but see -tap, below).
-
-
-  The first thing you need to do is run the daemon.  Running it with no
-  arguments will make it listen on a default pair of unix domain
-  sockets.
-
-
-  If you want it to listen on a different pair of sockets, use
-
-
-        -unix control socket data socket
-
-
-
-
-
-  If you want it to act as a hub rather than a switch, use
-
-
-        -hub
-
-
-
-
-
-  If you want the switch to be connected to host networking (allowing
-  the umls to get access to the outside world through the host), use
-
-
-        -tap tap0
-
-
-
-
-
-  Note that the tap device must be preconfigured (see "TUN/TAP with a
-  preconfigured tap device", above).  If you're using a different tap
-  device than tap0, specify that instead of tap0.
-
-
-  uml_switch can be backgrounded as follows
-
-
-       host%
-       uml_switch [ options ] < /dev/null > /dev/null
-
-
-
-
-  The reason it doesn't background by default is that it listens to
-  stdin for EOF.  When it sees that, it exits.
-
-
-  The general format of the kernel command line switch is
-
-
-
-       ethn=daemon,ethernet address,socket
-       type,control socket,data socket
-
-
-
-
-  You can leave off everything except the 'daemon'.  You only need to
-  specify the ethernet address if the one that will be assigned to it
-  isn't acceptable for some reason.  The rest of the arguments describe
-  how to communicate with the daemon.  You should only specify them if
-  you told the daemon to use different sockets than the default.  So, if
-  you ran the daemon with no arguments, running the UML on the same
-  machine with
-       eth0=daemon
-
-
-
-
-  will cause the eth0 driver to attach itself to the daemon correctly.
-
-
-
-  6.10.  Slip
-
-  Slip is another, less general, mechanism for a process to communicate
-  with the host networking.  In contrast to the ethertap interface,
-  which exchanges ethernet frames with the host and can be used to
-  transport any higher-level protocol, it can only be used to transport
-  IP.
-
-
-  The general format of the command line switch is
-
-
-
-       ethn=slip,slip IP
-
-
-
-
-  The slip IP argument is the IP address that will be assigned to the
-  host end of the slip device.  If it is specified, the helper will run
-  and will set up the host so that the virtual machine can reach it and
-  the rest of the network.
-
-
-  There are some oddities with this interface that you should be aware
-  of.  You should only specify one slip device on a given virtual
-  machine, and its name inside UML will be 'umn', not 'eth0' or whatever
-  you specified on the command line.  These problems will be fixed at
-  some point.
-
-
-
-  6.11.  Slirp
-
-  slirp uses an external program, usually /usr/bin/slirp, to provide IP
-  only networking connectivity through the host. This is similar to IP
-  masquerading with a firewall, although the translation is performed in
-  user-space, rather than by the kernel.  As slirp does not set up any
-  interfaces on the host, or changes routing, slirp does not require
-  root access or setuid binaries on the host.
-
-
-  The general format of the command line switch for slirp is:
-
-
-
-       ethn=slirp,ethernet address,slirp path
-
-
-
-
-  The ethernet address is optional, as UML will set up the interface
-  with an ethernet address based upon the initial IP address of the
-  interface.  The slirp path is generally /usr/bin/slirp, although it
-  will depend on distribution.
-
-
-  The slirp program can have a number of options passed to the command
-  line and we can't add them to the UML command line, as they will be
-  parsed incorrectly.  Instead, a wrapper shell script can be written or
-  the options inserted into the  /.slirprc file.  More information on
-  all of the slirp options can be found in its man pages.
-
-
-  The eth0 interface on UML should be set up with the IP 10.2.0.15,
-  although you can use anything as long as it is not used by a network
-  you will be connecting to. The default route on UML should be set to
-  use
-
-
-       UML#
-       route add default dev eth0
-
-
-
-
-  slirp provides a number of useful IP addresses which can be used by
-  UML, such as 10.0.2.3 which is an alias for the DNS server specified
-  in /etc/resolv.conf on the host or the IP given in the 'dns' option
-  for slirp.
-
-
-  Even with a baudrate setting higher than 115200, the slirp connection
-  is limited to 115200. If you need it to go faster, the slirp binary
-  needs to be compiled with FULL_BOLT defined in config.h.
-
-
-
-  6.12.  pcap
-
-  The pcap transport is attached to a UML ethernet device on the command
-  line or with uml_mconsole with the following syntax:
-
-
-
-       ethn=pcap,host interface,filter
-       expression,option1,option2
-
-
-
-
-  The expression and options are optional.
-
-
-  The interface is whatever network device on the host you want to
-  sniff.  The expression is a pcap filter expression, which is also what
-  tcpdump uses, so if you know how to specify tcpdump filters, you will
-  use the same expressions here.  The options are up to two of
-  'promisc', control whether pcap puts the host interface into
-  promiscuous mode. 'optimize' and 'nooptimize' control whether the pcap
-  expression optimizer is used.
-
-
-  Example:
-
-
-
-       eth0=pcap,eth0,tcp
-
-       eth1=pcap,eth0,!tcp
-
-
-
-  will cause the UML eth0 to emit all tcp packets on the host eth0 and
-  the UML eth1 to emit all non-tcp packets on the host eth0.
-
-
-
-  6.13.  Setting up the host yourself
-
-  If you don't specify an address for the host side of the ethertap or
-  slip device, UML won't do any setup on the host.  So this is what is
-  needed to get things working (the examples use a host-side IP of
-  192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
-  own network):
-
-  o  The device needs to be configured with its IP address.  Tap devices
-     are also configured with an mtu of 1484.  Slip devices are
-     configured with a point-to-point address pointing at the UML ip
-     address.
-
-
-       host#  ifconfig tap0 arp mtu 1484 192.168.0.251 up
-
-
-
-
-
-
-       host#
-       ifconfig sl0 192.168.0.251 pointopoint 192.168.0.250 up
-
-
-
-
-
-  o  If a tap device is being set up, a route is set to the UML IP.
-
-
-       UML# route add -host 192.168.0.250 gw 192.168.0.251
-
-
-
-
-
-  o  To allow other hosts on your network to see the virtual machine,
-     proxy arp is set up for it.
-
-
-       host#  arp -Ds 192.168.0.250 eth0 pub
-
-
-
-
-
-  o  Finally, the host is set up to route packets.
-
-
-       host#  echo 1 > /proc/sys/net/ipv4/ip_forward
-
-
-
-
-
-
-
-
-
-
-  7.  Sharing Filesystems between Virtual Machines
-
-
-
-
-  7.1.  A warning
-
-  Don't attempt to share filesystems simply by booting two UMLs from the
-  same file.  That's the same thing as booting two physical machines
-  from a shared disk.  It will result in filesystem corruption.
-
-
-
-  7.2.  Using layered block devices
-
-  The way to share a filesystem between two virtual machines is to use
-  the copy-on-write (COW) layering capability of the ubd block driver.
-  As of 2.4.6-2um, the driver supports layering a read-write private
-  device over a read-only shared device.  A machine's writes are stored
-  in the private device, while reads come from either device - the
-  private one if the requested block is valid in it, the shared one if
-  not.  Using this scheme, the majority of data which is unchanged is
-  shared between an arbitrary number of virtual machines, each of which
-  has a much smaller file containing the changes that it has made.  With
-  a large number of UMLs booting from a large root filesystem, this
-  leads to a huge disk space saving.  It will also help performance,
-  since the host will be able to cache the shared data using a much
-  smaller amount of memory, so UML disk requests will be served from the
-  host's memory rather than its disks.
-
-
-
-
-  To add a copy-on-write layer to an existing block device file, simply
-  add the name of the COW file to the appropriate ubd switch:
-
-
-        ubd0=root_fs_cow,root_fs_debian_22
-
-
-
-
-  where 'root_fs_cow' is the private COW file and 'root_fs_debian_22' is
-  the existing shared filesystem.  The COW file need not exist.  If it
-  doesn't, the driver will create and initialize it.  Once the COW file
-  has been initialized, it can be used on its own on the command line:
-
-
-        ubd0=root_fs_cow
-
-
-
-
-  The name of the backing file is stored in the COW file header, so it
-  would be redundant to continue specifying it on the command line.
-
-
-
-  7.3.  Note!
-
-  When checking the size of the COW file in order to see the gobs of
-  space that you're saving, make sure you use 'ls -ls' to see the actual
-  disk consumption rather than the length of the file.  The COW file is
-  sparse, so the length will be very different from the disk usage.
-  Here is a 'ls -l' of a COW file and backing file from one boot and
-  shutdown:
-       host% ls -l cow.debian debian2.2
-       -rw-r--r--    1 jdike    jdike    492504064 Aug  6 21:16 cow.debian
-       -rwxrw-rw-    1 jdike    jdike    537919488 Aug  6 20:42 debian2.2
-
-
-
-
-  Doesn't look like much saved space, does it?  Well, here's 'ls -ls':
-
-
-       host% ls -ls cow.debian debian2.2
-          880 -rw-r--r--    1 jdike    jdike    492504064 Aug  6 21:16 cow.debian
-       525832 -rwxrw-rw-    1 jdike    jdike    537919488 Aug  6 20:42 debian2.2
-
-
-
-
-  Now, you can see that the COW file has less than a meg of disk, rather
-  than 492 meg.
-
-
-
-  7.4.  Another warning
-
-  Once a filesystem is being used as a readonly backing file for a COW
-  file, do not boot directly from it or modify it in any way.  Doing so
-  will invalidate any COW files that are using it.  The mtime and size
-  of the backing file are stored in the COW file header at its creation,
-  and they must continue to match.  If they don't, the driver will
-  refuse to use the COW file.
-
-
-
-
-  If you attempt to evade this restriction by changing either the
-  backing file or the COW header by hand, you will get a corrupted
-  filesystem.
-
-
-
-
-  Among other things, this means that upgrading the distribution in a
-  backing file and expecting that all of the COW files using it will see
-  the upgrade will not work.
-
-
-
-
-  7.5.  uml_moo : Merging a COW file with its backing file
-
-  Depending on how you use UML and COW devices, it may be advisable to
-  merge the changes in the COW file into the backing file every once in
-  a while.
-
-
-
-
-  The utility that does this is uml_moo.  Its usage is
-
-
-       host% uml_moo COW file new backing file
-
-
-
-
-  There's no need to specify the backing file since that information is
-  already in the COW file header.  If you're paranoid, boot the new
-  merged file, and if you're happy with it, move it over the old backing
-  file.
-
-
-
-
-  uml_moo creates a new backing file by default as a safety measure.  It
-  also has a destructive merge option which will merge the COW file
-  directly into its current backing file.  This is really only usable
-  when the backing file only has one COW file associated with it.  If
-  there are multiple COWs associated with a backing file, a -d merge of
-  one of them will invalidate all of the others.  However, it is
-  convenient if you're short of disk space, and it should also be
-  noticeably faster than a non-destructive merge.
-
-
-
-
-  uml_moo is installed with the UML deb and RPM.  If you didn't install
-  UML from one of those packages, you can also get it from the UML
-  utilities <http://user-mode-linux.sourceforge.net/
-  utilities>  tar file in tools/moo.
-
-
-
-
-
-
-
-
-  8.  Creating filesystems
-
-
-  You may want to create and mount new UML filesystems, either because
-  your root filesystem isn't large enough or because you want to use a
-  filesystem other than ext2.
-
-
-  This was written on the occasion of reiserfs being included in the
-  2.4.1 kernel pool, and therefore the 2.4.1 UML, so the examples will
-  talk about reiserfs.  This information is generic, and the examples
-  should be easy to translate to the filesystem of your choice.
-
-
-  8.1.  Create the filesystem file
-
-  dd is your friend.  All you need to do is tell dd to create an empty
-  file of the appropriate size.  I usually make it sparse to save time
-  and to avoid allocating disk space until it's actually used.  For
-  example, the following command will create a sparse 100 meg file full
-  of zeroes.
-
-
-       host%
-       dd if=/dev/zero of=new_filesystem seek=100 count=1 bs=1M
-
-
-
-
-
-
-  8.2.  Assign the file to a UML device
-
-  Add an argument like the following to the UML command line:
-
-  ubd4=new_filesystem
-
-
-
-
-  making sure that you use an unassigned ubd device number.
-
-
-
-  8.3.  Creating and mounting the filesystem
-
-  Make sure that the filesystem is available, either by being built into
-  the kernel, or available as a module, then boot up UML and log in.  If
-  the root filesystem doesn't have the filesystem utilities (mkfs, fsck,
-  etc), then get them into UML by way of the net or hostfs.
-
-
-  Make the new filesystem on the device assigned to the new file:
-
-
-       host#  mkreiserfs /dev/ubd/4
-
-
-       <----------- MKREISERFSv2 ----------->
-
-       ReiserFS version 3.6.25
-       Block size 4096 bytes
-       Block count 25856
-       Used blocks 8212
-               Journal - 8192 blocks (18-8209), journal header is in block 8210
-               Bitmaps: 17
-               Root block 8211
-       Hash function "r5"
-       ATTENTION: ALL DATA WILL BE LOST ON '/dev/ubd/4'! (y/n)y
-       journal size 8192 (from 18)
-       Initializing journal - 0%....20%....40%....60%....80%....100%
-       Syncing..done.
-
-
-
-
-  Now, mount it:
-
-
-       UML#
-       mount /dev/ubd/4 /mnt
-
-
-
-
-  and you're in business.
-
-
-
-
-
-
-
-
-
-  9.  Host file access
-
-
-  If you want to access files on the host machine from inside UML, you
-  can treat it as a separate machine and either nfs mount directories
-  from the host or copy files into the virtual machine with scp or rcp.
-  However, since UML is running on the host, it can access those
-  files just like any other process and make them available inside the
-  virtual machine without needing to use the network.
-
-
-  This is now possible with the hostfs virtual filesystem.  With it, you
-  can mount a host directory into the UML filesystem and access the
-  files contained in it just as you would on the host.
-
-
-  9.1.  Using hostfs
-
-  To begin with, make sure that hostfs is available inside the virtual
-  machine with
-
-
-       UML# cat /proc/filesystems
-
-
-
-  .  hostfs should be listed.  If it's not, either rebuild the kernel
-  with hostfs configured into it or make sure that hostfs is built as a
-  module and available inside the virtual machine, and insmod it.
-
-
-  Now all you need to do is run mount:
-
-
-       UML# mount none /mnt/host -t hostfs
-
-
-
-
-  will mount the host's / on the virtual machine's /mnt/host.
-
-
-  If you don't want to mount the host root directory, then you can
-  specify a subdirectory to mount with the -o switch to mount:
-
-
-       UML# mount none /mnt/home -t hostfs -o /home
-
-
-
-
-  will mount the hosts's /home on the virtual machine's /mnt/home.
-
-
-
-  9.2.  hostfs as the root filesystem
-
-  It's possible to boot from a directory hierarchy on the host using
-  hostfs rather than using the standard filesystem in a file.
-
-  To start, you need that hierarchy.  The easiest way is to loop mount
-  an existing root_fs file:
-
-
-       host#  mount root_fs uml_root_dir -o loop
-
-
-
-
-  You need to change the filesystem type of / in etc/fstab to be
-  'hostfs', so that line looks like this:
-
-  /dev/ubd/0       /        hostfs      defaults          1   1
-
-
-
-
-  Then you need to chown to yourself all the files in that directory
-  that are owned by root.  This worked for me:
-
-
-       host#  find . -uid 0 -exec chown jdike {} \;
-
-
-
-
-  Next, make sure that your UML kernel has hostfs compiled in, not as a
-  module.  Then run UML with the boot device pointing at that directory:
-
-
-        ubd0=/path/to/uml/root/directory
-
-
-
-
-  UML should then boot as it does normally.
-
-
-  9.3.  Building hostfs
-
-  If you need to build hostfs because it's not in your kernel, you have
-  two choices:
-
-
-
-  o  Compiling hostfs into the kernel:
-
-
-     Reconfigure the kernel and set the 'Host filesystem' option under
-
-
-  o  Compiling hostfs as a module:
-
-
-     Reconfigure the kernel and set the 'Host filesystem' option under
-     be in arch/um/fs/hostfs/hostfs.o.  Install that in
-     /lib/modules/`uname -r`/fs in the virtual machine, boot it up, and
-
-
-       UML# insmod hostfs
-
-
-
-
-
-
-
-
-
-
-
-
-  10.  The Management Console
-
-
-
-  The UML management console is a low-level interface to the kernel,
-  somewhat like the i386 SysRq interface.  Since there is a full-blown
-  operating system under UML, there is much greater flexibility possible
-  than with the SysRq mechanism.
-
-
-  There are a number of things you can do with the mconsole interface:
-
-  o  get the kernel version
-
-  o  add and remove devices
-
-  o  halt or reboot the machine
-
-  o  Send SysRq commands
-
-  o  Pause and resume the UML
-
-
-  You need the mconsole client (uml_mconsole) which is present in CVS
-  (/tools/mconsole) in 2.4.5-9um and later, and will be in the RPM in
-  2.4.6.
-
-
-  You also need CONFIG_MCONSOLE (under 'General Setup') enabled in UML.
-  When you boot UML, you'll see a line like:
-
-
-       mconsole initialized on /home/jdike/.uml/umlNJ32yL/mconsole
-
-
-
-
-  If you specify a unique machine id one the UML command line, i.e.
-
-
-        umid=debian
-
-
-
-
-  you'll see this
-
-
-       mconsole initialized on /home/jdike/.uml/debian/mconsole
-
-
-
-
-  That file is the socket that uml_mconsole will use to communicate with
-  UML.  Run it with either the umid or the full path as its argument:
-
-
-       host% uml_mconsole debian
-
-
-
-
-  or
-
-
-       host% uml_mconsole /home/jdike/.uml/debian/mconsole
-
-
-
-
-  You'll get a prompt, at which you can run one of these commands:
-
-  o  version
-
-  o  halt
-
-  o  reboot
-
-  o  config
-
-  o  remove
-
-  o  sysrq
-
-  o  help
-
-  o  cad
-
-  o  stop
-
-  o  go
-
-
-  10.1.  version
-
-  This takes no arguments.  It prints the UML version.
-
-
-       (mconsole)  version
-       OK Linux usermode 2.4.5-9um #1 Wed Jun 20 22:47:08 EDT 2001 i686
-
-
-
-
-  There are a couple actual uses for this.  It's a simple no-op which
-  can be used to check that a UML is running.  It's also a way of
-  sending an interrupt to the UML.  This is sometimes useful on SMP
-  hosts, where there's a bug which causes signals to UML to be lost,
-  often causing it to appear to hang.  Sending such a UML the mconsole
-  version command is a good way to 'wake it up' before networking has
-  been enabled, as it does not do anything to the function of the UML.
-
-
-
-  10.2.  halt and reboot
-
-  These take no arguments.  They shut the machine down immediately, with
-  no syncing of disks and no clean shutdown of userspace.  So, they are
-  pretty close to crashing the machine.
-
-
-       (mconsole)  halt
-       OK
-
-
-
-
-
-
-  10.3.  config
-
-  "config" adds a new device to the virtual machine.  Currently the ubd
-  and network drivers support this.  It takes one argument, which is the
-  device to add, with the same syntax as the kernel command line.
-
-
-
-
-  (mconsole)
-  config ubd3=/home/jdike/incoming/roots/root_fs_debian22
-
-  OK
-  (mconsole)  config eth1=mcast
-  OK
-
-
-
-
-
-
-  10.4.  remove
-
-  "remove" deletes a device from the system.  Its argument is just the
-  name of the device to be removed. The device must be idle in whatever
-  sense the driver considers necessary.  In the case of the ubd driver,
-  the removed block device must not be mounted, swapped on, or otherwise
-  open, and in the case of the network driver, the device must be down.
-
-
-       (mconsole)  remove ubd3
-       OK
-       (mconsole)  remove eth1
-       OK
-
-
-
-
-
-
-  10.5.  sysrq
-
-  This takes one argument, which is a single letter.  It calls the
-  generic kernel's SysRq driver, which does whatever is called for by
-  that argument.  See the SysRq documentation in
-  Documentation/admin-guide/sysrq.rst in your favorite kernel tree to
-  see what letters are valid and what they do.
-
-
-
-  10.6.  help
-
-  "help" returns a string listing the valid commands and what each one
-  does.
-
-
-
-  10.7.  cad
-
-  This invokes the Ctl-Alt-Del action on init.  What exactly this ends
-  up doing is up to /etc/inittab.  Normally, it reboots the machine.
-  With UML, this is usually not desired, so if a halt would be better,
-  then find the section of inittab that looks like this
-
-
-       # What to do when CTRL-ALT-DEL is pressed.
-       ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
-
-
-
-
-  and change the command to halt.
-
-
-
-  10.8.  stop
-
-  This puts the UML in a loop reading mconsole requests until a 'go'
-  mconsole command is received. This is very useful for making backups
-  of UML filesystems, as the UML can be stopped, then synced via 'sysrq
-  s', so that everything is written to the filesystem. You can then copy
-  the filesystem and then send the UML 'go' via mconsole.
-
-
-  Note that a UML running with more than one CPU will have problems
-  after you send the 'stop' command, as only one CPU will be held in a
-  mconsole loop and all others will continue as normal.  This is a bug,
-  and will be fixed.
-
-
-
-  10.9.  go
-
-  This resumes a UML after being paused by a 'stop' command. Note that
-  when the UML has resumed, TCP connections may have timed out and if
-  the UML is paused for a long period of time, crond might go a little
-  crazy, running all the jobs it didn't do earlier.
-
-
-
-
-
-
-
-
-  11.  Kernel debugging
-
-
-  Note: The interface that makes debugging, as described here, possible
-  is present in 2.4.0-test6 kernels and later.
-
-
-  Since the user-mode kernel runs as a normal Linux process, it is
-  possible to debug it with gdb almost like any other process.  It is
-  slightly different because the kernel's threads are already being
-  ptraced for system call interception, so gdb can't ptrace them.
-  However, a mechanism has been added to work around that problem.
-
-
-  In order to debug the kernel, you need build it from source.  See
-  ``Compiling the kernel and modules''  for information on doing that.
-  Make sure that you enable CONFIG_DEBUGSYM and CONFIG_PT_PROXY during
-  the config.  These will compile the kernel with -g, and enable the
-  ptrace proxy so that gdb works with UML, respectively.
-
-
-
-
-  11.1.  Starting the kernel under gdb
-
-  You can have the kernel running under the control of gdb from the
-  beginning by putting 'debug' on the command line.  You will get an
-  xterm with gdb running inside it.  The kernel will send some commands
-  to gdb which will leave it stopped at the beginning of start_kernel.
-  At this point, you can get things going with 'next', 'step', or
-  'cont'.
-
-
-  There is a transcript of a debugging session  here <debug-
-  session.html> , with breakpoints being set in the scheduler and in an
-  interrupt handler.
-  11.2.  Examining sleeping processes
-
-  Not every bug is evident in the currently running process.  Sometimes,
-  processes hang in the kernel when they shouldn't because they've
-  deadlocked on a semaphore or something similar.  In this case, when
-  you ^C gdb and get a backtrace, you will see the idle thread, which
-  isn't very relevant.
-
-
-  What you want is the stack of whatever process is sleeping when it
-  shouldn't be.  You need to figure out which process that is, which is
-  generally fairly easy.  Then you need to get its host process id,
-  which you can do either by looking at ps on the host or at
-  task.thread.extern_pid in gdb.
-
-
-  Now what you do is this:
-
-  o  detach from the current thread
-
-
-       (UML gdb)  det
-
-
-
-
-
-  o  attach to the thread you are interested in
-
-
-       (UML gdb)  att <host pid>
-
-
-
-
-
-  o  look at its stack and anything else of interest
-
-
-       (UML gdb)  bt
-
-
-
-
-  Note that you can't do anything at this point that requires that a
-  process execute, e.g. calling a function
-
-  o  when you're done looking at that process, reattach to the current
-     thread and continue it
-
-
-       (UML gdb)
-       att 1
-
-
-
-
-
-
-       (UML gdb)
-       c
-
-
-
-
-  Here, specifying any pid which is not the process id of a UML thread
-  will cause gdb to reattach to the current thread.  I commonly use 1,
-  but any other invalid pid would work.
-
-
-
-  11.3.  Running ddd on UML
-
-  ddd works on UML, but requires a special kludge.  The process goes
-  like this:
-
-  o  Start ddd
-
-
-       host% ddd linux
-
-
-
-
-
-  o  With ps, get the pid of the gdb that ddd started.  You can ask the
-     gdb to tell you, but for some reason that confuses things and
-     causes a hang.
-
-  o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
-     - it will just sit there after you hit return
-
-  o  type 'att 1' to the ddd gdb and you will see something like
-
-
-       0xa013dc51 in __kill ()
-
-
-       (gdb)
-
-
-
-
-
-  o  At this point, type 'c', UML will boot up, and you can use ddd just
-     as you do on any other process.
-
-
-
-  11.4.  Debugging modules
-
-  gdb has support for debugging code which is dynamically loaded into
-  the process.  This support is what is needed to debug kernel modules
-  under UML.
-
-
-  Using that support is somewhat complicated.  You have to tell gdb what
-  object file you just loaded into UML and where in memory it is.  Then,
-  it can read the symbol table, and figure out where all the symbols are
-  from the load address that you provided.  It gets more interesting
-  when you load the module again (i.e. after an rmmod).  You have to
-  tell gdb to forget about all its symbols, including the main UML ones
-  for some reason, then load then all back in again.
-
-
-  There's an easy way and a hard way to do this.  The easy way is to use
-  the umlgdb expect script written by Chandan Kudige.  It basically
-  automates the process for you.
-
-
-  First, you must tell it where your modules are.  There is a list in
-  the script that looks like this:
-       set MODULE_PATHS {
-       "fat" "/usr/src/uml/linux-2.4.18/fs/fat/fat.o"
-       "isofs" "/usr/src/uml/linux-2.4.18/fs/isofs/isofs.o"
-       "minix" "/usr/src/uml/linux-2.4.18/fs/minix/minix.o"
-       }
-
-
-
-
-  You change that to list the names and paths of the modules that you
-  are going to debug.  Then you run it from the toplevel directory of
-  your UML pool and it basically tells you what to do:
-
-
-
-
-                   ******** GDB pid is 21903 ********
-       Start UML as: ./linux <kernel switches> debug gdb-pid=21903
-
-
-
-       GNU gdb 5.0rh-5 Red Hat Linux 7.1
-       Copyright 2001 Free Software Foundation, Inc.
-       GDB is free software, covered by the GNU General Public License, and you are
-       welcome to change it and/or distribute copies of it under certain conditions.
-       Type "show copying" to see the conditions.
-       There is absolutely no warranty for GDB.  Type "show warranty" for details.
-       This GDB was configured as "i386-redhat-linux"...
-       (gdb) b sys_init_module
-       Breakpoint 1 at 0xa0011923: file module.c, line 349.
-       (gdb) att 1
-
-
-
-
-  After you run UML and it sits there doing nothing, you hit return at
-  the 'att 1' and continue it:
-
-
-       Attaching to program: /home/jdike/linux/2.4/um/./linux, process 1
-       0xa00f4221 in __kill ()
-       (UML gdb)  c
-       Continuing.
-
-
-
-
-  At this point, you debug normally.  When you insmod something, the
-  expect magic will kick in and you'll see something like:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-   *** Module hostfs loaded ***
-  Breakpoint 1, sys_init_module (name_user=0x805abb0 "hostfs",
-      mod_user=0x8070e00) at module.c:349
-  349             char *name, *n_name, *name_tmp = NULL;
-  (UML gdb)  finish
-  Run till exit from #0  sys_init_module (name_user=0x805abb0 "hostfs",
-      mod_user=0x8070e00) at module.c:349
-  0xa00e2e23 in execute_syscall (r=0xa8140284) at syscall_kern.c:411
-  411             else res = EXECUTE_SYSCALL(syscall, regs);
-  Value returned is $1 = 0
-  (UML gdb)
-  p/x (int)module_list + module_list->size_of_struct
-
-  $2 = 0xa9021054
-  (UML gdb)  symbol-file ./linux
-  Load new symbol table from "./linux"? (y or n) y
-  Reading symbols from ./linux...
-  done.
-  (UML gdb)
-  add-symbol-file /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o 0xa9021054
-
-  add symbol table from file "/home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o" at
-          .text_addr = 0xa9021054
-   (y or n) y
-
-  Reading symbols from /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o...
-  done.
-  (UML gdb)  p *module_list
-  $1 = {size_of_struct = 84, next = 0xa0178720, name = 0xa9022de0 "hostfs",
-    size = 9016, uc = {usecount = {counter = 0}, pad = 0}, flags = 1,
-    nsyms = 57, ndeps = 0, syms = 0xa9023170, deps = 0x0, refs = 0x0,
-    init = 0xa90221f0 <init_hostfs>, cleanup = 0xa902222c <exit_hostfs>,
-    ex_table_start = 0x0, ex_table_end = 0x0, persist_start = 0x0,
-    persist_end = 0x0, can_unload = 0, runsize = 0, kallsyms_start = 0x0,
-    kallsyms_end = 0x0,
-    archdata_start = 0x1b855 <Address 0x1b855 out of bounds>,
-    archdata_end = 0xe5890000 <Address 0xe5890000 out of bounds>,
-    kernel_data = 0xf689c35d <Address 0xf689c35d out of bounds>}
-  >> Finished loading symbols for hostfs ...
-
-
-
-
-  That's the easy way.  It's highly recommended.  The hard way is
-  described below in case you're interested in what's going on.
-
-
-  Boot the kernel under the debugger and load the module with insmod or
-  modprobe.  With gdb, do:
-
-
-       (UML gdb)  p module_list
-
-
-
-
-  This is a list of modules that have been loaded into the kernel, with
-  the most recently loaded module first.  Normally, the module you want
-  is at module_list.  If it's not, walk down the next links, looking at
-  the name fields until find the module you want to debug.  Take the
-  address of that structure, and add module.size_of_struct (which in
-  2.4.10 kernels is 96 (0x60)) to it.  Gdb can make this hard addition
-  for you :-):
-
-
-
-  (UML gdb)
-  printf "%#x\n", (int)module_list module_list->size_of_struct
-
-
-
-
-  The offset from the module start occasionally changes (before 2.4.0,
-  it was module.size_of_struct + 4), so it's a good idea to check the
-  init and cleanup addresses once in a while, as describe below.  Now
-  do:
-
-
-       (UML gdb)
-       add-symbol-file /path/to/module/on/host that_address
-
-
-
-
-  Tell gdb you really want to do it, and you're in business.
-
-
-  If there's any doubt that you got the offset right, like breakpoints
-  appear not to work, or they're appearing in the wrong place, you can
-  check it by looking at the module structure.  The init and cleanup
-  fields should look like:
-
-
-       init = 0x588066b0 <init_hostfs>, cleanup = 0x588066c0 <exit_hostfs>
-
-
-
-
-  with no offsets on the symbol names.  If the names are right, but they
-  are offset, then the offset tells you how much you need to add to the
-  address you gave to add-symbol-file.
-
-
-  When you want to load in a new version of the module, you need to get
-  gdb to forget about the old one.  The only way I've found to do that
-  is to tell gdb to forget about all symbols that it knows about:
-
-
-       (UML gdb)  symbol-file
-
-
-
-
-  Then reload the symbols from the kernel binary:
-
-
-       (UML gdb)  symbol-file /path/to/kernel
-
-
-
-
-  and repeat the process above.  You'll also need to re-enable break-
-  points.  They were disabled when you dumped all the symbols because
-  gdb couldn't figure out where they should go.
-
-
-
-  11.5.  Attaching gdb to the kernel
-
-  If you don't have the kernel running under gdb, you can attach gdb to
-  it later by sending the tracing thread a SIGUSR1.  The first line of
-  the console output identifies its pid:
-       tracing thread pid = 20093
-
-
-
-
-  When you send it the signal:
-
-
-       host% kill -USR1 20093
-
-
-
-
-  you will get an xterm with gdb running in it.
-
-
-  If you have the mconsole compiled into UML, then the mconsole client
-  can be used to start gdb:
-
-
-       (mconsole)  (mconsole) config gdb=xterm
-
-
-
-
-  will fire up an xterm with gdb running in it.
-
-
-
-  11.6.  Using alternate debuggers
-
-  UML has support for attaching to an already running debugger rather
-  than starting gdb itself.  This is present in CVS as of 17 Apr 2001.
-  I sent it to Alan for inclusion in the ac tree, and it will be in my
-  2.4.4 release.
-
-
-  This is useful when gdb is a subprocess of some UI, such as emacs or
-  ddd.  It can also be used to run debuggers other than gdb on UML.
-  Below is an example of using strace as an alternate debugger.
-
-
-  To do this, you need to get the pid of the debugger and pass it in
-  with the
-
-
-  If you are using gdb under some UI, then tell it to 'att 1', and
-  you'll find yourself attached to UML.
-
-
-  If you are using something other than gdb as your debugger, then
-  you'll need to get it to do the equivalent of 'att 1' if it doesn't do
-  it automatically.
-
-
-  An example of an alternate debugger is strace.  You can strace the
-  actual kernel as follows:
-
-  o  Run the following in a shell
-
-
-       host%
-       sh -c 'echo pid=$$; echo -n hit return; read x; exec strace -p 1 -o strace.out'
-
-
-
-  o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
-     by the previous command
-
-  o  Hit return in the shell, and UML will start running, and strace
-     output will start accumulating in the output file.
-
-     Note that this is different from running
-
-
-       host% strace ./linux
-
-
-
-
-  That will strace only the main UML thread, the tracing thread, which
-  doesn't do any of the actual kernel work.  It just oversees the vir-
-  tual machine.  In contrast, using strace as described above will show
-  you the low-level activity of the virtual machine.
-
-
-
-
-
-  12.  Kernel debugging examples
-
-  12.1.  The case of the hung fsck
-
-  When booting up the kernel, fsck failed, and dropped me into a shell
-  to fix things up.  I ran fsck -y, which hung:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-  Setting hostname uml                    [ OK ]
-  Checking root filesystem
-  /dev/fhd0 was not cleanly unmounted, check forced.
-  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
-
-  /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
-          (i.e., without -a or -p options)
-  [ FAILED ]
-
-  *** An error occurred during the file system check.
-  *** Dropping you to a shell; the system will reboot
-  *** when you leave the shell.
-  Give root password for maintenance
-  (or type Control-D for normal startup):
-
-  [root@uml /root]# fsck -y /dev/fhd0
-  fsck -y /dev/fhd0
-  Parallelizing fsck version 1.14 (9-Jan-1999)
-  e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
-  /dev/fhd0 contains a file system with errors, check forced.
-  Pass 1: Checking inodes, blocks, and sizes
-  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.  Ignore error? yes
-
-  Inode 19780, i_blocks is 1548, should be 540.  Fix? yes
-
-  Pass 2: Checking directory structure
-  Error reading block 49405 (Attempt to read block from filesystem resulted in short read).  Ignore error? yes
-
-  Directory inode 11858, block 0, offset 0: directory corrupted
-  Salvage? yes
-
-  Missing '.' in directory inode 11858.
-  Fix? yes
-
-  Missing '..' in directory inode 11858.
-  Fix? yes
-
-
-
-
-
-  The standard drill in this sort of situation is to fire up gdb on the
-  signal thread, which, in this case, was pid 1935.  In another window,
-  I run gdb and attach pid 1935.
-
-
-
-
-       ~/linux/2.3.26/um 1016: gdb linux
-       GNU gdb 4.17.0.11 with Linux support
-       Copyright 1998 Free Software Foundation, Inc.
-       GDB is free software, covered by the GNU General Public License, and you are
-       welcome to change it and/or distribute copies of it under certain conditions.
-       Type "show copying" to see the conditions.
-       There is absolutely no warranty for GDB.  Type "show warranty" for details.
-       This GDB was configured as "i386-redhat-linux"...
-
-       (gdb) att 1935
-       Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1935
-       0x100756d9 in __wait4 ()
-
-
-
-
-
-
-  Let's see what's currently running:
-
-
-
-       (gdb) p current_task.pid
-       $1 = 0
-
-
-
-
-
-  It's the idle thread, which means that fsck went to sleep for some
-  reason and never woke up.
-
-
-  Let's guess that the last process in the process list is fsck:
-
-
-
-       (gdb) p current_task.prev_task.comm
-       $13 = "fsck.ext2\000\000\000\000\000\000"
-
-
-
-
-
-  It is, so let's see what it thinks it's up to:
-
-
-
-       (gdb) p current_task.prev_task.thread
-       $14 = {extern_pid = 1980, tracing = 0, want_tracing = 0, forking = 0,
-         kernel_stack_page = 0, signal_stack = 1342627840, syscall = {id = 4, args = {
-             3, 134973440, 1024, 0, 1024}, have_result = 0, result = 50590720},
-         request = {op = 2, u = {exec = {ip = 1350467584, sp = 2952789424}, fork = {
-               regs = {1350467584, 2952789424, 0 <repeats 15 times>}, sigstack = 0,
-               pid = 0}, switch_to = 0x507e8000, thread = {proc = 0x507e8000,
-               arg = 0xaffffdb0, flags = 0, new_pid = 0}, input_request = {
-               op = 1350467584, fd = -1342177872, proc = 0, pid = 0}}}}
-
-
-
-
-
-  The interesting things here are the fact that its .thread.syscall.id
-  is __NR_write (see the big switch in arch/um/kernel/syscall_kern.c or
-  the defines in include/asm-um/arch/unistd.h), and that it never
-  returned.  Also, its .request.op is OP_SWITCH (see
-  arch/um/include/user_util.h).  These mean that it went into a write,
-  and, for some reason, called schedule().
-
-
-  The fact that it never returned from write means that its stack should
-  be fairly interesting.  Its pid is 1980 (.thread.extern_pid).  That
-  process is being ptraced by the signal thread, so it must be detached
-  before gdb can attach it:
-
-
-
-
-
-
-
-
-
-
-  (gdb) call detach(1980)
-
-  Program received signal SIGSEGV, Segmentation fault.
-  <function called from gdb>
-  The program being debugged stopped while in a function called from GDB.
-  When the function (detach) is done executing, GDB will silently
-  stop (instead of continuing to evaluate the expression containing
-  the function call).
-  (gdb) call detach(1980)
-  $15 = 0
-
-
-
-
-
-  The first detach segfaults for some reason, and the second one
-  succeeds.
-
-
-  Now I detach from the signal thread, attach to the fsck thread, and
-  look at its stack:
-
-
-       (gdb) det
-       Detaching from program: /home/dike/linux/2.3.26/um/linux Pid 1935
-       (gdb) att 1980
-       Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1980
-       0x10070451 in __kill ()
-       (gdb) bt
-       #0  0x10070451 in __kill ()
-       #1  0x10068ccd in usr1_pid (pid=1980) at process.c:30
-       #2  0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
-           at process_kern.c:156
-       #3  0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
-           at process_kern.c:161
-       #4  0x10001d12 in schedule () at core.c:777
-       #5  0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
-       #6  0x1006aa10 in __down_failed () at semaphore.c:157
-       #7  0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
-       #8  0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
-       #9  <signal handler called>
-       #10 0x10155404 in errno ()
-       #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
-       #12 0x1006c5d8 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
-       #13 0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
-       #14 <signal handler called>
-       #15 0xc0fd in ?? ()
-       #16 0x10016647 in sys_write (fd=3,
-           buf=0x80b8800 <Address 0x80b8800 out of bounds>, count=1024)
-           at read_write.c:159
-       #17 0x1006d5b3 in execute_syscall (syscall=4, args=0x5006ef08)
-           at syscall_kern.c:254
-       #18 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
-       #19 <signal handler called>
-       #20 0x400dc8b0 in ?? ()
-
-
-
-
-
-  The interesting things here are :
-
-  o  There are two segfaults on this stack (frames 9 and 14)
-
-  o  The first faulting address (frame 11) is 0x50000800
-
-  (gdb) p (void *)1342179328
-  $16 = (void *) 0x50000800
-
-
-
-
-
-  The initial faulting address is interesting because it is on the idle
-  thread's stack.  I had been seeing the idle thread segfault for no
-  apparent reason, and the cause looked like stack corruption.  In hopes
-  of catching the culprit in the act, I had turned off all protections
-  to that stack while the idle thread wasn't running.  This apparently
-  tripped that trap.
-
-
-  However, the more immediate problem is that second segfault and I'm
-  going to concentrate on that.  First, I want to see where the fault
-  happened, so I have to go look at the sigcontent struct in frame 8:
-
-
-
-       (gdb) up
-       #1  0x10068ccd in usr1_pid (pid=1980) at process.c:30
-       30        kill(pid, SIGUSR1);
-       (gdb)
-       #2  0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
-           at process_kern.c:156
-       156       usr1_pid(getpid());
-       (gdb)
-       #3  0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
-           at process_kern.c:161
-       161       _switch_to(prev, next);
-       (gdb)
-       #4  0x10001d12 in schedule () at core.c:777
-       777             switch_to(prev, next, prev);
-       (gdb)
-       #5  0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
-       71                      schedule();
-       (gdb)
-       #6  0x1006aa10 in __down_failed () at semaphore.c:157
-       157     }
-       (gdb)
-       #7  0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
-       174       segv(sc->cr2, sc->err & 2);
-       (gdb)
-       #8  0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
-       182       segv_handler(sc);
-       (gdb) p *sc
-       Cannot access memory at address 0x0.
-
-
-
-
-  That's not very useful, so I'll try a more manual method:
-
-
-       (gdb) p *((struct sigcontext *) (&sig + 1))
-       $19 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
-         __dsh = 0, edi = 1342179328, esi = 1350378548, ebp = 1342630440,
-         esp = 1342630420, ebx = 1348150624, edx = 1280, ecx = 0, eax = 0,
-         trapno = 14, err = 4, eip = 268480945, cs = 35, __csh = 0, eflags = 66118,
-         esp_at_signal = 1342630420, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
-         cr2 = 1280}
-
-
-
-  The ip is in handle_mm_fault:
-
-
-       (gdb) p (void *)268480945
-       $20 = (void *) 0x1000b1b1
-       (gdb) i sym $20
-       handle_mm_fault + 57 in section .text
-
-
-
-
-
-  Specifically, it's in pte_alloc:
-
-
-       (gdb) i line *$20
-       Line 124 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1b1 <handle_mm_fault+57>
-          and ends at 0x1000b1b7 <handle_mm_fault+63>.
-
-
-
-
-
-  To find where in handle_mm_fault this is, I'll jump forward in the
-  code until I see an address in that procedure:
-
-
-
-       (gdb) i line *0x1000b1c0
-       Line 126 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1b7 <handle_mm_fault+63>
-          and ends at 0x1000b1c3 <handle_mm_fault+75>.
-       (gdb) i line *0x1000b1d0
-       Line 131 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1d0 <handle_mm_fault+88>
-          and ends at 0x1000b1da <handle_mm_fault+98>.
-       (gdb) i line *0x1000b1e0
-       Line 61 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1da <handle_mm_fault+98>
-          and ends at 0x1000b1e1 <handle_mm_fault+105>.
-       (gdb) i line *0x1000b1f0
-       Line 134 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1f0 <handle_mm_fault+120>
-          and ends at 0x1000b200 <handle_mm_fault+136>.
-       (gdb) i line *0x1000b200
-       Line 135 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b200 <handle_mm_fault+136>
-          and ends at 0x1000b208 <handle_mm_fault+144>.
-       (gdb) i line *0x1000b210
-       Line 139 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b210 <handle_mm_fault+152>
-          and ends at 0x1000b219 <handle_mm_fault+161>.
-       (gdb) i line *0x1000b220
-       Line 1168 of "memory.c" starts at address 0x1000b21e <handle_mm_fault+166>
-          and ends at 0x1000b222 <handle_mm_fault+170>.
-
-
-
-
-
-  Something is apparently wrong with the page tables or vma_structs, so
-  lets go back to frame 11 and have a look at them:
-
-
-
-  #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
-  50        handle_mm_fault(current, vma, address, is_write);
-  (gdb) call pgd_offset_proc(vma->vm_mm, address)
-  $22 = (pgd_t *) 0x80a548c
-
-
-
-
-
-  That's pretty bogus.  Page tables aren't supposed to be in process
-  text or data areas.  Let's see what's in the vma:
-
-
-       (gdb) p *vma
-       $23 = {vm_mm = 0x507d2434, vm_start = 0, vm_end = 134512640,
-         vm_next = 0x80a4f8c, vm_page_prot = {pgprot = 0}, vm_flags = 31200,
-         vm_avl_height = 2058, vm_avl_left = 0x80a8c94, vm_avl_right = 0x80d1000,
-         vm_next_share = 0xaffffdb0, vm_pprev_share = 0xaffffe63,
-         vm_ops = 0xaffffe7a, vm_pgoff = 2952789626, vm_file = 0xafffffec,
-         vm_private_data = 0x62}
-       (gdb) p *vma.vm_mm
-       $24 = {mmap = 0x507d2434, mmap_avl = 0x0, mmap_cache = 0x8048000,
-         pgd = 0x80a4f8c, mm_users = {counter = 0}, mm_count = {counter = 134904288},
-         map_count = 134909076, mmap_sem = {count = {counter = 135073792},
-           sleepers = -1342177872, wait = {lock = <optimized out or zero length>,
-             task_list = {next = 0xaffffe63, prev = 0xaffffe7a},
-             __magic = -1342177670, __creator = -1342177300}, __magic = 98},
-         page_table_lock = {}, context = 138, start_code = 0, end_code = 0,
-         start_data = 0, end_data = 0, start_brk = 0, brk = 0, start_stack = 0,
-         arg_start = 0, arg_end = 0, env_start = 0, env_end = 0, rss = 1350381536,
-         total_vm = 0, locked_vm = 0, def_flags = 0, cpu_vm_mask = 0, swap_cnt = 0,
-         swap_address = 0, segments = 0x0}
-
-
-
-
-
-  This also pretty bogus.  With all of the 0x80xxxxx and 0xaffffxxx
-  addresses, this is looking like a stack was plonked down on top of
-  these structures.  Maybe it's a stack overflow from the next page:
-
-
-
-       (gdb) p vma
-       $25 = (struct vm_area_struct *) 0x507d2434
-
-
-
-
-
-  That's towards the lower quarter of the page, so that would have to
-  have been pretty heavy stack overflow:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-  (gdb) x/100x $25
-  0x507d2434:     0x507d2434      0x00000000      0x08048000      0x080a4f8c
-  0x507d2444:     0x00000000      0x080a79e0      0x080a8c94      0x080d1000
-  0x507d2454:     0xaffffdb0      0xaffffe63      0xaffffe7a      0xaffffe7a
-  0x507d2464:     0xafffffec      0x00000062      0x0000008a      0x00000000
-  0x507d2474:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2484:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2494:     0x00000000      0x00000000      0x507d2fe0      0x00000000
-  0x507d24a4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24b4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24c4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24d4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24e4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24f4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2504:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2514:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2524:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2534:     0x00000000      0x00000000      0x507d25dc      0x00000000
-  0x507d2544:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2554:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2564:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2574:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2584:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2594:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d25a4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d25b4:     0x00000000      0x00000000      0x00000000      0x00000000
-
-
-
-
-
-  It's not stack overflow.  The only "stack-like" piece of this data is
-  the vma_struct itself.
-
-
-  At this point, I don't see any avenues to pursue, so I just have to
-  admit that I have no idea what's going on.  What I will do, though, is
-  stick a trap on the segfault handler which will stop if it sees any
-  writes to the idle thread's stack.  That was the thing that happened
-  first, and it may be that if I can catch it immediately, what's going
-  on will be somewhat clearer.
-
-
-  12.2.  Episode 2: The case of the hung fsck
-
-  After setting a trap in the SEGV handler for accesses to the signal
-  thread's stack, I reran the kernel.
-
-
-  fsck hung again, this time by hitting the trap:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-  Setting hostname uml                            [ OK ]
-  Checking root filesystem
-  /dev/fhd0 contains a file system with errors, check forced.
-  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
-
-  /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
-          (i.e., without -a or -p options)
-  [ FAILED ]
-
-  *** An error occurred during the file system check.
-  *** Dropping you to a shell; the system will reboot
-  *** when you leave the shell.
-  Give root password for maintenance
-  (or type Control-D for normal startup):
-
-  [root@uml /root]# fsck -y /dev/fhd0
-  fsck -y /dev/fhd0
-  Parallelizing fsck version 1.14 (9-Jan-1999)
-  e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
-  /dev/fhd0 contains a file system with errors, check forced.
-  Pass 1: Checking inodes, blocks, and sizes
-  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.  Ignore error? yes
-
-  Pass 2: Checking directory structure
-  Error reading block 49405 (Attempt to read block from filesystem resulted in short read).  Ignore error? yes
-
-  Directory inode 11858, block 0, offset 0: directory corrupted
-  Salvage? yes
-
-  Missing '.' in directory inode 11858.
-  Fix? yes
-
-  Missing '..' in directory inode 11858.
-  Fix? yes
-
-  Untested (4127) [100fe44c]: trap_kern.c line 31
-
-
-
-
-
-  I need to get the signal thread to detach from pid 4127 so that I can
-  attach to it with gdb.  This is done by sending it a SIGUSR1, which is
-  caught by the signal thread, which detaches the process:
-
-
-       kill -USR1 4127
-
-
-
-
-
-  Now I can run gdb on it:
-
-
-
-
-
-
-
-
-
-
-
-
-
-  ~/linux/2.3.26/um 1034: gdb linux
-  GNU gdb 4.17.0.11 with Linux support
-  Copyright 1998 Free Software Foundation, Inc.
-  GDB is free software, covered by the GNU General Public License, and you are
-  welcome to change it and/or distribute copies of it under certain conditions.
-  Type "show copying" to see the conditions.
-  There is absolutely no warranty for GDB.  Type "show warranty" for details.
-  This GDB was configured as "i386-redhat-linux"...
-  (gdb) att 4127
-  Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 4127
-  0x10075891 in __libc_nanosleep ()
-
-
-
-
-
-  The backtrace shows that it was in a write and that the fault address
-  (address in frame 3) is 0x50000800, which is right in the middle of
-  the signal thread's stack page:
-
-
-       (gdb) bt
-       #0  0x10075891 in __libc_nanosleep ()
-       #1  0x1007584d in __sleep (seconds=1000000)
-           at ../sysdeps/unix/sysv/linux/sleep.c:78
-       #2  0x1006ce9a in stop () at user_util.c:191
-       #3  0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
-       #4  0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
-       #5  0x1006c63c in kern_segv_handler (sig=11) at trap_user.c:182
-       #6  <signal handler called>
-       #7  0xc0fd in ?? ()
-       #8  0x10016647 in sys_write (fd=3, buf=0x80b8800 "R.", count=1024)
-           at read_write.c:159
-       #9  0x1006d603 in execute_syscall (syscall=4, args=0x5006ef08)
-           at syscall_kern.c:254
-       #10 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
-       #11 <signal handler called>
-       #12 0x400dc8b0 in ?? ()
-       #13 <signal handler called>
-       #14 0x400dc8b0 in ?? ()
-       #15 0x80545fd in ?? ()
-       #16 0x804daae in ?? ()
-       #17 0x8054334 in ?? ()
-       #18 0x804d23e in ?? ()
-       #19 0x8049632 in ?? ()
-       #20 0x80491d2 in ?? ()
-       #21 0x80596b5 in ?? ()
-       (gdb) p (void *)1342179328
-       $3 = (void *) 0x50000800
-
-
-
-
-
-  Going up the stack to the segv_handler frame and looking at where in
-  the code the access happened shows that it happened near line 110 of
-  block_dev.c:
-
-
-
-
-
-
-
-
-
-  (gdb) up
-  #1  0x1007584d in __sleep (seconds=1000000)
-      at ../sysdeps/unix/sysv/linux/sleep.c:78
-  ../sysdeps/unix/sysv/linux/sleep.c:78: No such file or directory.
-  (gdb)
-  #2  0x1006ce9a in stop () at user_util.c:191
-  191       while(1) sleep(1000000);
-  (gdb)
-  #3  0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
-  31          KERN_UNTESTED();
-  (gdb)
-  #4  0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
-  174       segv(sc->cr2, sc->err & 2);
-  (gdb) p *sc
-  $1 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
-    __dsh = 0, edi = 1342179328, esi = 134973440, ebp = 1342631484,
-    esp = 1342630864, ebx = 256, edx = 0, ecx = 256, eax = 1024, trapno = 14,
-    err = 6, eip = 268550834, cs = 35, __csh = 0, eflags = 66070,
-    esp_at_signal = 1342630864, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
-    cr2 = 1342179328}
-  (gdb) p (void *)268550834
-  $2 = (void *) 0x1001c2b2
-  (gdb) i sym $2
-  block_write + 1090 in section .text
-  (gdb) i line *$2
-  Line 209 of "/home/dike/linux/2.3.26/um/include/asm/arch/string.h"
-     starts at address 0x1001c2a1 <block_write+1073>
-     and ends at 0x1001c2bf <block_write+1103>.
-  (gdb) i line *0x1001c2c0
-  Line 110 of "block_dev.c" starts at address 0x1001c2bf <block_write+1103>
-     and ends at 0x1001c2e3 <block_write+1139>.
-
-
-
-
-
-  Looking at the source shows that the fault happened during a call to
-  copy_from_user to copy the data into the kernel:
-
-
-       107             count -= chars;
-       108             copy_from_user(p,buf,chars);
-       109             p += chars;
-       110             buf += chars;
-
-
-
-
-
-  p is the pointer which must contain 0x50000800, since buf contains
-  0x80b8800 (frame 8 above).  It is defined as:
-
-
-                       p = offset + bh->b_data;
-
-
-
-
-
-  I need to figure out what bh is, and it just so happens that bh is
-  passed as an argument to mark_buffer_uptodate and mark_buffer_dirty a
-  few lines later, so I do a little disassembly:
-
-
-
-
-  (gdb) disas 0x1001c2bf 0x1001c2e0
-  Dump of assembler code from 0x1001c2bf to 0x1001c2d0:
-  0x1001c2bf <block_write+1103>:  addl   %eax,0xc(%ebp)
-  0x1001c2c2 <block_write+1106>:  movl   0xfffffdd4(%ebp),%edx
-  0x1001c2c8 <block_write+1112>:  btsl   $0x0,0x18(%edx)
-  0x1001c2cd <block_write+1117>:  btsl   $0x1,0x18(%edx)
-  0x1001c2d2 <block_write+1122>:  sbbl   %ecx,%ecx
-  0x1001c2d4 <block_write+1124>:  testl  %ecx,%ecx
-  0x1001c2d6 <block_write+1126>:  jne    0x1001c2e3 <block_write+1139>
-  0x1001c2d8 <block_write+1128>:  pushl  $0x0
-  0x1001c2da <block_write+1130>:  pushl  %edx
-  0x1001c2db <block_write+1131>:  call   0x1001819c <__mark_buffer_dirty>
-  End of assembler dump.
-
-
-
-
-
-  At that point, bh is in %edx (address 0x1001c2da), which is calculated
-  at 0x1001c2c2 as %ebp + 0xfffffdd4, so I figure exactly what that is,
-  taking %ebp from the sigcontext_struct above:
-
-
-       (gdb) p (void *)1342631484
-       $5 = (void *) 0x5006ee3c
-       (gdb) p 0x5006ee3c+0xfffffdd4
-       $6 = 1342630928
-       (gdb) p (void *)$6
-       $7 = (void *) 0x5006ec10
-       (gdb) p *((void **)$7)
-       $8 = (void *) 0x50100200
-
-
-
-
-
-  Now, I look at the structure to see what's in it, and particularly,
-  what its b_data field contains:
-
-
-       (gdb) p *((struct buffer_head *)0x50100200)
-       $13 = {b_next = 0x50289380, b_blocknr = 49405, b_size = 1024, b_list = 0,
-         b_dev = 15872, b_count = {counter = 1}, b_rdev = 15872, b_state = 24,
-         b_flushtime = 0, b_next_free = 0x501001a0, b_prev_free = 0x50100260,
-         b_this_page = 0x501001a0, b_reqnext = 0x0, b_pprev = 0x507fcf58,
-         b_data = 0x50000800 "", b_page = 0x50004000,
-         b_end_io = 0x10017f60 <end_buffer_io_sync>, b_dev_id = 0x0,
-         b_rsector = 98810, b_wait = {lock = <optimized out or zero length>,
-           task_list = {next = 0x50100248, prev = 0x50100248}, __magic = 1343226448,
-           __creator = 0}, b_kiobuf = 0x0}
-
-
-
-
-
-  The b_data field is indeed 0x50000800, so the question becomes how
-  that happened.  The rest of the structure looks fine, so this probably
-  is not a case of data corruption.  It happened on purpose somehow.
-
-
-  The b_page field is a pointer to the page_struct representing the
-  0x50000000 page.  Looking at it shows the kernel's idea of the state
-  of that page:
-
-
-
-  (gdb) p *$13.b_page
-  $17 = {list = {next = 0x50004a5c, prev = 0x100c5174}, mapping = 0x0,
-    index = 0, next_hash = 0x0, count = {counter = 1}, flags = 132, lru = {
-      next = 0x50008460, prev = 0x50019350}, wait = {
-      lock = <optimized out or zero length>, task_list = {next = 0x50004024,
-        prev = 0x50004024}, __magic = 1342193708, __creator = 0},
-    pprev_hash = 0x0, buffers = 0x501002c0, virtual = 1342177280,
-    zone = 0x100c5160}
-
-
-
-
-
-  Some sanity-checking: the virtual field shows the "virtual" address of
-  this page, which in this kernel is the same as its "physical" address,
-  and the page_struct itself should be mem_map[0], since it represents
-  the first page of memory:
-
-
-
-       (gdb) p (void *)1342177280
-       $18 = (void *) 0x50000000
-       (gdb) p mem_map
-       $19 = (mem_map_t *) 0x50004000
-
-
-
-
-
-  These check out fine.
-
-
-  Now to check out the page_struct itself.  In particular, the flags
-  field shows whether the page is considered free or not:
-
-
-       (gdb) p (void *)132
-       $21 = (void *) 0x84
-
-
-
-
-
-  The "reserved" bit is the high bit, which is definitely not set, so
-  the kernel considers the signal stack page to be free and available to
-  be used.
-
-
-  At this point, I jump to conclusions and start looking at my early
-  boot code, because that's where that page is supposed to be reserved.
-
-
-  In my setup_arch procedure, I have the following code which looks just
-  fine:
-
-
-
-       bootmap_size = init_bootmem(start_pfn, end_pfn - start_pfn);
-       free_bootmem(__pa(low_physmem) + bootmap_size, high_physmem - low_physmem);
-
-
-
-
-
-  Two stack pages have already been allocated, and low_physmem points to
-  the third page, which is the beginning of free memory.
-  The init_bootmem call declares the entire memory to the boot memory
-  manager, which marks it all reserved.  The free_bootmem call frees up
-  all of it, except for the first two pages.  This looks correct to me.
-
-
-  So, I decide to see init_bootmem run and make sure that it is marking
-  those first two pages as reserved.  I never get that far.
-
-
-  Stepping into init_bootmem, and looking at bootmem_map before looking
-  at what it contains shows the following:
-
-
-
-       (gdb) p bootmem_map
-       $3 = (void *) 0x50000000
-
-
-
-
-
-  Aha!  The light dawns.  That first page is doing double duty as a
-  stack and as the boot memory map.  The last thing that the boot memory
-  manager does is to free the pages used by its memory map, so this page
-  is getting freed even its marked as reserved.
-
-
-  The fix was to initialize the boot memory manager before allocating
-  those two stack pages, and then allocate them through the boot memory
-  manager.  After doing this, and fixing a couple of subsequent buglets,
-  the stack corruption problem disappeared.
-
-
-
-
-
-  13.  What to do when UML doesn't work
-
-
-
-
-  13.1.  Strange compilation errors when you build from source
-
-  As of test11, it is necessary to have "ARCH=um" in the environment or
-  on the make command line for all steps in building UML, including
-  clean, distclean, or mrproper, config, menuconfig, or xconfig, dep,
-  and linux.  If you forget for any of them, the i386 build seems to
-  contaminate the UML build.  If this happens, start from scratch with
-
-
-       host%
-       make mrproper ARCH=um
-
-
-
-
-  and repeat the build process with ARCH=um on all the steps.
-
-
-  See ``Compiling the kernel and modules''  for more details.
-
-
-  Another cause of strange compilation errors is building UML in
-  /usr/src/linux.  If you do this, the first thing you need to do is
-  clean up the mess you made.  The /usr/src/linux/asm link will now
-  point to /usr/src/linux/asm-um.  Make it point back to
-  /usr/src/linux/asm-i386.  Then, move your UML pool someplace else and
-  build it there.  Also see below, where a more specific set of symptoms
-  is described.
-
-
-
-  13.3.  A variety of panics and hangs with /tmp on a reiserfs  filesys-
-  tem
-
-  I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
-  Panics preceded by
-
-
-       Detaching pid nnnn
-
-
-
-  are diagnostic of this problem.  This is a reiserfs bug which causes a
-  thread to occasionally read stale data from a mmapped page shared with
-  another thread.  The fix is to upgrade the filesystem or to have /tmp
-  be an ext2 filesystem.
-
-
-
-  13.4.  The compile fails with errors about conflicting types for
-  'open', 'dup', and 'waitpid'
-
-  This happens when you build in /usr/src/linux.  The UML build makes
-  the include/asm link point to include/asm-um.  /usr/include/asm points
-  to /usr/src/linux/include/asm, so when that link gets moved, files
-  which need to include the asm-i386 versions of headers get the
-  incompatible asm-um versions.  The fix is to move the include/asm link
-  back to include/asm-i386 and to do UML builds someplace else.
-
-
-
-  13.5.  UML doesn't work when /tmp is an NFS filesystem
-
-  This seems to be a similar situation with the ReiserFS problem above.
-  Some versions of NFS seems not to handle mmap correctly, which UML
-  depends on.  The workaround is have /tmp be a non-NFS directory.
-
-
-  13.6.  UML hangs on boot when compiled with gprof support
-
-  If you build UML with gprof support and, early in the boot, it does
-  this
-
-
-       kernel BUG at page_alloc.c:100!
-
-
-
-
-  you have a buggy gcc.  You can work around the problem by removing
-  UM_FASTCALL from CFLAGS in arch/um/Makefile-i386.  This will open up
-  another bug, but that one is fairly hard to reproduce.
-
-
-
-  13.7.  syslogd dies with a SIGTERM on startup
-
-  The exact boot error depends on the distribution that you're booting,
-  but Debian produces this:
-
-
-       /etc/rc2.d/S10sysklogd: line 49:    93 Terminated
-       start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD
-
-
-
-
-  This is a syslogd bug.  There's a race between a parent process
-  installing a signal handler and its child sending the signal.  See
-  this uml-devel post <http://www.geocrawler.com/lists/3/Source-
-  Forge/709/0/6612801>  for the details.
-
-
-
-  13.8.  TUN/TAP networking doesn't work on a 2.4 host
-
-  There are a couple of problems which were
-  <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
-  out">  by Tim Robinson <timro at trkr dot net>
-
-  o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
-     The fix is to upgrade to something more recent and then read the
-     next item.
-
-  o  If you see
-
-
-       File descriptor in bad state
-
-
-
-  when you bring up the device inside UML, you have a header mismatch
-  between the original kernel and the upgraded one.  Make /usr/src/linux
-  point at the new headers.  This will only be a problem if you build
-  uml_net yourself.
-
-
-
-  13.9.  You can network to the host but not to other machines on the
-  net
-
-  If you can connect to the host, and the host can connect to UML, but
-  you cannot connect to any other machines, then you may need to enable
-  IP Masquerading on the host.  Usually this is only experienced when
-  using private IP addresses (192.168.x.x or 10.x.x.x) for host/UML
-  networking, rather than the public address space that your host is
-  connected to.  UML does not enable IP Masquerading, so you will need
-  to create a static rule to enable it:
-
-
-       host%
-       iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
-
-
-
-
-  Replace eth0 with the interface that you use to talk to the rest of
-  the world.
-
-
-  Documentation on IP Masquerading, and SNAT, can be found at
-  www.netfilter.org  <http://www.netfilter.org> .
-
-
-  If you can reach the local net, but not the outside Internet, then
-  that is usually a routing problem.  The UML needs a default route:
-
-
-       UML#
-       route add default gw gateway IP
-
-
-
-
-  The gateway IP can be any machine on the local net that knows how to
-  reach the outside world.  Usually, this is the host or the local net-
-  work's gateway.
-
-
-  Occasionally, we hear from someone who can reach some machines, but
-  not others on the same net, or who can reach some ports on other
-  machines, but not others.  These are usually caused by strange
-  firewalling somewhere between the UML and the other box.  You track
-  this down by running tcpdump on every interface the packets travel
-  over and see where they disappear.  When you find a machine that takes
-  the packets in, but does not send them onward, that's the culprit.
-
-
-
-  13.10.  I have no root and I want to scream
-
-  Thanks to Birgit Wahlich for telling me about this strange one.  It
-  turns out that there's a limit of six environment variables on the
-  kernel command line.  When that limit is reached or exceeded, argument
-  processing stops, which means that the 'root=' argument that UML
-  usually adds is not seen.  So, the filesystem has no idea what the
-  root device is, so it panics.
-
-
-  The fix is to put less stuff on the command line.  Glomming all your
-  setup variables into one is probably the best way to go.
-
-
-
-  13.11.  UML build conflict between ptrace.h and ucontext.h
-
-  On some older systems, /usr/include/asm/ptrace.h and
-  /usr/include/sys/ucontext.h define the same names.  So, when they're
-  included together, the defines from one completely mess up the parsing
-  of the other, producing errors like:
-       /usr/include/sys/ucontext.h:47: parse error before
-       `10'
-
-
-
-
-  plus a pile of warnings.
-
-
-  This is a libc botch, which has since been fixed, and I don't see any
-  way around it besides upgrading.
-
-
-
-  13.12.  The UML BogoMips is exactly half the host's BogoMips
-
-  On i386 kernels, there are two ways of running the loop that is used
-  to calculate the BogoMips rating, using the TSC if it's there or using
-  a one-instruction loop.  The TSC produces twice the BogoMips as the
-  loop.  UML uses the loop, since it has nothing resembling a TSC, and
-  will get almost exactly the same BogoMips as a host using the loop.
-  However, on a host with a TSC, its BogoMips will be double the loop
-  BogoMips, and therefore double the UML BogoMips.
-
-
-
-  13.13.  When you run UML, it immediately segfaults
-
-  If the host is configured with the 2G/2G address space split, that's
-  why.  See ``UML on 2G/2G hosts''  for the details on getting UML to
-  run on your host.
-
-
-
-  13.14.  xterms appear, then immediately disappear
-
-  If you're running an up to date kernel with an old release of
-  uml_utilities, the port-helper program will not work properly, so
-  xterms will exit straight after they appear. The solution is to
-  upgrade to the latest release of uml_utilities.  Usually this problem
-  occurs when you have installed a packaged release of UML then compiled
-  your own development kernel without upgrading the uml_utilities from
-  the source distribution.
-
-
-
-  13.15.  Any other panic, hang, or strange behavior
-
-  If you're seeing truly strange behavior, such as hangs or panics that
-  happen in random places, or you try running the debugger to see what's
-  happening and it acts strangely, then it could be a problem in the
-  host kernel.  If you're not running a stock Linus or -ac kernel, then
-  try that.  An early version of the preemption patch and a 2.4.10 SuSE
-  kernel have caused very strange problems in UML.
-
-
-  Otherwise, let me know about it.  Send a message to one of the UML
-  mailing lists - either the developer list - user-mode-linux-devel at
-  lists dot sourceforge dot net (subscription info) or the user list -
-  user-mode-linux-user at lists dot sourceforge do net (subscription
-  info), whichever you prefer.  Don't assume that everyone knows about
-  it and that a fix is imminent.
-
-
-  If you want to be super-helpful, read ``Diagnosing Problems'' and
-  follow the instructions contained therein.
-  14.  Diagnosing Problems
-
-
-  If you get UML to crash, hang, or otherwise misbehave, you should
-  report this on one of the project mailing lists, either the developer
-  list - user-mode-linux-devel at lists dot sourceforge dot net
-  (subscription info) or the user list - user-mode-linux-user at lists
-  dot sourceforge dot net (subscription info).  When you do, it is
-  likely that I will want more information.  So, it would be helpful to
-  read the stuff below, do whatever is applicable in your case, and
-  report the results to the list.
-
-
-  For any diagnosis, you're going to need to build a debugging kernel.
-  The binaries from this site aren't debuggable.  If you haven't done
-  this before, read about ``Compiling the kernel and modules''  and
-  ``Kernel debugging''  UML first.
-
-
-  14.1.  Case 1 : Normal kernel panics
-
-  The most common case is for a normal thread to panic.  To debug this,
-  you will need to run it under the debugger (add 'debug' to the command
-  line).  An xterm will start up with gdb running inside it.  Continue
-  it when it stops in start_kernel and make it crash.  Now ^C gdb and
-
-
-  If the panic was a "Kernel mode fault", then there will be a segv
-  frame on the stack and I'm going to want some more information.  The
-  stack might look something like this:
-
-
-       (UML gdb)  backtrace
-       #0  0x1009bf76 in __sigprocmask (how=1, set=0x5f347940, oset=0x0)
-           at ../sysdeps/unix/sysv/linux/sigprocmask.c:49
-       #1  0x10091411 in change_sig (signal=10, on=1) at process.c:218
-       #2  0x10094785 in timer_handler (sig=26) at time_kern.c:32
-       #3  0x1009bf38 in __restore ()
-           at ../sysdeps/unix/sysv/linux/i386/sigaction.c:125
-       #4  0x1009534c in segv (address=8, ip=268849158, is_write=2, is_user=0)
-           at trap_kern.c:66
-       #5  0x10095c04 in segv_handler (sig=11) at trap_user.c:285
-       #6  0x1009bf38 in __restore ()
-
-
-
-
-  I'm going to want to see the symbol and line information for the value
-  of ip in the segv frame.  In this case, you would do the following:
-
-
-       (UML gdb)  i sym 268849158
-
-
-
-
-  and
-
-
-       (UML gdb)  i line *268849158
-
-
-
-
-  The reason for this is the __restore frame right above the segv_han-
-  dler frame is hiding the frame that actually segfaulted.  So, I have
-  to get that information from the faulting ip.
-
-
-  14.2.  Case 2 : Tracing thread panics
-
-  The less common and more painful case is when the tracing thread
-  panics.  In this case, the kernel debugger will be useless because it
-  needs a healthy tracing thread in order to work.  The first thing to
-  do is get a backtrace from the tracing thread.  This is done by
-  figuring out what its pid is, firing up gdb, and attaching it to that
-  pid.  You can figure out the tracing thread pid by looking at the
-  first line of the console output, which will look like this:
-
-
-       tracing thread pid = 15851
-
-
-
-
-  or by running ps on the host and finding the line that looks like
-  this:
-
-
-       jdike 15851 4.5 0.4 132568 1104 pts/0 S 21:34 0:05 ./linux [(tracing thread)]
-
-
-
-
-  If the panic was 'segfault in signals', then follow the instructions
-  above for collecting information about the location of the seg fault.
-
-
-  If the tracing thread flaked out all by itself, then send that
-  backtrace in and wait for our crack debugging team to fix the problem.
-
-
-  14.3.  Case 3 : Tracing thread panics caused by other threads
-
-  However, there are cases where the misbehavior of another thread
-  caused the problem.  The most common panic of this type is:
-
-
-       wait_for_stop failed to wait for  <pid>  to stop with  <signal number>
-
-
-
-
-  In this case, you'll need to get a backtrace from the process men-
-  tioned in the panic, which is complicated by the fact that the kernel
-  debugger is defunct and without some fancy footwork, another gdb can't
-  attach to it.  So, this is how the fancy footwork goes:
-
-  In a shell:
-
-
-       host% kill -STOP pid
-
-
-
-
-  Run gdb on the tracing thread as described in case 2 and do:
-
-
-       (host gdb)  call detach(pid)
-
-
-  If you get a segfault, do it again.  It always works the second time.
-
-  Detach from the tracing thread and attach to that other thread:
-
-
-       (host gdb)  detach
-
-
-
-
-
-
-       (host gdb)  attach pid
-
-
-
-
-  If gdb hangs when attaching to that process, go back to a shell and
-  do:
-
-
-       host%
-       kill -CONT pid
-
-
-
-
-  And then get the backtrace:
-
-
-       (host gdb)  backtrace
-
-
-
-
-
-  14.4.  Case 4 : Hangs
-
-  Hangs seem to be fairly rare, but they sometimes happen.  When a hang
-  happens, we need a backtrace from the offending process.  Run the
-  kernel debugger as described in case 1 and get a backtrace.  If the
-  current process is not the idle thread, then send in the backtrace.
-  You can tell that it's the idle thread if the stack looks like this:
-
-
-       #0  0x100b1401 in __libc_nanosleep ()
-       #1  0x100a2885 in idle_sleep (secs=10) at time.c:122
-       #2  0x100a546f in do_idle () at process_kern.c:445
-       #3  0x100a5508 in cpu_idle () at process_kern.c:471
-       #4  0x100ec18f in start_kernel () at init/main.c:592
-       #5  0x100a3e10 in start_kernel_proc (unused=0x0) at um_arch.c:71
-       #6  0x100a383f in signal_tramp (arg=0x100a3dd8) at trap_user.c:50
-
-
-
-
-  If this is the case, then some other process is at fault, and went to
-  sleep when it shouldn't have.  Run ps on the host and figure out which
-  process should not have gone to sleep and stayed asleep.  Then attach
-  to it with gdb and get a backtrace as described in case 3.
-
-
-
-
-
-
-  15.  Thanks
-
-
-  A number of people have helped this project in various ways, and this
-  page gives recognition where recognition is due.
-
-
-  If you're listed here and you would prefer a real link on your name,
-  or no link at all, instead of the despammed email address pseudo-link,
-  let me know.
-
-
-  If you're not listed here and you think maybe you should be, please
-  let me know that as well.  I try to get everyone, but sometimes my
-  bookkeeping lapses and I forget about contributions.
-
-
-  15.1.  Code and Documentation
-
-  Rusty Russell <rusty at linuxcare.com.au>  -
-
-  o  wrote the  HOWTO <http://user-mode-
-     linux.sourceforge.net/UserModeLinux-HOWTO.html>
-
-  o  prodded me into making this project official and putting it on
-     SourceForge
-
-  o  came up with the way cool UML logo <http://user-mode-
-     linux.sourceforge.net/uml-small.png>
-
-  o  redid the config process
-
-
-  Peter Moulder <reiter at netspace.net.au>  - Fixed my config and build
-  processes, and added some useful code to the block driver
-
-
-  Bill Stearns <wstearns at pobox.com>  -
-
-  o  HOWTO updates
-
-  o  lots of bug reports
-
-  o  lots of testing
-
-  o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
-
-  o  wrote the mkrootfs script, which allows bootable filesystems of
-     RPM-based distributions to be cranked out
-
-  o  cranked out a large number of filesystems with said script
-
-
-  Jim Leu <jleu at mindspring.com>  - Wrote the virtual ethernet driver
-  and associated usermode tools
-
-  Lars Brinkhoff <http://lars.nocrew.org/>  - Contributed the ptrace
-  proxy from his own  project <http://a386.nocrew.org/> to allow easier
-  kernel debugging
-
-
-  Andrea Arcangeli <andrea at suse.de>  - Redid some of the early boot
-  code so that it would work on machines with Large File Support
-
-
-  Chris Emerson <http://www.chiark.greenend.org.uk/~cemerson/>  - Did
-  the first UML port to Linux/ppc
-
-
-  Harald Welte <laforge at gnumonks.org>  - Wrote the multicast
-  transport for the network driver
-
-
-  Jorgen Cederlof - Added special file support to hostfs
-
-
-  Greg Lonnon  <glonnon at ridgerun dot com>  - Changed the ubd driver
-  to allow it to layer a COW file on a shared read-only filesystem and
-  wrote the iomem emulation support
-
-
-  Henrik Nordstrom <http://hem.passagen.se/hno/>  - Provided a variety
-  of patches, fixes, and clues
-
-
-  Lennert Buytenhek - Contributed various patches, a rewrite of the
-  network driver, the first implementation of the mconsole driver, and
-  did the bulk of the work needed to get SMP working again.
-
-
-  Yon Uriarte - Fixed the TUN/TAP network backend while I slept.
-
-
-  Adam Heath - Made a bunch of nice cleanups to the initialization code,
-  plus various other small patches.
-
-
-  Matt Zimmerman - Matt volunteered to be the UML Debian maintainer and
-  is doing a real nice job of it.  He also noticed and fixed a number of
-  actually and potentially exploitable security holes in uml_net.  Plus
-  the occasional patch.  I like patches.
-
-
-  James McMechan - James seems to have taken over maintenance of the ubd
-  driver and is doing a nice job of it.
-
-
-  Chandan Kudige - wrote the umlgdb script which automates the reloading
-  of module symbols.
-
-
-  Steve Schmidtke - wrote the UML slirp transport and hostaudio drivers,
-  enabling UML processes to access audio devices on the host. He also
-  submitted patches for the slip transport and lots of other things.
-
-
-  David Coulson <http://davidcoulson.net>  -
-
-  o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
-     which is a great way of keeping the UML user community on top of
-     UML goings-on.
-
-  o  Site documentation and updates
-
-  o  Nifty little UML management daemon  UMLd
-     <http://uml.openconsultancy.com/umld/>
-
-  o  Lots of testing and bug reports
-
-
-
-
-  15.2.  Flushing out bugs
-
-
-
-  o  Yuri Pudgorodsky
-
-  o  Gerald Britton
-
-  o  Ian Wehrman
-
-  o  Gord Lamb
-
-  o  Eugene Koontz
-
-  o  John H. Hartman
-
-  o  Anders Karlsson
-
-  o  Daniel Phillips
-
-  o  John Fremlin
-
-  o  Rainer Burgstaller
-
-  o  James Stevenson
-
-  o  Matt Clay
-
-  o  Cliff Jefferies
-
-  o  Geoff Hoff
-
-  o  Lennert Buytenhek
-
-  o  Al Viro
-
-  o  Frank Klingenhoefer
-
-  o  Livio Baldini Soares
-
-  o  Jon Burgess
-
-  o  Petru Paler
-
-  o  Paul
-
-  o  Chris Reahard
-
-  o  Sverker Nilsson
-
-  o  Gong Su
-
-  o  johan verrept
-
-  o  Bjorn Eriksson
-
-  o  Lorenzo Allegrucci
-
-  o  Muli Ben-Yehuda
-
-  o  David Mansfield
-
-  o  Howard Goff
-
-  o  Mike Anderson
-
-  o  John Byrne
-
-  o  Sapan J. Batia
-
-  o  Iris Huang
-
-  o  Jan Hudec
-
-  o  Voluspa
-
-
-
-
-  15.3.  Buglets and clean-ups
-
-
-
-  o  Dave Zarzycki
-
-  o  Adam Lazur
-
-  o  Boria Feigin
-
-  o  Brian J. Murrell
-
-  o  JS
-
-  o  Roman Zippel
-
-  o  Wil Cooley
-
-  o  Ayelet Shemesh
-
-  o  Will Dyson
-
-  o  Sverker Nilsson
-
-  o  dvorak
-
-  o  v.naga srinivas
-
-  o  Shlomi Fish
-
-  o  Roger Binns
-
-  o  johan verrept
-
-  o  MrChuoi
-
-  o  Peter Cleve
-
-  o  Vincent Guffens
-
-  o  Nathan Scott
-
-  o  Patrick Caulfield
-
-  o  jbearce
-
-  o  Catalin Marinas
-
-  o  Shane Spencer
-
-  o  Zou Min
-
-
-  o  Ryan Boder
-
-  o  Lorenzo Colitti
-
-  o  Gwendal Grignou
-
-  o  Andre' Breiler
-
-  o  Tsutomu Yasuda
-
-
-
-  15.4.  Case Studies
-
-
-  o  Jon Wright
-
-  o  William McEwan
-
-  o  Michael Richardson
-
-
-
-  15.5.  Other contributions
-
-
-  Bill Carr <Bill.Carr at compaq.com>  made the Red Hat mkrootfs script
-  work with RH 6.2.
-
-  Michael Jennings <mikejen at hevanet.com>  sent in some material which
-  is now gracing the top of the  index  page <http://user-mode-
-  linux.sourceforge.net/>  of this site.
-
-  SGI <http://www.sgi.com>  (and more specifically Ralf Baechle <ralf at
-  uni-koblenz.de> ) gave me an account on oss.sgi.com
-  <http://www.oss.sgi.com> .  The bandwidth there made it possible to
-  produce most of the filesystems available on the project download
-  page.
-
-  Laurent Bonnaud <Laurent.Bonnaud at inpg.fr>  took the old grotty
-  Debian filesystem that I've been distributing and updated it to 2.2.
-  It is now available by itself here.
-
-  Rik van Riel gave me some ftp space on ftp.nl.linux.org so I can make
-  releases even when Sourceforge is broken.
-
-  Rodrigo de Castro looked at my broken pte code and told me what was
-  wrong with it, letting me fix a long-standing (several weeks) and
-  serious set of bugs.
-
-  Chris Reahard built a specialized root filesystem for running a DNS
-  server jailed inside UML.  It's available from the download
-  <http://user-mode-linux.sourceforge.net/dl-sf.html>  page in the Jail
-  Filesystems section.
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Documentation/vm/conf.py b/Documentation/vm/conf.py
deleted file mode 100644 (file)
index 3b0b601..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux Memory Management Documentation"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'memory-management.tex', project,
-     'The kernel development community', 'manual'),
-]
index 7d90964abbb0fb87ff438024bbc2a0411b313639..710ce1c701bf3a0f50809332a9ef4868666dabd4 100644 (file)
@@ -237,7 +237,7 @@ The usage pattern is::
       ret = hmm_range_snapshot(&range);
       if (ret) {
           up_read(&mm->mmap_sem);
-          if (ret == -EAGAIN) {
+          if (ret == -EBUSY) {
             /*
              * No need to check hmm_range_wait_until_valid() return value
              * on retry we will get proper error with hmm_range_snapshot()
index c165d92cfd12052a25f7af3ef169115abe590e08..c824cd7f6e322fb7d2002d387f5190b345d2d04c 100644 (file)
@@ -63,7 +63,7 @@ Last reviewed: 08/20/2018
  and loop forever.  This is generally not what a watchdog user wants.
 
  For those wishing to learn more please see:
-       Documentation/kdump/kdump.rst
+       Documentation/admin-guide/kdump/kdump.rst
        Documentation/admin-guide/kernel-parameters.txt (panic=)
        Your Linux Distribution specific documentation.
 
diff --git a/Documentation/x86/conf.py b/Documentation/x86/conf.py
deleted file mode 100644 (file)
index 33c5c31..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "X86 architecture specific documentation"
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'x86.tex', project,
-     'The kernel development community', 'manual'),
-]
index 59df8f88b56de121d4e342d6610a8bdefabdcbde..8644a66a8db573c13f75114dd7f670be840d2e7b 100644 (file)
@@ -183,7 +183,7 @@ M:  Realtek linux nic maintainers <nic_swsd@realtek.com>
 M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ethernet/realtek/r8169.c
+F:     drivers/net/ethernet/realtek/r8169*
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -683,7 +683,7 @@ S:  Maintained
 F:     drivers/crypto/sunxi-ss/
 
 ALLWINNER VPU DRIVER
-M:     Maxime Ripard <maxime.ripard@bootlin.com>
+M:     Maxime Ripard <mripard@kernel.org>
 M:     Paul Kocialkowski <paul.kocialkowski@bootlin.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
@@ -899,7 +899,7 @@ L:  linux-iio@vger.kernel.org
 W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/iio/adc/ad7124.c
-F:     Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt
+F:     Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml
 
 ANALOG DEVICES INC AD7606 DRIVER
 M:     Stefan Popa <stefan.popa@analog.com>
@@ -1194,7 +1194,7 @@ F:        include/uapi/linux/if_arcnet.h
 
 ARM ARCHITECTED TIMER DRIVER
 M:     Mark Rutland <mark.rutland@arm.com>
-M:     Marc Zyngier <marc.zyngier@arm.com>
+M:     Marc Zyngier <maz@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/include/asm/arch_timer.h
@@ -1408,7 +1408,7 @@ S:        Maintained
 F:     drivers/clk/sunxi/
 
 ARM/Allwinner sunXi SoC support
-M:     Maxime Ripard <maxime.ripard@bootlin.com>
+M:     Maxime Ripard <mripard@kernel.org>
 M:     Chen-Yu Tsai <wens@csie.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
@@ -2155,10 +2155,12 @@ F:      Documentation/devicetree/bindings/arm/realtek.txt
 
 ARM/RENESAS ARM64 ARCHITECTURE
 M:     Simon Horman <horms@verge.net.au>
+M:     Geert Uytterhoeven <geert+renesas@glider.be>
 M:     Magnus Damm <magnus.damm@gmail.com>
 L:     linux-renesas-soc@vger.kernel.org
 Q:     http://patchwork.kernel.org/project/linux-renesas-soc/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next
 S:     Supported
 F:     arch/arm64/boot/dts/renesas/
 F:     Documentation/devicetree/bindings/arm/renesas.yaml
@@ -2269,10 +2271,12 @@ F:      drivers/media/platform/s5p-mfc/
 
 ARM/SHMOBILE ARM ARCHITECTURE
 M:     Simon Horman <horms@verge.net.au>
+M:     Geert Uytterhoeven <geert+renesas@glider.be>
 M:     Magnus Damm <magnus.damm@gmail.com>
 L:     linux-renesas-soc@vger.kernel.org
 Q:     http://patchwork.kernel.org/project/linux-renesas-soc/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next
 S:     Supported
 F:     arch/arm/boot/dts/emev2*
 F:     arch/arm/boot/dts/gr-peach*
@@ -3573,7 +3577,7 @@ F:        Documentation/filesystems/caching/cachefiles.txt
 F:     fs/cachefiles/
 
 CADENCE MIPI-CSI2 BRIDGES
-M:     Maxime Ripard <maxime.ripard@bootlin.com>
+M:     Maxime Ripard <mripard@kernel.org>
 L:     linux-media@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/media/cdns,*.txt
@@ -4190,7 +4194,7 @@ M:        Jens Axboe <axboe@kernel.dk>
 L:     cgroups@vger.kernel.org
 L:     linux-block@vger.kernel.org
 T:     git git://git.kernel.dk/linux-block
-F:     Documentation/cgroup-v1/blkio-controller.rst
+F:     Documentation/admin-guide/cgroup-v1/blkio-controller.rst
 F:     block/blk-cgroup.c
 F:     include/linux/blk-cgroup.h
 F:     block/blk-throttle.c
@@ -4469,7 +4473,7 @@ F:        arch/powerpc/platforms/powernv/pci-cxl.c
 F:     drivers/misc/cxl/
 F:     include/misc/cxl*
 F:     include/uapi/misc/cxl.h
-F:     Documentation/powerpc/cxl.txt
+F:     Documentation/powerpc/cxl.rst
 F:     Documentation/ABI/testing/sysfs-class-cxl
 
 CXLFLASH (IBM Coherent Accelerator Processor Interface CAPI Flash) SCSI DRIVER
@@ -4480,7 +4484,7 @@ L:        linux-scsi@vger.kernel.org
 S:     Supported
 F:     drivers/scsi/cxlflash/
 F:     include/uapi/scsi/cxlflash_ioctl.h
-F:     Documentation/powerpc/cxlflash.txt
+F:     Documentation/powerpc/cxlflash.rst
 
 CYBERPRO FB DRIVER
 M:     Russell King <linux@armlinux.org.uk>
@@ -5291,7 +5295,7 @@ F:        include/linux/vga*
 
 DRM DRIVERS AND MISC GPU PATCHES
 M:     Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-M:     Maxime Ripard <maxime.ripard@bootlin.com>
+M:     Maxime Ripard <mripard@kernel.org>
 M:     Sean Paul <sean@poorly.run>
 W:     https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
 S:     Maintained
@@ -5304,7 +5308,7 @@ F:        include/uapi/drm/drm*
 F:     include/linux/vga*
 
 DRM DRIVERS FOR ALLWINNER A10
-M:     Maxime Ripard  <maxime.ripard@bootlin.com>
+M:     Maxime Ripard <mripard@kernel.org>
 L:     dri-devel@lists.freedesktop.org
 S:     Supported
 F:     drivers/gpu/drm/sun4i/
@@ -6061,7 +6065,7 @@ M:        Florian Fainelli <f.fainelli@gmail.com>
 M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     Documentation/ABI/testing/sysfs-bus-mdio
+F:     Documentation/ABI/testing/sysfs-class-net-phydev
 F:     Documentation/devicetree/bindings/net/ethernet-phy.yaml
 F:     Documentation/devicetree/bindings/net/mdio*
 F:     Documentation/networking/phy.rst
@@ -6322,7 +6326,8 @@ F:        Documentation/devicetree/bindings/counter/ftm-quaddec.txt
 F:     drivers/counter/ftm-quaddec.c
 
 FLOPPY DRIVER
-S:     Orphan
+M:     Denis Efremov <efremov@linux.com>
+S:     Odd Fixes
 L:     linux-block@vger.kernel.org
 F:     drivers/block/floppy.c
 
@@ -6339,7 +6344,7 @@ FPGA MANAGER FRAMEWORK
 M:     Moritz Fischer <mdf@kernel.org>
 L:     linux-fpga@vger.kernel.org
 S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga.git
 Q:     http://patchwork.kernel.org/project/linux-fpga/list/
 F:     Documentation/fpga/
 F:     Documentation/driver-api/fpga/
@@ -6372,7 +6377,7 @@ FRAMEBUFFER LAYER
 M:     Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
 L:     dri-devel@lists.freedesktop.org
 L:     linux-fbdev@vger.kernel.org
-T:     git git://github.com/bzolnier/linux.git
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 Q:     http://patchwork.kernel.org/project/linux-fbdev/list/
 S:     Maintained
 F:     Documentation/fb/
@@ -6436,6 +6441,14 @@ S:       Maintained
 F:     drivers/perf/fsl_imx8_ddr_perf.c
 F:     Documentation/devicetree/bindings/perf/fsl-imx-ddr.txt
 
+FREESCALE IMX I2C DRIVER
+M:     Oleksij Rempel <o.rempel@pengutronix.de>
+R:     Pengutronix Kernel Team <kernel@pengutronix.de>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     drivers/i2c/busses/i2c-imx.c
+F:     Documentation/devicetree/bindings/i2c/i2c-imx.txt
+
 FREESCALE IMX LPI2C DRIVER
 M:     Dong Aisheng <aisheng.dong@nxp.com>
 L:     linux-i2c@vger.kernel.org
@@ -6822,13 +6835,6 @@ F:       Documentation/filesystems/gfs2*.txt
 F:     fs/gfs2/
 F:     include/uapi/linux/gfs2_ondisk.h
 
-GIGASET ISDN DRIVERS
-M:     Paul Bolle <pebolle@tiscali.nl>
-L:     gigaset307x-common@lists.sourceforge.net
-W:     http://gigaset307x.sourceforge.net/
-S:     Odd Fixes
-F:     drivers/staging/isdn/gigaset/
-
 GNSS SUBSYSTEM
 M:     Johan Hovold <johan@kernel.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/johan/gnss.git
@@ -6856,7 +6862,7 @@ R:        Sagi Shahar <sagis@google.com>
 R:     Jon Olson <jonolson@google.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     Documentation/networking/device_drivers/google/gve.txt
+F:     Documentation/networking/device_drivers/google/gve.rst
 F:     drivers/net/ethernet/google
 
 GPD POCKET FAN DRIVER
@@ -7454,7 +7460,7 @@ F:        drivers/net/hyperv/
 F:     drivers/scsi/storvsc_drv.c
 F:     drivers/uio/uio_hv_generic.c
 F:     drivers/video/fbdev/hyperv_fb.c
-F:     drivers/iommu/hyperv_iommu.c
+F:     drivers/iommu/hyperv-iommu.c
 F:     net/vmw_vsock/hyperv_transport.c
 F:     include/clocksource/hyperv_timer.h
 F:     include/linux/hyperv.h
@@ -7507,7 +7513,7 @@ I2C MV64XXX MARVELL AND ALLWINNER DRIVER
 M:     Gregory CLEMENT <gregory.clement@bootlin.com>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
+F:     Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
 F:     drivers/i2c/busses/i2c-mv64xxx.c
 
 I2C OVER PARALLEL PORT
@@ -8044,6 +8050,7 @@ S:        Maintained
 F:     drivers/video/fbdev/i810/
 
 INTEL ASoC DRIVERS
+M:     Cezary Rojewski <cezary.rojewski@intel.com>
 M:     Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
 M:     Liam Girdwood <liam.r.girdwood@linux.intel.com>
 M:     Jie Yang <yang.jie@linux.intel.com>
@@ -8065,6 +8072,13 @@ T:       git git://git.code.sf.net/p/intel-sas/isci
 S:     Supported
 F:     drivers/scsi/isci/
 
+INTEL CPU family model numbers
+M:     Tony Luck <tony.luck@intel.com>
+M:     x86@kernel.org
+L:     linux-kernel@vger.kernel.org
+S:     Supported
+F:     arch/x86/include/asm/intel-family.h
+
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Jani Nikula <jani.nikula@linux.intel.com>
 M:     Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
@@ -8416,7 +8430,6 @@ L:        linux-xfs@vger.kernel.org
 L:     linux-fsdevel@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
 S:     Supported
-F:     fs/iomap.c
 F:     fs/iomap/
 F:     include/linux/iomap.h
 
@@ -8441,11 +8454,6 @@ S:       Maintained
 F:     fs/io_uring.c
 F:     include/uapi/linux/io_uring.h
 
-IP MASQUERADING
-M:     Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
-S:     Maintained
-F:     net/ipv4/netfilter/ipt_MASQUERADE.c
-
 IPMI SUBSYSTEM
 M:     Corey Minyard <minyard@acm.org>
 L:     openipmi-developer@lists.sourceforge.net (moderated for non-subscribers)
@@ -8490,7 +8498,7 @@ S:        Obsolete
 F:     include/uapi/linux/ipx.h
 
 IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
-M:     Marc Zyngier <marc.zyngier@arm.com>
+M:     Marc Zyngier <maz@kernel.org>
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
 F:     Documentation/IRQ-domain.txt
@@ -8508,7 +8516,7 @@ F:        kernel/irq/
 IRQCHIP DRIVERS
 M:     Thomas Gleixner <tglx@linutronix.de>
 M:     Jason Cooper <jason@lakedaemon.net>
-M:     Marc Zyngier <marc.zyngier@arm.com>
+M:     Marc Zyngier <maz@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
@@ -8808,7 +8816,7 @@ L:        kvm@vger.kernel.org
 W:     http://www.linux-kvm.org
 T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
 S:     Supported
-F:     Documentation/virtual/kvm/
+F:     Documentation/virt/kvm/
 F:     include/trace/events/kvm.h
 F:     include/uapi/asm-generic/kvm*
 F:     include/uapi/linux/kvm*
@@ -8819,19 +8827,11 @@ F:      virt/kvm/*
 F:     tools/kvm/
 F:     tools/testing/selftests/kvm/
 
-KERNEL VIRTUAL MACHINE FOR AMD-V (KVM/amd)
-M:     Joerg Roedel <joro@8bytes.org>
-L:     kvm@vger.kernel.org
-W:     http://www.linux-kvm.org/
-S:     Maintained
-F:     arch/x86/include/asm/svm.h
-F:     arch/x86/kvm/svm.c
-
 KERNEL VIRTUAL MACHINE FOR ARM/ARM64 (KVM/arm, KVM/arm64)
-M:     Marc Zyngier <marc.zyngier@arm.com>
+M:     Marc Zyngier <maz@kernel.org>
 R:     James Morse <james.morse@arm.com>
-R:     Julien Thierry <julien.thierry@arm.com>
-R:     Suzuki K Pouloze <suzuki.poulose@arm.com>
+R:     Julien Thierry <julien.thierry.kdev@gmail.com>
+R:     Suzuki K Poulose <suzuki.poulose@arm.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     kvmarm@lists.cs.columbia.edu
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
@@ -8869,7 +8869,7 @@ M:        Christian Borntraeger <borntraeger@de.ibm.com>
 M:     Janosch Frank <frankja@linux.ibm.com>
 R:     David Hildenbrand <david@redhat.com>
 R:     Cornelia Huck <cohuck@redhat.com>
-L:     linux-s390@vger.kernel.org
+L:     kvm@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
 S:     Supported
@@ -8884,6 +8884,11 @@ F:       tools/testing/selftests/kvm/*/s390x/
 KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86)
 M:     Paolo Bonzini <pbonzini@redhat.com>
 M:     Radim Krčmář <rkrcmar@redhat.com>
+R:     Sean Christopherson <sean.j.christopherson@intel.com>
+R:     Vitaly Kuznetsov <vkuznets@redhat.com>
+R:     Wanpeng Li <wanpengli@tencent.com>
+R:     Jim Mattson <jmattson@google.com>
+R:     Joerg Roedel <joro@8bytes.org>
 L:     kvm@vger.kernel.org
 W:     http://www.linux-kvm.org
 T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
@@ -8891,8 +8896,12 @@ S:       Supported
 F:     arch/x86/kvm/
 F:     arch/x86/kvm/*/
 F:     arch/x86/include/uapi/asm/kvm*
+F:     arch/x86/include/uapi/asm/vmx.h
+F:     arch/x86/include/uapi/asm/svm.h
 F:     arch/x86/include/asm/kvm*
 F:     arch/x86/include/asm/pvclock-abi.h
+F:     arch/x86/include/asm/svm.h
+F:     arch/x86/include/asm/vmx.h
 F:     arch/x86/kernel/kvm.c
 F:     arch/x86/kernel/kvmclock.c
 
@@ -9220,6 +9229,18 @@ F:       include/linux/nd.h
 F:     include/linux/libnvdimm.h
 F:     include/uapi/linux/ndctl.h
 
+LICENSES and SPDX stuff
+M:     Thomas Gleixner <tglx@linutronix.de>
+M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+L:     linux-spdx@vger.kernel.org
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/spdx.git
+F:     COPYING
+F:     Documentation/process/license-rules.rst
+F:     LICENSES/
+F:     scripts/spdxcheck-test.sh
+F:     scripts/spdxcheck.py
+
 LIGHTNVM PLATFORM SUPPORT
 M:     Matias Bjorling <mb@lightnvm.io>
 W:     http://github/OpenChannelSSD
@@ -11072,7 +11093,7 @@ NET_FAILOVER MODULE
 M:     Sridhar Samudrala <sridhar.samudrala@intel.com>
 L:     netdev@vger.kernel.org
 S:     Supported
-F:     driver/net/net_failover.c
+F:     drivers/net/net_failover.c
 F:     include/net/net_failover.h
 F:     Documentation/networking/net_failover.rst
 
@@ -11144,6 +11165,7 @@ L:      netdev@vger.kernel.org
 S:     Maintained
 W:     https://fedorahosted.org/dropwatch/
 F:     net/core/drop_monitor.c
+F:     include/uapi/linux/net_dropmon.h
 
 NETWORKING DRIVERS
 M:     "David S. Miller" <davem@davemloft.net>
@@ -11282,6 +11304,7 @@ M:      Aviad Yehezkel <aviadye@mellanox.com>
 M:     Dave Watson <davejwatson@fb.com>
 M:     John Fastabend <john.fastabend@gmail.com>
 M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     Jakub Kicinski <jakub.kicinski@netronome.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     net/tls/*
@@ -12137,7 +12160,7 @@ M:      Thomas Hellstrom <thellstrom@vmware.com>
 M:     "VMware, Inc." <pv-drivers@vmware.com>
 L:     virtualization@lists.linux-foundation.org
 S:     Supported
-F:     Documentation/virtual/paravirt_ops.txt
+F:     Documentation/virt/paravirt_ops.rst
 F:     arch/*/kernel/paravirt*
 F:     arch/*/include/asm/paravirt*.h
 F:     include/linux/hypervisor.h
@@ -12394,7 +12417,7 @@ F:      Documentation/PCI/pci-error-recovery.rst
 F:     drivers/pci/pcie/aer.c
 F:     drivers/pci/pcie/dpc.c
 F:     drivers/pci/pcie/err.c
-F:     Documentation/powerpc/eeh-pci-error-recovery.txt
+F:     Documentation/powerpc/eeh-pci-error-recovery.rst
 F:     arch/powerpc/kernel/eeh*.c
 F:     arch/powerpc/platforms/*/eeh*.c
 F:     arch/powerpc/include/*/eeh*.h
@@ -13725,6 +13748,7 @@ F:      drivers/mtd/nand/raw/r852.c
 F:     drivers/mtd/nand/raw/r852.h
 
 RISC-V ARCHITECTURE
+M:     Paul Walmsley <paul.walmsley@sifive.com>
 M:     Palmer Dabbelt <palmer@sifive.com>
 M:     Albert Ou <aou@eecs.berkeley.edu>
 L:     linux-riscv@lists.infradead.org
@@ -13947,7 +13971,6 @@ F:      drivers/pci/hotplug/s390_pci_hpc.c
 
 S390 VFIO-CCW DRIVER
 M:     Cornelia Huck <cohuck@redhat.com>
-M:     Farhan Ali <alifm@linux.ibm.com>
 M:     Eric Farman <farman@linux.ibm.com>
 R:     Halil Pasic <pasic@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
@@ -14016,6 +14039,12 @@ F:     drivers/media/common/saa7146/
 F:     drivers/media/pci/saa7146/
 F:     include/media/drv-intf/saa7146*
 
+SAFESETID SECURITY MODULE
+M:     Micah Morton <mortonm@chromium.org>
+S:     Supported
+F:     security/safesetid/
+F:     Documentation/admin-guide/LSM/SafeSetID.rst
+
 SAMSUNG AUDIO (ASoC) DRIVERS
 M:     Krzysztof Kozlowski <krzk@kernel.org>
 M:     Sangbeom Kim <sbkim73@samsung.com>
@@ -14456,6 +14485,7 @@ F:      drivers/net/phy/phylink.c
 F:     drivers/net/phy/sfp*
 F:     include/linux/phylink.h
 F:     include/linux/sfp.h
+K:     phylink
 
 SGI GRU DRIVER
 M:     Dimitri Sivanich <sivanich@sgi.com>
@@ -14861,9 +14891,9 @@ F:      include/linux/arm_sdei.h
 F:     include/uapi/linux/arm_sdei.h
 
 SOFTWARE RAID (Multiple Disks) SUPPORT
-M:     Shaohua Li <shli@kernel.org>
+M:     Song Liu <song@kernel.org>
 L:     linux-raid@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shli/md.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/song/md.git
 S:     Supported
 F:     drivers/md/Makefile
 F:     drivers/md/Kconfig
@@ -16079,7 +16109,7 @@ S:      Maintained
 F:     drivers/net/ethernet/ti/netcp*
 
 TI PCM3060 ASoC CODEC DRIVER
-M:     Kirill Marinushkin <kmarinushkin@birdec.tech>
+M:     Kirill Marinushkin <kmarinushkin@birdec.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/sound/pcm3060.txt
@@ -16855,7 +16885,7 @@ W:      http://user-mode-linux.sourceforge.net
 Q:     https://patchwork.ozlabs.org/project/linux-um/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml.git
 S:     Maintained
-F:     Documentation/virtual/uml/
+F:     Documentation/virt/uml/
 F:     arch/um/
 F:     arch/x86/um/
 F:     fs/hostfs/
@@ -17124,7 +17154,7 @@ F:      drivers/virtio/virtio_input.c
 F:     include/uapi/linux/virtio_input.h
 
 VIRTIO IOMMU DRIVER
-M:     Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+M:     Jean-Philippe Brucker <jean-philippe@linaro.org>
 L:     virtualization@lists.linux-foundation.org
 S:     Maintained
 F:     drivers/iommu/virtio-iommu.c
@@ -17173,7 +17203,6 @@ F:      drivers/vme/
 F:     include/linux/vme*
 
 VMWARE BALLOON DRIVER
-M:     Julien Freche <jfreche@vmware.com>
 M:     Nadav Amit <namit@vmware.com>
 M:     "VMware, Inc." <pv-drivers@vmware.com>
 L:     linux-kernel@vger.kernel.org
@@ -17556,7 +17585,6 @@ M:      Jakub Kicinski <jakub.kicinski@netronome.com>
 M:     Jesper Dangaard Brouer <hawk@kernel.org>
 M:     John Fastabend <john.fastabend@gmail.com>
 L:     netdev@vger.kernel.org
-L:     xdp-newbies@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
 F:     net/core/xdp.c
@@ -17672,8 +17700,7 @@ F:      include/uapi/linux/dqblk_xfs.h
 F:     include/uapi/linux/fsmap.h
 
 XILINX AXI ETHERNET DRIVER
-M:     Anirudha Sarangi <anirudh@xilinx.com>
-M:     John Linn <John.Linn@xilinx.com>
+M:     Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
 S:     Maintained
 F:     drivers/net/ethernet/xilinx/xilinx_axienet*
 
index 9be5834073f8937f5ceb358e620af0795243b56d..6886f22902c9cbff2f5640f0f72bfc08d0ef4356 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION =
 NAME = Bobtail Squid
 
 # *DOCUMENTATION*
@@ -419,6 +419,7 @@ NM          = $(CROSS_COMPILE)nm
 STRIP          = $(CROSS_COMPILE)strip
 OBJCOPY                = $(CROSS_COMPILE)objcopy
 OBJDUMP                = $(CROSS_COMPILE)objdump
+OBJSIZE                = $(CROSS_COMPILE)size
 PAHOLE         = pahole
 LEX            = flex
 YACC           = bison
@@ -472,11 +473,12 @@ KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 KBUILD_LDFLAGS :=
 GCC_PLUGINS_CFLAGS :=
+CLANG_FLAGS :=
 
 export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
-export CPP AR NM STRIP OBJCOPY OBJDUMP PAHOLE KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS
-export MAKE LEX YACC AWK INSTALLKERNEL PERL PYTHON PYTHON2 PYTHON3 UTS_MACHINE
-export HOSTCXX KBUILD_HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL
+export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
+export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
 
 export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
 export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
@@ -519,7 +521,7 @@ endif
 
 ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
 ifneq ($(CROSS_COMPILE),)
-CLANG_FLAGS    := --target=$(notdir $(CROSS_COMPILE:%-=%))
+CLANG_FLAGS    += --target=$(notdir $(CROSS_COMPILE:%-=%))
 GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
 CLANG_FLAGS    += --prefix=$(GCC_TOOLCHAIN_DIR)
 GCC_TOOLCHAIN  := $(realpath $(GCC_TOOLCHAIN_DIR)/..)
@@ -843,6 +845,9 @@ NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 # warn about C99 declaration after statement
 KBUILD_CFLAGS += -Wdeclaration-after-statement
 
+# Warn about unmarked fall-throughs in switch statement.
+KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,)
+
 # Variable Length Arrays (VLAs) should not be used anywhere in the kernel
 KBUILD_CFLAGS += -Wvla
 
@@ -998,6 +1003,8 @@ endif
 
 PHONY += prepare0
 
+export MODORDER := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order
+
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
 
@@ -1767,13 +1774,22 @@ build-dir = $(patsubst %/,%,$(dir $(build-target)))
        $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
 %.symtypes: prepare FORCE
        $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
+ifeq ($(KBUILD_EXTMOD),)
+# For the single build of an in-tree module, use a temporary file to avoid
+# the situation of modules_install installing an invalid modules.order.
+%.ko: MODORDER := .modules.tmp
+endif
+%.ko: prepare FORCE
+       $(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod)
+       $(Q)echo $(build-target) > $(MODORDER)
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
 
 # Modules
 PHONY += /
 /: ./
 
 %/: prepare FORCE
-       $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir)
+       $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1
 
 # FIXME Should go into a make.lib or something
 # ===========================================================================
index a83c4f5e928b3957f2e1f9113cfa856acc19a065..8483a86c743d409872c94c3af8e34ce39ec8a772 100644 (file)
@@ -12,3 +12,6 @@ dtb-y := $(builtindtb-y).dtb
 # for CONFIG_OF_ALL_DTBS test
 dtstree        := $(srctree)/$(src)
 dtb-   := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
+
+# board-specific dtc flags
+DTC_FLAGS_hsdk += --pad 20
index f5ae394ebe067028bd9076dbd5075068a589390c..41b16f21beecac28099ed7ee154db6947b6b0d14 100644 (file)
 
 .macro FAKE_RET_FROM_EXCPN
        lr      r9, [status32]
-       bic     r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
+       bic     r9, r9, STATUS_AE_MASK
        or      r9, r9, STATUS_IE_MASK
        kflag   r9
 .endm
index a0eeb9f8f0a90fc5a9834b2faf4d4445a3dbcde3..d9ee43c6b7dbc2c698960365e8bbe78d0f087ddb 100644 (file)
 #else  /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_ARC_HAS_ICCM
-#define __arcfp_code __attribute__((__section__(".text.arcfp")))
+#define __arcfp_code __section(.text.arcfp)
 #else
-#define __arcfp_code __attribute__((__section__(".text")))
+#define __arcfp_code __section(.text)
 #endif
 
 #ifdef CONFIG_ARC_HAS_DCCM
-#define __arcfp_data __attribute__((__section__(".data.arcfp")))
+#define __arcfp_data __section(.data.arcfp)
 #else
-#define __arcfp_data __attribute__((__section__(".data")))
+#define __arcfp_data __section(.data)
 #endif
 
 #endif /* __ASSEMBLY__ */
index 8ac0e2ac3e70614c6f90d06989980fec8b333841..73746ed5b834dd9d8a4d91fb6cb337c51b3306c8 100644 (file)
@@ -53,8 +53,7 @@ extern const struct machine_desc __arch_info_begin[], __arch_info_end[];
  */
 #define MACHINE_START(_type, _name)                    \
 static const struct machine_desc __mach_desc_##_type   \
-__used                                                 \
-__attribute__((__section__(".arch.info.init"))) = {    \
+__used __section(.arch.info.init) = {                  \
        .name           = _name,
 
 #define MACHINE_END                            \
index 18b493dfb3a83941e8049b537785e629f63337dc..abf9398cc333acb9a8dee9709e54f589c67aec8f 100644 (file)
@@ -202,8 +202,8 @@ static void idu_set_dest(unsigned int cmn_irq, unsigned int cpu_mask)
        __mcip_cmd_data(CMD_IDU_SET_DEST, cmn_irq, cpu_mask);
 }
 
-static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
-                          unsigned int distr)
+static void idu_set_mode(unsigned int cmn_irq, bool set_lvl, unsigned int lvl,
+                        bool set_distr, unsigned int distr)
 {
        union {
                unsigned int word;
@@ -212,8 +212,11 @@ static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
                };
        } data;
 
-       data.distr = distr;
-       data.lvl = lvl;
+       data.word = __mcip_cmd_read(CMD_IDU_READ_MODE, cmn_irq);
+       if (set_distr)
+               data.distr = distr;
+       if (set_lvl)
+               data.lvl = lvl;
        __mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
 }
 
@@ -240,6 +243,25 @@ static void idu_irq_unmask(struct irq_data *data)
        raw_spin_unlock_irqrestore(&mcip_lock, flags);
 }
 
+static void idu_irq_ack(struct irq_data *data)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+       __mcip_cmd(CMD_IDU_ACK_CIRQ, data->hwirq);
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+}
+
+static void idu_irq_mask_ack(struct irq_data *data)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+       __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
+       __mcip_cmd(CMD_IDU_ACK_CIRQ, data->hwirq);
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+}
+
 static int
 idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
                     bool force)
@@ -263,13 +285,36 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
        else
                distribution_mode = IDU_M_DISTRI_RR;
 
-       idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode);
+       idu_set_mode(data->hwirq, false, 0, true, distribution_mode);
 
        raw_spin_unlock_irqrestore(&mcip_lock, flags);
 
        return IRQ_SET_MASK_OK;
 }
 
+static int idu_irq_set_type(struct irq_data *data, u32 type)
+{
+       unsigned long flags;
+
+       /*
+        * ARCv2 IDU HW does not support inverse polarity, so these are the
+        * only interrupt types supported.
+        */
+       if (type & ~(IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+               return -EINVAL;
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+
+       idu_set_mode(data->hwirq, true,
+                    type & IRQ_TYPE_EDGE_RISING ? IDU_M_TRIG_EDGE :
+                                                  IDU_M_TRIG_LEVEL,
+                    false, 0);
+
+       raw_spin_unlock_irqrestore(&mcip_lock, flags);
+
+       return 0;
+}
+
 static void idu_irq_enable(struct irq_data *data)
 {
        /*
@@ -289,7 +334,10 @@ static struct irq_chip idu_irq_chip = {
        .name                   = "MCIP IDU Intc",
        .irq_mask               = idu_irq_mask,
        .irq_unmask             = idu_irq_unmask,
+       .irq_ack                = idu_irq_ack,
+       .irq_mask_ack           = idu_irq_mask_ack,
        .irq_enable             = idu_irq_enable,
+       .irq_set_type           = idu_irq_set_type,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = idu_irq_set_affinity,
 #endif
@@ -317,7 +365,7 @@ static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t
 }
 
 static const struct irq_domain_ops idu_irq_ops = {
-       .xlate  = irq_domain_xlate_onecell,
+       .xlate  = irq_domain_xlate_onetwocell,
        .map    = idu_irq_map,
 };
 
index c2663fce7f6c8c43c5085dd3c139f3001879590a..dc05a63516f5b5a3c695578cd864b2f3886910ba 100644 (file)
@@ -572,6 +572,7 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end,
 #else
                BUILD_BUG_ON(sizeof(u32) != sizeof(value));
 #endif
+               /* Fall through */
        case DW_EH_PE_native:
                if (end < (const void *)(ptr.pul + 1))
                        return 0;
@@ -826,7 +827,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
                        case DW_CFA_def_cfa:
                                state->cfa.reg = get_uleb128(&ptr.p8, end);
                                unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
-                               /*nobreak*/
+                               /* fall through */
                        case DW_CFA_def_cfa_offset:
                                state->cfa.offs = get_uleb128(&ptr.p8, end);
                                unw_debug("cfa_def_cfa_offset: 0x%lx ",
@@ -834,7 +835,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
                                break;
                        case DW_CFA_def_cfa_sf:
                                state->cfa.reg = get_uleb128(&ptr.p8, end);
-                               /*nobreak */
+                               /* fall through */
                        case DW_CFA_def_cfa_offset_sf:
                                state->cfa.offs = get_sleb128(&ptr.p8, end)
                                    * state->dataAlign;
index 62c210e7ee4cdc5046b422d819a997e03134652f..70a3fbe79fbaa2affaefdec0c10afcbcc05f96d7 100644 (file)
@@ -101,7 +101,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
        if (is_isa_arcv2() && ioc_enable && coherent)
                dev->dma_coherent = true;
 
-       dev_info(dev, "use %sncoherent DMA ops\n",
+       dev_info(dev, "use %scoherent DMA ops\n",
                 dev->dma_coherent ? "" : "non");
 }
 
index 7dd2dd335cf66ef321bc5d6389a732cf9e68788d..0b961a2a10b8efb525ba0ffa980e6eab74e057c5 100644 (file)
@@ -6,11 +6,15 @@
  */
 
 #include <linux/init.h>
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
 #include <linux/smp.h>
 #include <asm/arcregs.h>
 #include <asm/io.h>
 #include <asm/mach_desc.h>
 
+int arc_hsdk_axi_dmac_coherent __section(.data) = 0;
+
 #define ARC_CCM_UNUSED_ADDR    0x60000000
 
 static void __init hsdk_init_per_cpu(unsigned int cpu)
@@ -97,6 +101,42 @@ static void __init hsdk_enable_gpio_intc_wire(void)
        iowrite32(GPIO_INT_CONNECTED_MASK, (void __iomem *) GPIO_INTEN);
 }
 
+static int __init hsdk_tweak_node_coherency(const char *path, bool coherent)
+{
+       void *fdt = initial_boot_params;
+       const void *prop;
+       int node, ret;
+       bool dt_coh_set;
+
+       node = fdt_path_offset(fdt, path);
+       if (node < 0)
+               goto tweak_fail;
+
+       prop = fdt_getprop(fdt, node, "dma-coherent", &ret);
+       if (!prop && ret != -FDT_ERR_NOTFOUND)
+               goto tweak_fail;
+
+       dt_coh_set = ret != -FDT_ERR_NOTFOUND;
+       ret = 0;
+
+       /* need to remove "dma-coherent" property */
+       if (dt_coh_set && !coherent)
+               ret = fdt_delprop(fdt, node, "dma-coherent");
+
+       /* need to set "dma-coherent" property */
+       if (!dt_coh_set && coherent)
+               ret = fdt_setprop(fdt, node, "dma-coherent", NULL, 0);
+
+       if (ret < 0)
+               goto tweak_fail;
+
+       return 0;
+
+tweak_fail:
+       pr_err("failed to tweak %s to %scoherent\n", path, coherent ? "" : "non");
+       return -EFAULT;
+}
+
 enum hsdk_axi_masters {
        M_HS_CORE = 0,
        M_HS_RTT,
@@ -162,6 +202,39 @@ enum hsdk_axi_masters {
 #define CREG_PAE               ((void __iomem *)(CREG_BASE + 0x180))
 #define CREG_PAE_UPDT          ((void __iomem *)(CREG_BASE + 0x194))
 
+static void __init hsdk_init_memory_bridge_axi_dmac(void)
+{
+       bool coherent = !!arc_hsdk_axi_dmac_coherent;
+       u32 axi_m_slv1, axi_m_oft1;
+
+       /*
+        * Don't tweak memory bridge configuration if we failed to tweak DTB
+        * as we will end up in a inconsistent state.
+        */
+       if (hsdk_tweak_node_coherency("/soc/dmac@80000", coherent))
+               return;
+
+       if (coherent) {
+               axi_m_slv1 = 0x77999999;
+               axi_m_oft1 = 0x76DCBA98;
+       } else {
+               axi_m_slv1 = 0x77777777;
+               axi_m_oft1 = 0x76543210;
+       }
+
+       writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
+       writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
+       writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_0));
+       writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_0));
+       writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
+
+       writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
+       writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
+       writel(axi_m_slv1, CREG_AXI_M_SLV1(M_DMAC_1));
+       writel(axi_m_oft1, CREG_AXI_M_OFT1(M_DMAC_1));
+       writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
+}
+
 static void __init hsdk_init_memory_bridge(void)
 {
        u32 reg;
@@ -227,24 +300,14 @@ static void __init hsdk_init_memory_bridge(void)
        writel(0x76543210, CREG_AXI_M_OFT1(M_GPU));
        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU));
 
-       writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
-       writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0));
-       writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
-       writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0));
-       writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
-
-       writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
-       writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1));
-       writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
-       writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1));
-       writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
-
        writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS));
        writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS));
        writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS));
        writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS));
        writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS));
 
+       hsdk_init_memory_bridge_axi_dmac();
+
        /*
         * PAE remapping for DMA clients does not work due to an RTL bug, so
         * CREG_PAE register must be programmed to all zeroes, otherwise it
index 33b00579befff2d4ea0809965398f67cedb6fc77..24360211534abe47a053dbc575c6e46c49e3c734 100644 (file)
@@ -7,6 +7,8 @@ config ARM
        select ARCH_HAS_BINFMT_FLAT
        select ARCH_HAS_DEBUG_VIRTUAL if MMU
        select ARCH_HAS_DEVMEM_IS_ALLOWED
+       select ARCH_HAS_DMA_COHERENT_TO_PFN if SWIOTLB
+       select ARCH_HAS_DMA_MMAP_PGPROT if SWIOTLB
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_KEEPINITRD
@@ -18,6 +20,8 @@ config ARM
        select ARCH_HAS_SET_MEMORY
        select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
        select ARCH_HAS_STRICT_MODULE_RWX if MMU
+       select ARCH_HAS_SYNC_DMA_FOR_DEVICE if SWIOTLB
+       select ARCH_HAS_SYNC_DMA_FOR_CPU if SWIOTLB
        select ARCH_HAS_TEARDOWN_DMA_OPS if MMU
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAVE_CUSTOM_GPIO_H
index c929bea9a9ffe56dd9db0b9498054f61fb9a9204..85710e078afb4878738c75b8d3d7fd0814e119aa 100644 (file)
@@ -1535,7 +1535,6 @@ config DEBUG_LL_INCLUDE
                                 DEBUG_IMX7D_UART
        default "debug/ks8695.S" if DEBUG_KS8695_UART
        default "debug/msm.S" if DEBUG_QCOM_UARTDM
-       default "debug/netx.S" if DEBUG_NETX_UART
        default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
        default "debug/renesas-scif.S" if DEBUG_R7S72100_SCIF2
        default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF0
@@ -1575,7 +1574,6 @@ config DEBUG_UART_8250
 
 config DEBUG_UART_PHYS
        hex "Physical base address of debug UART"
-       default 0x00100a00 if DEBUG_NETX_UART
        default 0x01c20000 if DEBUG_DAVINCI_DMx_UART0
        default 0x01c28000 if DEBUG_SUNXI_UART0
        default 0x01c28400 if DEBUG_SUNXI_UART1
@@ -1700,7 +1698,6 @@ config DEBUG_UART_PHYS
                DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
                DEBUG_LL_UART_EFM32 || \
                DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
-               DEBUG_NETX_UART || \
                DEBUG_QCOM_UARTDM || DEBUG_R7S72100_SCIF2 || \
                DEBUG_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \
                DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF1 || \
@@ -1717,7 +1714,6 @@ config DEBUG_UART_VIRT
        default 0xc881f000 if DEBUG_RV1108_UART2
        default 0xc8821000 if DEBUG_RV1108_UART1
        default 0xc8912000 if DEBUG_RV1108_UART0
-       default 0xe0000a00 if DEBUG_NETX_UART
        default 0xe0010fe0 if ARCH_RPC
        default 0xf0000be0 if ARCH_EBSA110
        default 0xf0010000 if DEBUG_ASM9260_UART
@@ -1822,7 +1818,6 @@ config DEBUG_UART_VIRT
        default DEBUG_UART_PHYS if !MMU
        depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
                DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
-               DEBUG_NETX_UART || \
                DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
                DEBUG_S3C64XX_UART || \
                DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
index ced1a19d5f8982f11c12986dce5ea4d81decec3e..46849d6ecb3e264fb2b6f0fbef0c0e8e1031306a 100644 (file)
                        uart0: serial@0 {
                                compatible = "ti,am3352-uart", "ti,omap3-uart";
                                clock-frequency = <48000000>;
-                               reg = <0x0 0x2000>;
+                               reg = <0x0 0x1000>;
                                interrupts = <72>;
                                status = "disabled";
                                dmas = <&edma 26 0>, <&edma 27 0>;
                        uart1: serial@0 {
                                compatible = "ti,am3352-uart", "ti,omap3-uart";
                                clock-frequency = <48000000>;
-                               reg = <0x0 0x2000>;
+                               reg = <0x0 0x1000>;
                                interrupts = <73>;
                                status = "disabled";
                                dmas = <&edma 28 0>, <&edma 29 0>;
                        uart2: serial@0 {
                                compatible = "ti,am3352-uart", "ti,omap3-uart";
                                clock-frequency = <48000000>;
-                               reg = <0x0 0x2000>;
+                               reg = <0x0 0x1000>;
                                interrupts = <74>;
                                status = "disabled";
                                dmas = <&edma 30 0>, <&edma 31 0>;
                        uart3: serial@0 {
                                compatible = "ti,am3352-uart", "ti,omap3-uart";
                                clock-frequency = <48000000>;
-                               reg = <0x0 0x2000>;
+                               reg = <0x0 0x1000>;
                                interrupts = <44>;
                                status = "disabled";
                        };
                        uart4: serial@0 {
                                compatible = "ti,am3352-uart", "ti,omap3-uart";
                                clock-frequency = <48000000>;
-                               reg = <0x0 0x2000>;
+                               reg = <0x0 0x1000>;
                                interrupts = <45>;
                                status = "disabled";
                        };
                        uart5: serial@0 {
                                compatible = "ti,am3352-uart", "ti,omap3-uart";
                                clock-frequency = <48000000>;
-                               reg = <0x0 0x2000>;
+                               reg = <0x0 0x1000>;
                                interrupts = <46>;
                                status = "disabled";
                        };
 
                target-module@cc000 {                   /* 0x481cc000, ap 60 46.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
+                       reg = <0xcc020 0x4>;
+                       reg-names = "rev";
                        ti,hwmods = "d_can0";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
                        clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN0_CLKCTRL 0>,
 
                target-module@d0000 {                   /* 0x481d0000, ap 62 42.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
+                       reg = <0xd0020 0x4>;
+                       reg-names = "rev";
                        ti,hwmods = "d_can1";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
                        clocks = <&l4ls_clkctrl AM3_L4LS_D_CAN1_CLKCTRL 0>,
index e5c2f71a7c77da4cd1f4393652e442eac45a4220..fb6b8aa12cc56c68e15eaba389e3120e90a40336 100644 (file)
                        interrupt-names = "edma3_tcerrint";
                };
 
-               mmc3: mmc@47810000 {
-                       compatible = "ti,omap4-hsmmc";
+               target-module@47810000 {
+                       compatible = "ti,sysc-omap2", "ti,sysc";
                        ti,hwmods = "mmc3";
-                       ti,needs-special-reset;
-                       interrupts = <29>;
-                       reg = <0x47810000 0x1000>;
-                       status = "disabled";
+                       reg = <0x478102fc 0x4>,
+                             <0x47810110 0x4>,
+                             <0x47810114 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       clocks = <&l3s_clkctrl AM3_L3S_MMC3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x47810000 0x1000>;
+
+                       mmc3: mmc@0 {
+                               compatible = "ti,omap4-hsmmc";
+                               ti,needs-special-reset;
+                               interrupts = <29>;
+                               reg = <0x0 0x1000>;
+                       };
                };
 
                usb: usb@47400000 {
index 55aff4db9c7c29625e8ef26fc30642f6995fcfb9..848e2a8884e2cdd0a7430a65c87576eca048f5ac 100644 (file)
                        interrupt-names = "edma3_tcerrint";
                };
 
-               mmc3: mmc@47810000 {
-                       compatible = "ti,omap4-hsmmc";
-                       reg = <0x47810000 0x1000>;
+               target-module@47810000 {
+                       compatible = "ti,sysc-omap2", "ti,sysc";
                        ti,hwmods = "mmc3";
-                       ti,needs-special-reset;
-                       interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
-                       status = "disabled";
+                       reg = <0x478102fc 0x4>,
+                             <0x47810110 0x4>,
+                             <0x47810114 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       clocks = <&l3s_clkctrl AM4_L3S_MMC3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x47810000 0x1000>;
+
+                       mmc3: mmc@0 {
+                               compatible = "ti,omap4-hsmmc";
+                               ti,needs-special-reset;
+                               interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+                               reg = <0x0 0x1000>;
+                       };
                };
 
                sham: sham@53100000 {
index 989cb60b90295868f1b983ff4129c867c33fce6b..04bee4ff9dcb86e6ea435834d5826c9eca98ab00 100644 (file)
 
                target-module@cc000 {                   /* 0x481cc000, ap 50 46.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
+                       reg = <0xcc020 0x4>;
+                       reg-names = "rev";
                        ti,hwmods = "d_can0";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
                        clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>;
 
                target-module@d0000 {                   /* 0x481d0000, ap 52 3a.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
+                       reg = <0xd0020 0x4>;
+                       reg-names = "rev";
                        ti,hwmods = "d_can1";
                        /* Domains (P, C): per_pwrdm, l4ls_clkdm */
                        clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>;
index 1d5e99964bbf89411daa4a73bc22b9d091f2dcca..0aaacea1d887bf2c2b61f9887f970a5719bbf6fb 100644 (file)
 };
 
 &mmc1 {
-       pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+       pinctrl-names = "default", "hs";
        pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
        pinctrl-1 = <&mmc1_pins_hs>;
-       pinctrl-2 = <&mmc1_pins_sdr12>;
-       pinctrl-3 = <&mmc1_pins_sdr25>;
-       pinctrl-4 = <&mmc1_pins_sdr50>;
-       pinctrl-5 = <&mmc1_pins_ddr50_rev20 &mmc1_iodelay_ddr50_conf>;
-       pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
 };
 
 &mmc2 {
index c65d7f6d3b5a6384b34c9969b945a42b442ca51a..ea1c119feaa5746d4b72baeaf63b0cfd2a15dce2 100644 (file)
 };
 
 &mmc1 {
-       pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+       pinctrl-names = "default", "hs";
        pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
        pinctrl-1 = <&mmc1_pins_hs>;
-       pinctrl-2 = <&mmc1_pins_sdr12>;
-       pinctrl-3 = <&mmc1_pins_sdr25>;
-       pinctrl-4 = <&mmc1_pins_sdr50>;
-       pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev20_conf>;
-       pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
 };
 
 &mmc2 {
index dc5141c35610e9596ee5e6fb3272bedc95e426c3..7935d70874ce2b9558a1c0410c40ff4d40633e9e 100644 (file)
 };
 
 &mmc1 {
-       pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+       pinctrl-names = "default", "hs";
        pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
        pinctrl-1 = <&mmc1_pins_hs>;
-       pinctrl-2 = <&mmc1_pins_default>;
-       pinctrl-3 = <&mmc1_pins_hs>;
-       pinctrl-4 = <&mmc1_pins_sdr50>;
-       pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_conf>;
-       pinctrl-6 = <&mmc1_pins_ddr50 &mmc1_iodelay_sdr104_conf>;
 };
 
 &mmc2 {
index d02f5fa61e5f5a5144c2a1f8032a96d156b23eb4..bc76f1705c0f667dab3ad9af455b5f7685823e08 100644 (file)
        };
 };
 
-&gpio7 {
+&gpio7_target {
        ti,no-reset-on-init;
        ti,no-idle-on-init;
 };
 
        bus-width = <4>;
        cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */
+       no-1-8-v;
 };
 
 &mmc2 {
index a374b5cd6db0e2ec16ea7994e33b350f68aa8532..7b113b52c3fb6494411afcd7fc32e7f5bb150e15 100644 (file)
 };
 
 &mmc1 {
-       pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+       pinctrl-names = "default", "hs";
        pinctrl-0 = <&mmc1_pins_default>;
        pinctrl-1 = <&mmc1_pins_hs>;
-       pinctrl-2 = <&mmc1_pins_sdr12>;
-       pinctrl-3 = <&mmc1_pins_sdr25>;
-       pinctrl-4 = <&mmc1_pins_sdr50>;
-       pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev11_conf>;
-       pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev11_conf>;
        vmmc-supply = <&vdd_3v3>;
        vqmmc-supply = <&ldo1_reg>;
 };
index 4badd2144db9a3ba95fdcb3bb3fd007942672116..30c500b15b21972baf89a7ce540776ff987f519a 100644 (file)
 };
 
 &mmc1 {
-       pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+       pinctrl-names = "default", "hs";
        pinctrl-0 = <&mmc1_pins_default>;
        pinctrl-1 = <&mmc1_pins_hs>;
-       pinctrl-2 = <&mmc1_pins_sdr12>;
-       pinctrl-3 = <&mmc1_pins_sdr25>;
-       pinctrl-4 = <&mmc1_pins_sdr50>;
-       pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev20_conf>;
-       pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>;
        vmmc-supply = <&vdd_3v3>;
        vqmmc-supply = <&ldo1_reg>;
 };
index 18d0ae46e76c48c96c609ef7f093d8bd48401557..0faae8950375337e236c9a501d47eeefa32fd6d1 100644 (file)
        };
 
        mdio-bus-mux {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
                /* BIT(9) = 1 => external mdio */
                mdio_ext: mdio@200 {
                        reg = <0x200>;
index 714e971b912a488e46d4ebd6d0f0edafb9a74016..de7f85efaa5120a765abf05eb34780b8000994d2 100644 (file)
        phy-supply = <&ldousb_reg>;
 };
 
-&gpio7 {
+&gpio7_target {
        ti,no-reset-on-init;
        ti,no-idle-on-init;
 };
index 23faedec08abd04f215ba55d21391281d93e374f..21e5914fdd6209157b7149710b4cec249056c9dc 100644 (file)
                        };
                };
 
-               target-module@51000 {                   /* 0x48051000, ap 45 2e.0 */
+               gpio7_target: target-module@51000 {             /* 0x48051000, ap 45 2e.0 */
                        compatible = "ti,sysc-omap2", "ti,sysc";
                        ti,hwmods = "gpio7";
                        reg = <0x51000 0x4>,
 
                target-module@80000 {                   /* 0x48480000, ap 31 16.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
-                       reg = <0x80000 0x4>;
+                       reg = <0x80020 0x4>;
                        reg-names = "rev";
                        clocks = <&l4per2_clkctrl DRA7_L4PER2_DCAN2_CLKCTRL 0>;
                        clock-names = "fck";
 
                target-module@c000 {                    /* 0x4ae3c000, ap 30 04.0 */
                        compatible = "ti,sysc-omap4", "ti,sysc";
-                       reg = <0xc000 0x4>;
+                       reg = <0xc020 0x4>;
                        reg-names = "rev";
                        clocks = <&wkupaon_clkctrl DRA7_WKUPAON_DCAN1_CLKCTRL 0>;
                        clock-names = "fck";
index 28ebb4eb884a9450f51508c576e2b37d3d8a0808..214b9e6de2c356d1c6a3650ba9fc92bcc17b8240 100644 (file)
@@ -32,7 +32,7 @@
  *
  * Datamanual Revisions:
  *
- * AM572x Silicon Revision 2.0: SPRS953B, Revised November 2016
+ * AM572x Silicon Revision 2.0: SPRS953F, Revised May 2019
  * AM572x Silicon Revision 1.1: SPRS915R, Revised November 2016
  *
  */
 
        mmc3_pins_default: mmc3_pins_default {
                pinctrl-single,pins = <
-                       DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
-                       DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
-                       DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
-                       DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
-                       DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
-                       DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
+                       DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
+                       DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
+                       DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
+                       DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
+                       DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
+                       DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
                >;
        };
 
        mmc3_pins_hs: mmc3_pins_hs {
                pinctrl-single,pins = <
-                       DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
-                       DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
-                       DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
-                       DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
-                       DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
-                       DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
+                       DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
+                       DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
+                       DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
+                       DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
+                       DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
+                       DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
                >;
        };
 
        mmc3_pins_sdr12: mmc3_pins_sdr12 {
                pinctrl-single,pins = <
-                       DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
-                       DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
-                       DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
-                       DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
-                       DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
-                       DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
+                       DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
+                       DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
+                       DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
+                       DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
+                       DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
+                       DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
                >;
        };
 
        mmc3_pins_sdr25: mmc3_pins_sdr25 {
                pinctrl-single,pins = <
-                       DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
-                       DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
-                       DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
-                       DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
-                       DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
-                       DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
+                       DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
+                       DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
+                       DRA7XX_CORE_IOPAD(0x3784, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat0.mmc3_dat0 */
+                       DRA7XX_CORE_IOPAD(0x3788, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat1.mmc3_dat1 */
+                       DRA7XX_CORE_IOPAD(0x378c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat2.mmc3_dat2 */
+                       DRA7XX_CORE_IOPAD(0x3790, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_dat3.mmc3_dat3 */
                >;
        };
 
index cbe61b61a21201d31068ea1af7210306583f35c8..c2a9dd57e56ad206237ce4c289338e0e1f3999fe 100644 (file)
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index 21ddd359d3ed68b99281a86c9f6136e25e5f1b60..9f63706383a75c57ac4b8152a19a44d4ec6a4f14 100644 (file)
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index b26d4f57c6555009b6aa5bca6ff67b03aa64f83b..cc9adce638f56c9eb8e07918f1565f22aac4ff2b 100644 (file)
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index 39eeeddac39e3145781e45f18be3e09630a880d1..09f7ffa9ad8c40cf8c73302efe779f8539e2a08e 100644 (file)
@@ -43,7 +43,7 @@
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index de07357b27fc25d9ace8f74fe5db4c6fe2c49716..6cd7d5877d20cf40df028acd6b9ba28f41ebe022 100644 (file)
@@ -43,7 +43,7 @@
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
@@ -58,7 +58,7 @@
 };
 
 &i2c3 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c3>;
        status = "okay";
index 992747a5744205c58aa34e3a36be6eb473df6eb1..56907bb4b3291dc65849c8833bb02784773bbadc 100644 (file)
                        reg = <0x40330200 0x200>;
                };
 
-               usbphy1: usb-phy@0x40350000 {
+               usbphy1: usb-phy@40350000 {
                        compatible = "fsl,imx7ulp-usbphy", "fsl,imx6ul-usbphy";
                        reg = <0x40350000 0x1000>;
                        interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
index 3fa0cbe456db6f35f3d35c8bfce85a41edadd2af..0f3870d3b0990e7f07caf2be5a4a0a47ece86366 100644 (file)
                reg = <0>;
        };
 
-       n25q128a13_2: flash@1 {
+       n25q128a13_2: flash@2 {
                compatible = "n25q128a13", "jedec,spi-nor";
                #address-cells = <1>;
                #size-cells = <1>;
                spi-max-frequency = <66000000>;
                spi-rx-bus-width = <2>;
-               reg = <1>;
+               reg = <2>;
        };
 };
 
index e6b98b6eb88ddf779aa30f8a453172171aab101f..822cddfbf1af01c463f0a035d5efd20faaf3a29e 100644 (file)
@@ -4,17 +4,9 @@ CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_U8500=y
-CONFIG_MACH_HREFV60=y
-CONFIG_MACH_SNOWBALL=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
@@ -25,6 +17,11 @@ CONFIG_CPU_IDLE=y
 CONFIG_ARM_U8500_CPUIDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_CMA=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -47,7 +44,6 @@ CONFIG_SMSC911X=y
 CONFIG_SMSC_PHY=y
 CONFIG_CW1200=y
 CONFIG_CW1200_WLAN_SDIO=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_GPIO=y
@@ -63,7 +59,6 @@ CONFIG_RMI4_CORE=y
 CONFIG_RMI4_I2C=y
 CONFIG_RMI4_F11=y
 # CONFIG_SERIO is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
@@ -72,6 +67,7 @@ CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_TC3589X=y
+CONFIG_SENSORS_IIO_HWMON=y
 CONFIG_THERMAL=y
 CONFIG_CPU_THERMAL=y
 CONFIG_WATCHDOG=y
@@ -79,6 +75,13 @@ CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
 CONFIG_REGULATOR_AB8500=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_DRM=y
+CONFIG_DRM_PANEL_SAMSUNG_S6D16D0=y
+CONFIG_DRM_LIMA=y
+CONFIG_DRM_MCDE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
@@ -87,6 +90,7 @@ CONFIG_SND_SOC_UX500_MACH_MOP500=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HDRC=y
 CONFIG_USB_MUSB_UX500=y
+CONFIG_MUSB_PIO_ONLY=y
 CONFIG_AB8500_USB=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
@@ -103,6 +107,7 @@ CONFIG_RTC_DRV_AB8500=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
+CONFIG_HWSPINLOCK=y
 CONFIG_HSEM_U8500=y
 CONFIG_IIO=y
 CONFIG_IIO_SW_TRIGGER=y
@@ -126,20 +131,19 @@ CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_CRYPTO_DEV_UX500=y
+CONFIG_CRYPTO_DEV_UX500_CRYP=y
+CONFIG_CRYPTO_DEV_UX500_HASH=y
+CONFIG_CRYPTO_DEV_UX500_DEBUG=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
 CONFIG_CORESIGHT=y
 CONFIG_CORESIGHT_SINK_TPIU=y
 CONFIG_CORESIGHT_SINK_ETBV10=y
 CONFIG_CORESIGHT_SOURCE_ETM3X=y
-CONFIG_CRYPTO_DEV_UX500=y
-CONFIG_CRYPTO_DEV_UX500_CRYP=y
-CONFIG_CRYPTO_DEV_UX500_HASH=y
-CONFIG_CRYPTO_DEV_UX500_DEBUG=y
index 7e0486ad1318cdf3037b0689340f4faa407ed13b..dba9355e24849ce92bdff29cb0af54fbe46fa771 100644 (file)
@@ -18,7 +18,9 @@ extern const struct dma_map_ops arm_coherent_dma_ops;
 
 static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 {
-       return IS_ENABLED(CONFIG_MMU) ? &arm_dma_ops : NULL;
+       if (IS_ENABLED(CONFIG_MMU) && !IS_ENABLED(CONFIG_ARM_LPAE))
+               return &arm_dma_ops;
+       return NULL;
 }
 
 #ifdef __arch_page_to_dma
index af8b8e15f589d0dee271c6217373ee296476cd66..b0c195e3a06df00ac7d07f65113f7820b13b6db5 100644 (file)
@@ -544,6 +544,7 @@ static int arch_build_bp_info(struct perf_event *bp,
                if ((hw->ctrl.type != ARM_BREAKPOINT_EXECUTE)
                        && max_watchpoint_len >= 8)
                        break;
+               /* Else, fall through */
        default:
                return -EINVAL;
        }
@@ -608,10 +609,12 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
                /* Allow halfword watchpoints and breakpoints. */
                if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2)
                        break;
+               /* Else, fall through */
        case 3:
                /* Allow single byte watchpoint. */
                if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
                        break;
+               /* Else, fall through */
        default:
                ret = -EINVAL;
                goto out;
@@ -861,6 +864,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
                break;
        case ARM_ENTRY_ASYNC_WATCHPOINT:
                WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");
+               /* Fall through */
        case ARM_ENTRY_SYNC_WATCHPOINT:
                watchpoint_handler(addr, fsr, regs);
                break;
@@ -909,6 +913,7 @@ static bool core_has_os_save_restore(void)
                ARM_DBG_READ(c1, c1, 4, oslsr);
                if (oslsr & ARM_OSLSR_OSLM0)
                        return true;
+               /* Else, fall through */
        default:
                return false;
        }
index 09f6fdd419745c891b3c9ebaf853ac8ef2b76c7f..ab2568996ddb0c73bdcb3633b648b983a0b27b68 100644 (file)
@@ -596,6 +596,7 @@ static int do_signal(struct pt_regs *regs, int syscall)
                switch (retval) {
                case -ERESTART_RESTARTBLOCK:
                        restart -= 2;
+                       /* Fall through */
                case -ERESTARTNOHAND:
                case -ERESTARTSYS:
                case -ERESTARTNOINTR:
index d2806bcff8bbb29a6be18d6e8c255bab19f33c8c..07745ee022a121aa482361bcce51dccee7ab8ef6 100644 (file)
@@ -651,13 +651,22 @@ int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
 }
 
 static void reset_coproc_regs(struct kvm_vcpu *vcpu,
-                             const struct coproc_reg *table, size_t num)
+                             const struct coproc_reg *table, size_t num,
+                             unsigned long *bmap)
 {
        unsigned long i;
 
        for (i = 0; i < num; i++)
-               if (table[i].reset)
+               if (table[i].reset) {
+                       int reg = table[i].reg;
+
                        table[i].reset(vcpu, &table[i]);
+                       if (reg > 0 && reg < NR_CP15_REGS) {
+                               set_bit(reg, bmap);
+                               if (table[i].is_64bit)
+                                       set_bit(reg + 1, bmap);
+                       }
+               }
 }
 
 static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
@@ -1432,17 +1441,15 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
 {
        size_t num;
        const struct coproc_reg *table;
-
-       /* Catch someone adding a register without putting in reset entry. */
-       memset(vcpu->arch.ctxt.cp15, 0x42, sizeof(vcpu->arch.ctxt.cp15));
+       DECLARE_BITMAP(bmap, NR_CP15_REGS) = { 0, };
 
        /* Generic chip reset first (so target could override). */
-       reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
+       reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs), bmap);
 
        table = get_target_table(vcpu->arch.target, &num);
-       reset_coproc_regs(vcpu, table, num);
+       reset_coproc_regs(vcpu, table, num, bmap);
 
        for (num = 1; num < NR_CP15_REGS; num++)
-               WARN(vcpu_cp15(vcpu, num) == 0x42424242,
+               WARN(!test_bit(num, bmap),
                     "Didn't reset vcpu_cp15(vcpu, %zi)", num);
 }
index 1d5210eb4776edcacb44cb0b5a23ea91864b87c3..582925238d65ea261cc126078462ce2a66421549 100644 (file)
@@ -66,7 +66,7 @@ for_each_frame:       tst     frame, mask             @ Check for address exceptions
 
 1003:          ldr     r2, [sv_pc, #-4]        @ if stmfd sp!, {args} exists,
                ldr     r3, .Ldsi+4             @ adjust saved 'pc' back one
-               teq     r3, r2, lsr #10         @ instruction
+               teq     r3, r2, lsr #11         @ instruction
                subne   r0, sv_pc, #4           @ allow for mov
                subeq   r0, sv_pc, #8           @ allow for mov + stmia
 
index a15c3a2913861b116b916beb8a0f519d8ce25201..44ee6bac255e6fa4b5e43f75b7e3403fe6a16b94 100644 (file)
@@ -26,7 +26,6 @@ config MACH_ASPEED_G4
 config MACH_ASPEED_G5
        bool "Aspeed SoC 5th Generation"
        depends on ARCH_MULTI_V6
-       select CPU_V6
        select PINCTRL_ASPEED_G5
        help
         Say yes if you intend to run on an Aspeed ast2500 or similar
index 05d03f09ff54b8af1d343edfaa76ec38d1da3670..71262dcdbca32aea22714945f43bc6671c71c8a9 100644 (file)
@@ -24,6 +24,7 @@
 #define DEEPSLEEP_SLEEPENABLE_BIT      BIT(31)
 
        .text
+       .arch   armv5te
 /*
  * Move DaVinci into deep sleep state
  *
index 1c9a4be8b5036d9fea7d0a8e9a001bccedb7cb52..1c05c5bf7e5c89331f9b72771334b819c4ec8a2c 100644 (file)
@@ -49,6 +49,7 @@ static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t)
                 * FALLTHROUGH: Ensure we don't try to overwrite our newly
                 * initialised state information on the first fault.
                 */
+               /* Fall through */
 
        case THREAD_NOTIFY_EXIT:
                crunch_task_release(thread);
diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig
deleted file mode 100644 (file)
index 1e5d9c8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menu "NetX Implementations"
-       depends on ARCH_NETX
-
-config MACH_NXDKN
-       bool "Enable Hilscher nxdkn Eval Board support"
-       help
-         Board support for the Hilscher NetX Eval Board
-
-config MACH_NXDB500
-       bool "Enable Hilscher nxdb500 Eval Board support"
-       select ARM_AMBA
-       help
-         Board support for the Hilscher nxdb500 Eval Board
-
-config MACH_NXEB500HMI
-       bool "Enable Hilscher nxeb500hmi Eval Board support"
-       select ARM_AMBA
-       help
-         Board support for the Hilscher nxeb500hmi Eval Board
-
-endmenu
diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile
deleted file mode 100644 (file)
index 44ea83f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y                  += time.o generic.o pfifo.o xc.o
-
-# Specific board support
-obj-$(CONFIG_MACH_NXDKN) += nxdkn.o
-obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o
-obj-$(CONFIG_MACH_NXEB500HMI) += nxeb500hmi.o fb.o
diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot
deleted file mode 100644 (file)
index 2eb23c0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-    zreladdr-y                 += 0x80008000
-
diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c
deleted file mode 100644 (file)
index 2dc80db..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/fb.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-#include <linux/err.h>
-#include <linux/gfp.h>
-
-#include <asm/irq.h>
-
-#include <mach/netx-regs.h>
-#include <mach/hardware.h>
-
-static struct clcd_panel *netx_panel;
-
-void netx_clcd_enable(struct clcd_fb *fb)
-{
-}
-
-int netx_clcd_setup(struct clcd_fb *fb)
-{
-       dma_addr_t dma;
-
-       fb->panel = netx_panel;
-
-       fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, 1024 * 1024, &dma,
-                                         GFP_KERNEL);
-       if (!fb->fb.screen_base) {
-               printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-               return -ENOMEM;
-       }
-
-       fb->fb.fix.smem_start   = dma;
-       fb->fb.fix.smem_len     = 1024*1024;
-
-       return 0;
-}
-
-int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-       return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
-                          fb->fb.fix.smem_start, fb->fb.fix.smem_len);
-}
-
-void netx_clcd_remove(struct clcd_fb *fb)
-{
-       dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
-                   fb->fb.fix.smem_start);
-}
-
-static AMBA_AHB_DEVICE(fb, "fb", 0, 0x00104000, { NETX_IRQ_LCD }, NULL);
-
-int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel)
-{
-       netx_panel = panel;
-       fb_device.dev.platform_data = board;
-       return amba_device_register(&fb_device, &iomem_resource);
-}
diff --git a/arch/arm/mach-netx/fb.h b/arch/arm/mach-netx/fb.h
deleted file mode 100644 (file)
index 5cdc01f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/fb.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-void netx_clcd_enable(struct clcd_fb *fb);
-int netx_clcd_setup(struct clcd_fb *fb);
-int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma);
-void netx_clcd_remove(struct clcd_fb *fb);
-int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel);
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
deleted file mode 100644 (file)
index 88881fd..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/generic.c
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/irqchip/arm-vic.h>
-#include <linux/reboot.h>
-#include <mach/hardware.h>
-#include <asm/mach/map.h>
-#include <mach/netx-regs.h>
-#include <asm/mach/irq.h>
-
-static struct map_desc netx_io_desc[] __initdata = {
-       {
-               .virtual        = NETX_IO_VIRT,
-               .pfn            = __phys_to_pfn(NETX_IO_PHYS),
-               .length         = NETX_IO_SIZE,
-               .type           = MT_DEVICE
-       }
-};
-
-void __init netx_map_io(void)
-{
-       iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc));
-}
-
-static struct resource netx_rtc_resources[] = {
-       [0] = {
-               .start  = 0x00101200,
-               .end    = 0x00101220,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device netx_rtc_device = {
-       .name           = "netx-rtc",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(netx_rtc_resources),
-       .resource       = netx_rtc_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
-       &netx_rtc_device,
-};
-
-#if 0
-#define DEBUG_IRQ(fmt...)      printk(fmt)
-#else
-#define DEBUG_IRQ(fmt...)      while (0) {}
-#endif
-
-static void netx_hif_demux_handler(struct irq_desc *desc)
-{
-       unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
-       unsigned int stat;
-
-       stat = ((readl(NETX_DPMAS_INT_EN) &
-               readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f;
-
-       while (stat) {
-               if (stat & 1) {
-                       DEBUG_IRQ("handling irq %d\n", irq);
-                       generic_handle_irq(irq);
-               }
-               irq++;
-               stat >>= 1;
-       }
-}
-
-static int
-netx_hif_irq_type(struct irq_data *d, unsigned int type)
-{
-       unsigned int val, irq;
-
-       val = readl(NETX_DPMAS_IF_CONF1);
-
-       irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
-
-       if (type & IRQ_TYPE_EDGE_RISING) {
-               DEBUG_IRQ("rising edges\n");
-               val |= (1 << 26) << irq;
-       }
-       if (type & IRQ_TYPE_EDGE_FALLING) {
-               DEBUG_IRQ("falling edges\n");
-               val &= ~((1 << 26) << irq);
-       }
-       if (type & IRQ_TYPE_LEVEL_LOW) {
-               DEBUG_IRQ("low level\n");
-               val &= ~((1 << 26) << irq);
-       }
-       if (type & IRQ_TYPE_LEVEL_HIGH) {
-               DEBUG_IRQ("high level\n");
-               val |= (1 << 26) << irq;
-       }
-
-       writel(val, NETX_DPMAS_IF_CONF1);
-
-       return 0;
-}
-
-static void
-netx_hif_ack_irq(struct irq_data *d)
-{
-       unsigned int val, irq;
-
-       irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
-       writel((1 << 24) << irq, NETX_DPMAS_INT_STAT);
-
-       val = readl(NETX_DPMAS_INT_EN);
-       val &= ~((1 << 24) << irq);
-       writel(val, NETX_DPMAS_INT_EN);
-
-       DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
-}
-
-static void
-netx_hif_mask_irq(struct irq_data *d)
-{
-       unsigned int val, irq;
-
-       irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
-       val = readl(NETX_DPMAS_INT_EN);
-       val &= ~((1 << 24) << irq);
-       writel(val, NETX_DPMAS_INT_EN);
-       DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
-}
-
-static void
-netx_hif_unmask_irq(struct irq_data *d)
-{
-       unsigned int val, irq;
-
-       irq = d->irq - NETX_IRQ_HIF_CHAINED(0);
-       val = readl(NETX_DPMAS_INT_EN);
-       val |= (1 << 24) << irq;
-       writel(val, NETX_DPMAS_INT_EN);
-       DEBUG_IRQ("%s: irq %d\n", __func__, d->irq);
-}
-
-static struct irq_chip netx_hif_chip = {
-       .irq_ack = netx_hif_ack_irq,
-       .irq_mask = netx_hif_mask_irq,
-       .irq_unmask = netx_hif_unmask_irq,
-       .irq_set_type = netx_hif_irq_type,
-};
-
-void __init netx_init_irq(void)
-{
-       int irq;
-
-       vic_init(io_p2v(NETX_PA_VIC), NETX_IRQ_VIC_START, ~0, 0);
-
-       for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
-               irq_set_chip_and_handler(irq, &netx_hif_chip,
-                                        handle_level_irq);
-               irq_clear_status_flags(irq, IRQ_NOREQUEST);
-       }
-
-       writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN);
-       irq_set_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
-}
-
-static int __init netx_init(void)
-{
-       return platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-subsys_initcall(netx_init);
-
-void netx_restart(enum reboot_mode mode, const char *cmd)
-{
-       writel(NETX_SYSTEM_RES_CR_FIRMW_RES_EN | NETX_SYSTEM_RES_CR_FIRMW_RES,
-              NETX_SYSTEM_RES_CR);
-}
diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h
deleted file mode 100644 (file)
index 223e304..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/generic.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/reboot.h>
-
-extern void __init netx_map_io(void);
-extern void __init netx_init_irq(void);
-extern void netx_restart(enum reboot_mode, const char *);
-
-extern void netx_timer_init(void);
diff --git a/arch/arm/mach-netx/include/mach/hardware.h b/arch/arm/mach-netx/include/mach/hardware.h
deleted file mode 100644 (file)
index 8425399..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/hardware.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#define NETX_IO_PHYS   0x00100000
-#define NETX_IO_VIRT   0xe0000000
-#define NETX_IO_SIZE   0x00100000
-
-#define SRAM_INTERNAL_PHYS_0 0x00000
-#define SRAM_INTERNAL_PHYS_1 0x08000
-#define SRAM_INTERNAL_PHYS_2 0x10000
-#define SRAM_INTERNAL_PHYS_3 0x18000
-#define SRAM_INTERNAL_PHYS(no) ((no) * 0x8000)
-
-#define XPEC_MEM_SIZE 0x4000
-#define XMAC_MEM_SIZE 0x1000
-#define SRAM_MEM_SIZE 0x8000
-
-#define io_p2v(x) IOMEM((x) - NETX_IO_PHYS + NETX_IO_VIRT)
-#define io_v2p(x) ((x) - NETX_IO_VIRT + NETX_IO_PHYS)
-
-#endif
diff --git a/arch/arm/mach-netx/include/mach/irqs.h b/arch/arm/mach-netx/include/mach/irqs.h
deleted file mode 100644 (file)
index 540c921..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/irqs.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#define NETX_IRQ_VIC_START     64
-#define NETX_IRQ_SOFTINT       (NETX_IRQ_VIC_START + 0)
-#define NETX_IRQ_TIMER0                (NETX_IRQ_VIC_START + 1)
-#define NETX_IRQ_TIMER1                (NETX_IRQ_VIC_START + 2)
-#define NETX_IRQ_TIMER2                (NETX_IRQ_VIC_START + 3)
-#define NETX_IRQ_SYSTIME_NS    (NETX_IRQ_VIC_START + 4)
-#define NETX_IRQ_SYSTIME_S     (NETX_IRQ_VIC_START + 5)
-#define NETX_IRQ_GPIO_15       (NETX_IRQ_VIC_START + 6)
-#define NETX_IRQ_WATCHDOG      (NETX_IRQ_VIC_START + 7)
-#define NETX_IRQ_UART0         (NETX_IRQ_VIC_START + 8)
-#define NETX_IRQ_UART1         (NETX_IRQ_VIC_START + 9)
-#define NETX_IRQ_UART2         (NETX_IRQ_VIC_START + 10)
-#define NETX_IRQ_USB           (NETX_IRQ_VIC_START + 11)
-#define NETX_IRQ_SPI           (NETX_IRQ_VIC_START + 12)
-#define NETX_IRQ_I2C           (NETX_IRQ_VIC_START + 13)
-#define NETX_IRQ_LCD           (NETX_IRQ_VIC_START + 14)
-#define NETX_IRQ_HIF           (NETX_IRQ_VIC_START + 15)
-#define NETX_IRQ_GPIO_0_14     (NETX_IRQ_VIC_START + 16)
-#define NETX_IRQ_XPEC0         (NETX_IRQ_VIC_START + 17)
-#define NETX_IRQ_XPEC1         (NETX_IRQ_VIC_START + 18)
-#define NETX_IRQ_XPEC2         (NETX_IRQ_VIC_START + 19)
-#define NETX_IRQ_XPEC3         (NETX_IRQ_VIC_START + 20)
-#define NETX_IRQ_XPEC(no)      (NETX_IRQ_VIC_START + 17 + (no))
-#define NETX_IRQ_MSYNC0                (NETX_IRQ_VIC_START + 21)
-#define NETX_IRQ_MSYNC1                (NETX_IRQ_VIC_START + 22)
-#define NETX_IRQ_MSYNC2                (NETX_IRQ_VIC_START + 23)
-#define NETX_IRQ_MSYNC3                (NETX_IRQ_VIC_START + 24)
-#define NETX_IRQ_IRQ_PHY       (NETX_IRQ_VIC_START + 25)
-#define NETX_IRQ_ISO_AREA      (NETX_IRQ_VIC_START + 26)
-/* int 27 is reserved */
-/* int 28 is reserved */
-#define NETX_IRQ_TIMER3                (NETX_IRQ_VIC_START + 29)
-#define NETX_IRQ_TIMER4                (NETX_IRQ_VIC_START + 30)
-/* int 31 is reserved */
-
-#define NETX_IRQS              (NETX_IRQ_VIC_START + 32)
-
-/* for multiplexed irqs on gpio 0..14 */
-#define NETX_IRQ_GPIO(x) (NETX_IRQS + (x))
-#define NETX_IRQ_GPIO_LAST NETX_IRQ_GPIO(14)
-
-/* Host interface interrupts */
-#define NETX_IRQ_HIF_CHAINED(x)    (NETX_IRQ_GPIO_LAST + 1 + (x))
-#define NETX_IRQ_HIF_PIO35         NETX_IRQ_HIF_CHAINED(0)
-#define NETX_IRQ_HIF_PIO36         NETX_IRQ_HIF_CHAINED(1)
-#define NETX_IRQ_HIF_PIO40         NETX_IRQ_HIF_CHAINED(2)
-#define NETX_IRQ_HIF_PIO47         NETX_IRQ_HIF_CHAINED(3)
-#define NETX_IRQ_HIF_PIO72         NETX_IRQ_HIF_CHAINED(4)
-#define NETX_IRQ_HIF_LAST          NETX_IRQ_HIF_CHAINED(4)
-
-#define NR_IRQS (NETX_IRQ_HIF_LAST + 1)
diff --git a/arch/arm/mach-netx/include/mach/netx-regs.h b/arch/arm/mach-netx/include/mach/netx-regs.h
deleted file mode 100644 (file)
index 7c356a6..0000000
+++ /dev/null
@@ -1,420 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/netx-regs.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#ifndef __ASM_ARCH_NETX_REGS_H
-#define __ASM_ARCH_NETX_REGS_H
-
-/* offsets relative to the beginning of the io space */
-#define NETX_OFS_SYSTEM  0x00000
-#define NETX_OFS_MEMCR   0x00100
-#define NETX_OFS_DPMAS   0x03000
-#define NETX_OFS_GPIO    0x00800
-#define NETX_OFS_PIO     0x00900
-#define NETX_OFS_UART0   0x00a00
-#define NETX_OFS_UART1   0x00a40
-#define NETX_OFS_UART2   0x00a80
-#define NETX_OF_MIIMU    0x00b00
-#define NETX_OFS_SPI     0x00c00
-#define NETX_OFS_I2C     0x00d00
-#define NETX_OFS_SYSTIME 0x01100
-#define NETX_OFS_RTC     0x01200
-#define NETX_OFS_EXTBUS  0x03600
-#define NETX_OFS_LCD     0x04000
-#define NETX_OFS_USB     0x20000
-#define NETX_OFS_XMAC0   0x60000
-#define NETX_OFS_XMAC1   0x61000
-#define NETX_OFS_XMAC2   0x62000
-#define NETX_OFS_XMAC3   0x63000
-#define NETX_OFS_XMAC(no) (0x60000 + (no) * 0x1000)
-#define NETX_OFS_PFIFO   0x64000
-#define NETX_OFS_XPEC0   0x70000
-#define NETX_OFS_XPEC1   0x74000
-#define NETX_OFS_XPEC2   0x78000
-#define NETX_OFS_XPEC3   0x7c000
-#define NETX_OFS_XPEC(no) (0x70000 + (no) * 0x4000)
-#define NETX_OFS_VIC     0xff000
-
-/* physical addresses */
-#define NETX_PA_SYSTEM   (NETX_IO_PHYS + NETX_OFS_SYSTEM)
-#define NETX_PA_MEMCR    (NETX_IO_PHYS + NETX_OFS_MEMCR)
-#define NETX_PA_DPMAS    (NETX_IO_PHYS + NETX_OFS_DPMAS)
-#define NETX_PA_GPIO     (NETX_IO_PHYS + NETX_OFS_GPIO)
-#define NETX_PA_PIO      (NETX_IO_PHYS + NETX_OFS_PIO)
-#define NETX_PA_UART0    (NETX_IO_PHYS + NETX_OFS_UART0)
-#define NETX_PA_UART1    (NETX_IO_PHYS + NETX_OFS_UART1)
-#define NETX_PA_UART2    (NETX_IO_PHYS + NETX_OFS_UART2)
-#define NETX_PA_MIIMU    (NETX_IO_PHYS + NETX_OF_MIIMU)
-#define NETX_PA_SPI      (NETX_IO_PHYS + NETX_OFS_SPI)
-#define NETX_PA_I2C      (NETX_IO_PHYS + NETX_OFS_I2C)
-#define NETX_PA_SYSTIME  (NETX_IO_PHYS + NETX_OFS_SYSTIME)
-#define NETX_PA_RTC      (NETX_IO_PHYS + NETX_OFS_RTC)
-#define NETX_PA_EXTBUS   (NETX_IO_PHYS + NETX_OFS_EXTBUS)
-#define NETX_PA_LCD      (NETX_IO_PHYS + NETX_OFS_LCD)
-#define NETX_PA_USB      (NETX_IO_PHYS + NETX_OFS_USB)
-#define NETX_PA_XMAC0    (NETX_IO_PHYS + NETX_OFS_XMAC0)
-#define NETX_PA_XMAC1    (NETX_IO_PHYS + NETX_OFS_XMAC1)
-#define NETX_PA_XMAC2    (NETX_IO_PHYS + NETX_OFS_XMAC2)
-#define NETX_PA_XMAC3    (NETX_IO_PHYS + NETX_OFS_XMAC3)
-#define NETX_PA_XMAC(no) (NETX_IO_PHYS + NETX_OFS_XMAC(no))
-#define NETX_PA_PFIFO    (NETX_IO_PHYS + NETX_OFS_PFIFO)
-#define NETX_PA_XPEC0    (NETX_IO_PHYS + NETX_OFS_XPEC0)
-#define NETX_PA_XPEC1    (NETX_IO_PHYS + NETX_OFS_XPEC1)
-#define NETX_PA_XPEC2    (NETX_IO_PHYS + NETX_OFS_XPEC2)
-#define NETX_PA_XPEC3    (NETX_IO_PHYS + NETX_OFS_XPEC3)
-#define NETX_PA_XPEC(no) (NETX_IO_PHYS + NETX_OFS_XPEC(no))
-#define NETX_PA_VIC      (NETX_IO_PHYS + NETX_OFS_VIC)
-
-/* virtual addresses */
-#define NETX_VA_SYSTEM   (NETX_IO_VIRT + NETX_OFS_SYSTEM)
-#define NETX_VA_MEMCR    (NETX_IO_VIRT + NETX_OFS_MEMCR)
-#define NETX_VA_DPMAS    (NETX_IO_VIRT + NETX_OFS_DPMAS)
-#define NETX_VA_GPIO     (NETX_IO_VIRT + NETX_OFS_GPIO)
-#define NETX_VA_PIO      (NETX_IO_VIRT + NETX_OFS_PIO)
-#define NETX_VA_UART0    (NETX_IO_VIRT + NETX_OFS_UART0)
-#define NETX_VA_UART1    (NETX_IO_VIRT + NETX_OFS_UART1)
-#define NETX_VA_UART2    (NETX_IO_VIRT + NETX_OFS_UART2)
-#define NETX_VA_MIIMU    (NETX_IO_VIRT + NETX_OF_MIIMU)
-#define NETX_VA_SPI      (NETX_IO_VIRT + NETX_OFS_SPI)
-#define NETX_VA_I2C      (NETX_IO_VIRT + NETX_OFS_I2C)
-#define NETX_VA_SYSTIME  (NETX_IO_VIRT + NETX_OFS_SYSTIME)
-#define NETX_VA_RTC      (NETX_IO_VIRT + NETX_OFS_RTC)
-#define NETX_VA_EXTBUS   (NETX_IO_VIRT + NETX_OFS_EXTBUS)
-#define NETX_VA_LCD      (NETX_IO_VIRT + NETX_OFS_LCD)
-#define NETX_VA_USB      (NETX_IO_VIRT + NETX_OFS_USB)
-#define NETX_VA_XMAC0    (NETX_IO_VIRT + NETX_OFS_XMAC0)
-#define NETX_VA_XMAC1    (NETX_IO_VIRT + NETX_OFS_XMAC1)
-#define NETX_VA_XMAC2    (NETX_IO_VIRT + NETX_OFS_XMAC2)
-#define NETX_VA_XMAC3    (NETX_IO_VIRT + NETX_OFS_XMAC3)
-#define NETX_VA_XMAC(no) (NETX_IO_VIRT + NETX_OFS_XMAC(no))
-#define NETX_VA_PFIFO    (NETX_IO_VIRT + NETX_OFS_PFIFO)
-#define NETX_VA_XPEC0    (NETX_IO_VIRT + NETX_OFS_XPEC0)
-#define NETX_VA_XPEC1    (NETX_IO_VIRT + NETX_OFS_XPEC1)
-#define NETX_VA_XPEC2    (NETX_IO_VIRT + NETX_OFS_XPEC2)
-#define NETX_VA_XPEC3    (NETX_IO_VIRT + NETX_OFS_XPEC3)
-#define NETX_VA_XPEC(no) (NETX_IO_VIRT + NETX_OFS_XPEC(no))
-#define NETX_VA_VIC      (NETX_IO_VIRT + NETX_OFS_VIC)
-
-/*********************************
- * System functions              *
- *********************************/
-
-/* Registers */
-#define NETX_SYSTEM_REG(ofs)            IOMEM(NETX_VA_SYSTEM + (ofs))
-#define NETX_SYSTEM_BOO_SR          NETX_SYSTEM_REG(0x00)
-#define NETX_SYSTEM_IOC_CR          NETX_SYSTEM_REG(0x04)
-#define NETX_SYSTEM_IOC_MR          NETX_SYSTEM_REG(0x08)
-
-/* FIXME: Docs are not consistent */
-/* #define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x08) */
-#define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x0c)
-
-#define NETX_SYSTEM_PHY_CONTROL     NETX_SYSTEM_REG(0x10)
-#define NETX_SYSTEM_REV             NETX_SYSTEM_REG(0x34)
-#define NETX_SYSTEM_IOC_ACCESS_KEY  NETX_SYSTEM_REG(0x70)
-#define NETX_SYSTEM_WDG_TR          NETX_SYSTEM_REG(0x200)
-#define NETX_SYSTEM_WDG_CTR         NETX_SYSTEM_REG(0x204)
-#define NETX_SYSTEM_WDG_IRQ_TIMEOUT NETX_SYSTEM_REG(0x208)
-#define NETX_SYSTEM_WDG_RES_TIMEOUT NETX_SYSTEM_REG(0x20c)
-
-/* Bits */
-#define NETX_SYSTEM_RES_CR_RSTIN         (1<<0)
-#define NETX_SYSTEM_RES_CR_WDG_RES       (1<<1)
-#define NETX_SYSTEM_RES_CR_HOST_RES      (1<<2)
-#define NETX_SYSTEM_RES_CR_FIRMW_RES     (1<<3)
-#define NETX_SYSTEM_RES_CR_XPEC0_RES     (1<<4)
-#define NETX_SYSTEM_RES_CR_XPEC1_RES     (1<<5)
-#define NETX_SYSTEM_RES_CR_XPEC2_RES     (1<<6)
-#define NETX_SYSTEM_RES_CR_XPEC3_RES     (1<<7)
-#define NETX_SYSTEM_RES_CR_DIS_XPEC0_RES (1<<16)
-#define NETX_SYSTEM_RES_CR_DIS_XPEC1_RES (1<<17)
-#define NETX_SYSTEM_RES_CR_DIS_XPEC2_RES (1<<18)
-#define NETX_SYSTEM_RES_CR_DIS_XPEC3_RES (1<<19)
-#define NETX_SYSTEM_RES_CR_FIRMW_FLG0    (1<<20)
-#define NETX_SYSTEM_RES_CR_FIRMW_FLG1    (1<<21)
-#define NETX_SYSTEM_RES_CR_FIRMW_FLG2    (1<<22)
-#define NETX_SYSTEM_RES_CR_FIRMW_FLG3    (1<<23)
-#define NETX_SYSTEM_RES_CR_FIRMW_RES_EN  (1<<24)
-#define NETX_SYSTEM_RES_CR_RSTOUT        (1<<25)
-#define NETX_SYSTEM_RES_CR_EN_RSTOUT     (1<<26)
-
-#define PHY_CONTROL_RESET            (1<<31)
-#define PHY_CONTROL_SIM_BYP          (1<<30)
-#define PHY_CONTROL_CLK_XLATIN       (1<<29)
-#define PHY_CONTROL_PHY1_EN          (1<<21)
-#define PHY_CONTROL_PHY1_NP_MSG_CODE
-#define PHY_CONTROL_PHY1_AUTOMDIX    (1<<17)
-#define PHY_CONTROL_PHY1_FIXMODE     (1<<16)
-#define PHY_CONTROL_PHY1_MODE(mode)  (((mode) & 0x7) << 13)
-#define PHY_CONTROL_PHY0_EN          (1<<12)
-#define PHY_CONTROL_PHY0_NP_MSG_CODE
-#define PHY_CONTROL_PHY0_AUTOMDIX    (1<<8)
-#define PHY_CONTROL_PHY0_FIXMODE     (1<<7)
-#define PHY_CONTROL_PHY0_MODE(mode)  (((mode) & 0x7) << 4)
-#define PHY_CONTROL_PHY_ADDRESS(adr) ((adr) & 0xf)
-
-#define PHY_MODE_10BASE_T_HALF      0
-#define PHY_MODE_10BASE_T_FULL      1
-#define PHY_MODE_100BASE_TX_FX_FULL 2
-#define PHY_MODE_100BASE_TX_FX_HALF 3
-#define PHY_MODE_100BASE_TX_HALF    4
-#define PHY_MODE_REPEATER           5
-#define PHY_MODE_POWER_DOWN         6
-#define PHY_MODE_ALL                7
-
-/* Bits */
-#define VECT_CNTL_ENABLE               (1 << 5)
-
-/*******************************
- * GPIO and timer module       *
- *******************************/
-
-/* Registers */
-#define NETX_GPIO_REG(ofs)                     IOMEM(NETX_VA_GPIO + (ofs))
-#define NETX_GPIO_CFG(gpio)                NETX_GPIO_REG(0x0  + ((gpio)<<2))
-#define NETX_GPIO_THRESHOLD_CAPTURE(gpio)  NETX_GPIO_REG(0x40 + ((gpio)<<2))
-#define NETX_GPIO_COUNTER_CTRL(counter)    NETX_GPIO_REG(0x80 + ((counter)<<2))
-#define NETX_GPIO_COUNTER_MAX(counter)     NETX_GPIO_REG(0x94 + ((counter)<<2))
-#define NETX_GPIO_COUNTER_CURRENT(counter) NETX_GPIO_REG(0xa8 + ((counter)<<2))
-#define NETX_GPIO_IRQ_ENABLE               NETX_GPIO_REG(0xbc)
-#define NETX_GPIO_IRQ_DISABLE              NETX_GPIO_REG(0xc0)
-#define NETX_GPIO_SYSTIME_NS_CMP           NETX_GPIO_REG(0xc4)
-#define NETX_GPIO_LINE                     NETX_GPIO_REG(0xc8)
-#define NETX_GPIO_IRQ                      NETX_GPIO_REG(0xd0)
-
-/* Bits */
-#define NETX_GPIO_CFG_IOCFG_GP_INPUT                 (0x0)
-#define NETX_GPIO_CFG_IOCFG_GP_OUTPUT                (0x1)
-#define NETX_GPIO_CFG_IOCFG_GP_UART                  (0x2)
-#define NETX_GPIO_CFG_INV                            (1<<2)
-#define NETX_GPIO_CFG_MODE_INPUT_READ                (0<<3)
-#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_CONT_RISING (1<<3)
-#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_ONCE_RISING (2<<3)
-#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_HIGH_LEVEL  (3<<3)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER0             (0<<5)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER1             (1<<5)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER2             (2<<5)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER3             (3<<5)
-#define NETX_GPIO_CFG_COUNT_REF_COUNTER4             (4<<5)
-#define NETX_GPIO_CFG_COUNT_REF_SYSTIME              (7<<5)
-
-#define NETX_GPIO_COUNTER_CTRL_RUN                   (1<<0)
-#define NETX_GPIO_COUNTER_CTRL_SYM                   (1<<1)
-#define NETX_GPIO_COUNTER_CTRL_ONCE                  (1<<2)
-#define NETX_GPIO_COUNTER_CTRL_IRQ_EN                (1<<3)
-#define NETX_GPIO_COUNTER_CTRL_CNT_EVENT             (1<<4)
-#define NETX_GPIO_COUNTER_CTRL_RST_EN                (1<<5)
-#define NETX_GPIO_COUNTER_CTRL_SEL_EVENT             (1<<6)
-#define NETX_GPIO_COUNTER_CTRL_GPIO_REF /* FIXME */
-
-#define GPIO_BIT(gpio)                     (1<<(gpio))
-#define COUNTER_BIT(counter)               ((1<<16)<<(counter))
-
-/*******************************
- * PIO                         *
- *******************************/
-
-/* Registers */
-#define NETX_PIO_REG(ofs)        IOMEM(NETX_VA_PIO + (ofs))
-#define NETX_PIO_INPIO       NETX_PIO_REG(0x0)
-#define NETX_PIO_OUTPIO      NETX_PIO_REG(0x4)
-#define NETX_PIO_OEPIO       NETX_PIO_REG(0x8)
-
-/*******************************
- * MII Unit                    *
- *******************************/
-
-/* Registers */
-#define NETX_MIIMU           IOMEM(NETX_VA_MIIMU)
-
-/* Bits */
-#define MIIMU_SNRDY        (1<<0)
-#define MIIMU_PREAMBLE     (1<<1)
-#define MIIMU_OPMODE_WRITE (1<<2)
-#define MIIMU_MDC_PERIOD   (1<<3)
-#define MIIMU_PHY_NRES     (1<<4)
-#define MIIMU_RTA          (1<<5)
-#define MIIMU_REGADDR(adr) (((adr) & 0x1f) << 6)
-#define MIIMU_PHYADDR(adr) (((adr) & 0x1f) << 11)
-#define MIIMU_DATA(data)   (((data) & 0xffff) << 16)
-
-/*******************************
- * xmac / xpec                 *
- *******************************/
-
-/* XPEC register offsets relative to NETX_VA_XPEC(no) */
-#define NETX_XPEC_R0_OFS           0x00
-#define NETX_XPEC_R1_OFS           0x04
-#define NETX_XPEC_R2_OFS           0x08
-#define NETX_XPEC_R3_OFS           0x0c
-#define NETX_XPEC_R4_OFS           0x10
-#define NETX_XPEC_R5_OFS           0x14
-#define NETX_XPEC_R6_OFS           0x18
-#define NETX_XPEC_R7_OFS           0x1c
-#define NETX_XPEC_RANGE01_OFS      0x20
-#define NETX_XPEC_RANGE23_OFS      0x24
-#define NETX_XPEC_RANGE45_OFS      0x28
-#define NETX_XPEC_RANGE67_OFS      0x2c
-#define NETX_XPEC_PC_OFS           0x48
-#define NETX_XPEC_TIMER_OFS(timer) (0x30 + ((timer)<<2))
-#define NETX_XPEC_IRQ_OFS          0x8c
-#define NETX_XPEC_SYSTIME_NS_OFS   0x90
-#define NETX_XPEC_FIFO_DATA_OFS    0x94
-#define NETX_XPEC_SYSTIME_S_OFS    0x98
-#define NETX_XPEC_ADC_OFS          0x9c
-#define NETX_XPEC_URX_COUNT_OFS    0x40
-#define NETX_XPEC_UTX_COUNT_OFS    0x44
-#define NETX_XPEC_PC_OFS           0x48
-#define NETX_XPEC_ZERO_OFS         0x4c
-#define NETX_XPEC_STATCFG_OFS      0x50
-#define NETX_XPEC_EC_MASKA_OFS     0x54
-#define NETX_XPEC_EC_MASKB_OFS     0x58
-#define NETX_XPEC_EC_MASK0_OFS     0x5c
-#define NETX_XPEC_EC_MASK8_OFS     0x7c
-#define NETX_XPEC_EC_MASK9_OFS     0x80
-#define NETX_XPEC_XPU_HOLD_PC_OFS  0x100
-#define NETX_XPEC_RAM_START_OFS    0x2000
-
-/* Bits */
-#define XPU_HOLD_PC (1<<0)
-
-/* XMAC register offsets relative to NETX_VA_XMAC(no) */
-#define NETX_XMAC_RPU_PROGRAM_START_OFS       0x000
-#define NETX_XMAC_RPU_PROGRAM_END_OFS         0x3ff
-#define NETX_XMAC_TPU_PROGRAM_START_OFS       0x400
-#define NETX_XMAC_TPU_PROGRAM_END_OFS         0x7ff
-#define NETX_XMAC_RPU_HOLD_PC_OFS             0xa00
-#define NETX_XMAC_TPU_HOLD_PC_OFS             0xa04
-#define NETX_XMAC_STATUS_SHARED0_OFS          0x840
-#define NETX_XMAC_CONFIG_SHARED0_OFS          0x844
-#define NETX_XMAC_STATUS_SHARED1_OFS          0x848
-#define NETX_XMAC_CONFIG_SHARED1_OFS          0x84c
-#define NETX_XMAC_STATUS_SHARED2_OFS          0x850
-#define NETX_XMAC_CONFIG_SHARED2_OFS          0x854
-#define NETX_XMAC_STATUS_SHARED3_OFS          0x858
-#define NETX_XMAC_CONFIG_SHARED3_OFS          0x85c
-
-#define RPU_HOLD_PC            (1<<15)
-#define TPU_HOLD_PC            (1<<15)
-
-/*******************************
- * Pointer FIFO                *
- *******************************/
-
-/* Registers */
-#define NETX_PFIFO_REG(ofs)               IOMEM(NETX_VA_PFIFO + (ofs))
-#define NETX_PFIFO_BASE(pfifo)        NETX_PFIFO_REG(0x00 + ((pfifo)<<2))
-#define NETX_PFIFO_BORDER_BASE(pfifo) NETX_PFIFO_REG(0x80 + ((pfifo)<<2))
-#define NETX_PFIFO_RESET              NETX_PFIFO_REG(0x100)
-#define NETX_PFIFO_FULL               NETX_PFIFO_REG(0x104)
-#define NETX_PFIFO_EMPTY              NETX_PFIFO_REG(0x108)
-#define NETX_PFIFO_OVEFLOW            NETX_PFIFO_REG(0x10c)
-#define NETX_PFIFO_UNDERRUN           NETX_PFIFO_REG(0x110)
-#define NETX_PFIFO_FILL_LEVEL(pfifo)  NETX_PFIFO_REG(0x180 + ((pfifo)<<2))
-#define NETX_PFIFO_XPEC_ISR(xpec)     NETX_PFIFO_REG(0x400 + ((xpec) << 2))
-
-
-/*******************************
- * Memory Controller           *
- *******************************/
-
-/* Registers */
-#define NETX_MEMCR_REG(ofs)               IOMEM(NETX_VA_MEMCR + (ofs))
-#define NETX_MEMCR_SRAM_CTRL(cs)      NETX_MEMCR_REG(0x0 + 4 * (cs)) /* SRAM for CS 0..2 */
-#define NETX_MEMCR_SDRAM_CFG_CTRL     NETX_MEMCR_REG(0x40)
-#define NETX_MEMCR_SDRAM_TIMING_CTRL  NETX_MEMCR_REG(0x44)
-#define NETX_MEMCR_SDRAM_MODE         NETX_MEMCR_REG(0x48)
-#define NETX_MEMCR_SDRAM_EXT_MODE     NETX_MEMCR_REG(0x4c)
-#define NETX_MEMCR_PRIO_TIMESLOT_CTRL NETX_MEMCR_REG(0x80)
-#define NETX_MEMCR_PRIO_ACCESS_CTRL   NETX_MEMCR_REG(0x84)
-
-/* Bits */
-#define NETX_MEMCR_SRAM_CTRL_WIDTHEXTMEM(x)       (((x) & 0x3)  << 24)
-#define NETX_MEMCR_SRAM_CTRL_WSPOSTPAUSEEXTMEM(x) (((x) & 0x3)  << 16)
-#define NETX_MEMCR_SRAM_CTRL_WSPREPASEEXTMEM(x)   (((x) & 0x3)  << 8)
-#define NETX_MEMCR_SRAM_CTRL_WSEXTMEM(x)          (((x) & 0x1f) << 0)
-
-
-/*******************************
- * Dual Port Memory            *
- *******************************/
-
-/* Registers */
-#define NETX_DPMAS_REG(ofs)               IOMEM(NETX_VA_DPMAS + (ofs))
-#define NETX_DPMAS_SYS_STAT           NETX_DPMAS_REG(0x4d8)
-#define NETX_DPMAS_INT_STAT           NETX_DPMAS_REG(0x4e0)
-#define NETX_DPMAS_INT_EN             NETX_DPMAS_REG(0x4f0)
-#define NETX_DPMAS_IF_CONF0           NETX_DPMAS_REG(0x608)
-#define NETX_DPMAS_IF_CONF1           NETX_DPMAS_REG(0x60c)
-#define NETX_DPMAS_EXT_CONFIG(cs)     NETX_DPMAS_REG(0x610 + 4 * (cs))
-#define NETX_DPMAS_IO_MODE0           NETX_DPMAS_REG(0x620) /* I/O 32..63 */
-#define NETX_DPMAS_DRV_EN0            NETX_DPMAS_REG(0x624)
-#define NETX_DPMAS_DATA0              NETX_DPMAS_REG(0x628)
-#define NETX_DPMAS_IO_MODE1           NETX_DPMAS_REG(0x630) /* I/O 64..84 */
-#define NETX_DPMAS_DRV_EN1            NETX_DPMAS_REG(0x634)
-#define NETX_DPMAS_DATA1              NETX_DPMAS_REG(0x638)
-
-/* Bits */
-#define NETX_DPMAS_INT_EN_GLB_EN         (1<<31)
-#define NETX_DPMAS_INT_EN_MEM_LCK        (1<<30)
-#define NETX_DPMAS_INT_EN_WDG            (1<<29)
-#define NETX_DPMAS_INT_EN_PIO72          (1<<28)
-#define NETX_DPMAS_INT_EN_PIO47          (1<<27)
-#define NETX_DPMAS_INT_EN_PIO40          (1<<26)
-#define NETX_DPMAS_INT_EN_PIO36          (1<<25)
-#define NETX_DPMAS_INT_EN_PIO35          (1<<24)
-
-#define NETX_DPMAS_IF_CONF0_HIF_DISABLED (0<<28)
-#define NETX_DPMAS_IF_CONF0_HIF_EXT_BUS  (1<<28)
-#define NETX_DPMAS_IF_CONF0_HIF_UP_8BIT  (2<<28)
-#define NETX_DPMAS_IF_CONF0_HIF_UP_16BIT (3<<28)
-#define NETX_DPMAS_IF_CONF0_HIF_IO       (4<<28)
-#define NETX_DPMAS_IF_CONF0_WAIT_DRV_PP  (1<<14)
-#define NETX_DPMAS_IF_CONF0_WAIT_DRV_OD  (2<<14)
-#define NETX_DPMAS_IF_CONF0_WAIT_DRV_TRI (3<<14)
-
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO35 (1<<26)
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO36 (1<<27)
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO40 (1<<28)
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO47 (1<<29)
-#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO72 (1<<30)
-
-#define NETX_EXT_CONFIG_TALEWIDTH(x) (((x) & 0x7) << 29)
-#define NETX_EXT_CONFIG_TADRHOLD(x)  (((x) & 0x7) << 26)
-#define NETX_EXT_CONFIG_TCSON(x)     (((x) & 0x7) << 23)
-#define NETX_EXT_CONFIG_TRDON(x)     (((x) & 0x7) << 20)
-#define NETX_EXT_CONFIG_TWRON(x)     (((x) & 0x7)  << 17)
-#define NETX_EXT_CONFIG_TWROFF(x)    (((x) & 0x1f) << 12)
-#define NETX_EXT_CONFIG_TRDWRCYC(x)  (((x) & 0x1f) << 7)
-#define NETX_EXT_CONFIG_WAIT_POL     (1<<6)
-#define NETX_EXT_CONFIG_WAIT_EN      (1<<5)
-#define NETX_EXT_CONFIG_NRD_MODE     (1<<4)
-#define NETX_EXT_CONFIG_DS_MODE      (1<<3)
-#define NETX_EXT_CONFIG_NWR_MODE     (1<<2)
-#define NETX_EXT_CONFIG_16BIT        (1<<1)
-#define NETX_EXT_CONFIG_CS_ENABLE    (1<<0)
-
-#define NETX_DPMAS_IO_MODE0_WRL   (1<<13)
-#define NETX_DPMAS_IO_MODE0_WAIT  (1<<14)
-#define NETX_DPMAS_IO_MODE0_READY (1<<15)
-#define NETX_DPMAS_IO_MODE0_CS0   (1<<19)
-#define NETX_DPMAS_IO_MODE0_EXTRD (1<<20)
-
-#define NETX_DPMAS_IO_MODE1_CS2           (1<<15)
-#define NETX_DPMAS_IO_MODE1_CS1           (1<<16)
-#define NETX_DPMAS_IO_MODE1_SAMPLE_NPOR   (0<<30)
-#define NETX_DPMAS_IO_MODE1_SAMPLE_100MHZ (1<<30)
-#define NETX_DPMAS_IO_MODE1_SAMPLE_NPIO36 (2<<30)
-#define NETX_DPMAS_IO_MODE1_SAMPLE_PIO36  (3<<30)
-
-/*******************************
- * I2C                         *
- *******************************/
-#define NETX_I2C_REG(ofs)      IOMEM(NETX_VA_I2C, (ofs))
-#define NETX_I2C_CTRL  NETX_I2C_REG(0x0)
-#define NETX_I2C_DATA  NETX_I2C_REG(0x4)
-
-#endif /* __ASM_ARCH_NETX_REGS_H */
diff --git a/arch/arm/mach-netx/include/mach/pfifo.h b/arch/arm/mach-netx/include/mach/pfifo.h
deleted file mode 100644 (file)
index de23180..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/pfifo.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-
-#ifndef ASM_ARCH_PFIFO_H
-#define ASM_ARCH_PFIFO_H
-
-static inline int pfifo_push(int no, unsigned int pointer)
-{
-       writel(pointer, NETX_PFIFO_BASE(no));
-       return 0;
-}
-
-static inline unsigned int pfifo_pop(int no)
-{
-       return readl(NETX_PFIFO_BASE(no));
-}
-
-static inline int pfifo_fill_level(int no)
-{
-
-       return readl(NETX_PFIFO_FILL_LEVEL(no));
-}
-
-static inline int pfifo_full(int no)
-{
-       return readl(NETX_PFIFO_FULL) & (1<<no) ? 1 : 0;
-}
-
-static inline int pfifo_empty(int no)
-{
-       return readl(NETX_PFIFO_EMPTY) & (1<<no) ? 1 : 0;
-}
-
-int pfifo_request(unsigned int pfifo_mask);
-void pfifo_free(unsigned int pfifo_mask);
-
-#endif /* ASM_ARCH_PFIFO_H */
diff --git a/arch/arm/mach-netx/include/mach/uncompress.h b/arch/arm/mach-netx/include/mach/uncompress.h
deleted file mode 100644 (file)
index edc1ac9..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/mach-netx/include/mach/uncompress.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader.  We search for the first enabled
- * port in the most probable order.  If you didn't setup a port in
- * your bootloader then nothing will appear (which might be desired).
- *
- * This does not append a newline
- */
-
-#define REG(x) (*(volatile unsigned long *)(x))
-
-#define UART1_BASE 0x100a00
-#define UART2_BASE 0x100a80
-
-#define UART_DR 0x0
-
-#define UART_CR 0x14
-#define CR_UART_EN (1<<0)
-
-#define UART_FR 0x18
-#define FR_BUSY (1<<3)
-#define FR_TXFF (1<<5)
-
-static inline void putc(char c)
-{
-       unsigned long base;
-
-       if (REG(UART1_BASE + UART_CR) & CR_UART_EN)
-               base = UART1_BASE;
-       else if (REG(UART2_BASE + UART_CR) & CR_UART_EN)
-               base = UART2_BASE;
-       else
-               return;
-
-       while (REG(base + UART_FR) & FR_TXFF);
-       REG(base + UART_DR) = c;
-}
-
-static inline void flush(void)
-{
-       unsigned long base;
-
-       if (REG(UART1_BASE + UART_CR) & CR_UART_EN)
-               base = UART1_BASE;
-       else if (REG(UART2_BASE + UART_CR) & CR_UART_EN)
-               base = UART2_BASE;
-       else
-               return;
-
-       while (REG(base + UART_FR) & FR_BUSY);
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
diff --git a/arch/arm/mach-netx/include/mach/xc.h b/arch/arm/mach-netx/include/mach/xc.h
deleted file mode 100644 (file)
index 465d5e2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- *  arch/arm/mach-netx/include/mach/xc.h
- *
- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#ifndef __ASM_ARCH_XC_H
-#define __ASM_ARCH_XC_H
-
-struct xc {
-       int no;
-       unsigned int type;
-       unsigned int version;
-       void __iomem *xpec_base;
-       void __iomem *xmac_base;
-       void __iomem *sram_base;
-       int irq;
-       struct device *dev;
-};
-
-int xc_reset(struct xc *x);
-int xc_stop(struct xc* x);
-int xc_start(struct xc *x);
-int xc_running(struct xc *x);
-int xc_request_firmware(struct xc* x);
-struct xc* request_xc(int xcno, struct device *dev);
-void free_xc(struct xc *x);
-
-#endif /* __ASM_ARCH_XC_H */
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
deleted file mode 100644 (file)
index ad5e674..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/nxdb500.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/netx-regs.h>
-#include <linux/platform_data/eth-netx.h>
-
-#include "generic.h"
-#include "fb.h"
-
-static struct clcd_panel qvga = {
-       .mode           = {
-               .name           = "QVGA",
-               .refresh        = 60,
-               .xres           = 240,
-               .yres           = 320,
-               .pixclock       = 187617,
-               .left_margin    = 6,
-               .right_margin   = 26,
-               .upper_margin   = 0,
-               .lower_margin   = 6,
-               .hsync_len      = 6,
-               .vsync_len      = 1,
-               .sync           = 0,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-       .width          = -1,
-       .height         = -1,
-       .tim2           =  16,
-       .cntl           = CNTL_LCDTFT | CNTL_BGR,
-       .bpp            = 16,
-       .grayscale      = 0,
-};
-
-static inline int nxdb500_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
-{
-       var->green.length = 5;
-       var->green.msb_right = 0;
-
-       return clcdfb_check(fb, var);
-}
-
-static int nxdb500_clcd_setup(struct clcd_fb *fb)
-{
-       unsigned int val;
-
-       fb->fb.var.green.length = 5;
-       fb->fb.var.green.msb_right = 0;
-
-       /* enable asic control */
-       val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
-       writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
-
-       writel(3, NETX_SYSTEM_IOC_CR);
-
-       val = readl(NETX_PIO_OUTPIO);
-       writel(val | 1, NETX_PIO_OUTPIO);
-
-       val = readl(NETX_PIO_OEPIO);
-       writel(val | 1, NETX_PIO_OEPIO);
-       return netx_clcd_setup(fb);
-}
-
-static struct clcd_board clcd_data = {
-       .name           = "netX",
-       .check          = nxdb500_check,
-       .decode         = clcdfb_decode,
-       .enable         = netx_clcd_enable,
-       .setup          = nxdb500_clcd_setup,
-       .mmap           = netx_clcd_mmap,
-       .remove         = netx_clcd_remove,
-};
-
-static struct netxeth_platform_data eth0_platform_data = {
-       .xcno = 0,
-};
-
-static struct platform_device netx_eth0_device = {
-       .name           = "netx-eth",
-       .id             = 0,
-       .num_resources  = 0,
-       .resource       = NULL,
-       .dev = {
-               .platform_data = &eth0_platform_data,
-       }
-};
-
-static struct netxeth_platform_data eth1_platform_data = {
-       .xcno = 1,
-};
-
-static struct platform_device netx_eth1_device = {
-       .name           = "netx-eth",
-       .id             = 1,
-       .num_resources  = 0,
-       .resource       = NULL,
-       .dev = {
-               .platform_data = &eth1_platform_data,
-       }
-};
-
-static struct resource netx_uart0_resources[] = {
-       [0] = {
-               .start  = 0x00100A00,
-               .end    = 0x00100A3F,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = (NETX_IRQ_UART0),
-               .end    = (NETX_IRQ_UART0),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device netx_uart0_device = {
-       .name           = "netx-uart",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(netx_uart0_resources),
-       .resource       = netx_uart0_resources,
-};
-
-static struct resource netx_uart1_resources[] = {
-       [0] = {
-               .start  = 0x00100A40,
-               .end    = 0x00100A7F,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = (NETX_IRQ_UART1),
-               .end    = (NETX_IRQ_UART1),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device netx_uart1_device = {
-       .name           = "netx-uart",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(netx_uart1_resources),
-       .resource       = netx_uart1_resources,
-};
-
-static struct resource netx_uart2_resources[] = {
-       [0] = {
-               .start  = 0x00100A80,
-               .end    = 0x00100ABF,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = (NETX_IRQ_UART2),
-               .end    = (NETX_IRQ_UART2),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device netx_uart2_device = {
-       .name           = "netx-uart",
-       .id             = 2,
-       .num_resources  = ARRAY_SIZE(netx_uart2_resources),
-       .resource       = netx_uart2_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
-       &netx_eth0_device,
-       &netx_eth1_device,
-       &netx_uart0_device,
-       &netx_uart1_device,
-       &netx_uart2_device,
-};
-
-static void __init nxdb500_init(void)
-{
-       netx_fb_init(&clcd_data, &qvga);
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-MACHINE_START(NXDB500, "Hilscher nxdb500")
-       .atag_offset    = 0x100,
-       .map_io         = netx_map_io,
-       .init_irq       = netx_init_irq,
-       .init_time      = netx_timer_init,
-       .init_machine   = nxdb500_init,
-       .restart        = netx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
deleted file mode 100644 (file)
index 9173815..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/nxdkn.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/netx-regs.h>
-#include <linux/platform_data/eth-netx.h>
-
-#include "generic.h"
-
-static struct netxeth_platform_data eth0_platform_data = {
-       .xcno = 0,
-};
-
-static struct platform_device nxdkn_eth0_device = {
-       .name           = "netx-eth",
-       .id             = 0,
-       .num_resources  = 0,
-       .resource       = NULL,
-       .dev = {
-               .platform_data = &eth0_platform_data,
-       }
-};
-
-static struct netxeth_platform_data eth1_platform_data = {
-       .xcno = 1,
-};
-
-static struct platform_device nxdkn_eth1_device = {
-       .name           = "netx-eth",
-       .id             = 1,
-       .num_resources  = 0,
-       .resource       = NULL,
-       .dev = {
-               .platform_data = &eth1_platform_data,
-       }
-};
-
-static struct resource netx_uart0_resources[] = {
-       [0] = {
-               .start  = 0x00100A00,
-               .end    = 0x00100A3F,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = (NETX_IRQ_UART0),
-               .end    = (NETX_IRQ_UART0),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device netx_uart0_device = {
-       .name           = "netx-uart",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(netx_uart0_resources),
-       .resource       = netx_uart0_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
-       &nxdkn_eth0_device,
-       &nxdkn_eth1_device,
-       &netx_uart0_device,
-};
-
-static void __init nxdkn_init(void)
-{
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-MACHINE_START(NXDKN, "Hilscher nxdkn")
-       .atag_offset    = 0x100,
-       .map_io         = netx_map_io,
-       .init_irq       = netx_init_irq,
-       .init_time      = netx_timer_init,
-       .init_machine   = nxdkn_init,
-       .restart        = netx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
deleted file mode 100644 (file)
index aa0d5b2..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/nxeb500hmi.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/netx-regs.h>
-#include <linux/platform_data/eth-netx.h>
-
-#include "generic.h"
-#include "fb.h"
-
-static struct clcd_panel qvga = {
-       .mode           = {
-               .name           = "QVGA",
-               .refresh        = 60,
-               .xres           = 240,
-               .yres           = 320,
-               .pixclock       = 187617,
-               .left_margin    = 6,
-               .right_margin   = 26,
-               .upper_margin   = 0,
-               .lower_margin   = 6,
-               .hsync_len      = 6,
-               .vsync_len      = 1,
-               .sync           = 0,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-       .width          = -1,
-       .height         = -1,
-       .tim2           =  16,
-       .cntl           = CNTL_LCDTFT | CNTL_BGR,
-       .bpp            = 16,
-       .grayscale      = 0,
-};
-
-static inline int nxeb500hmi_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
-{
-       var->green.length = 5;
-       var->green.msb_right = 0;
-
-       return clcdfb_check(fb, var);
-}
-
-static int nxeb500hmi_clcd_setup(struct clcd_fb *fb)
-{
-       unsigned int val;
-
-       fb->fb.var.green.length = 5;
-       fb->fb.var.green.msb_right = 0;
-
-       /* enable asic control */
-       val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
-       writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
-
-       writel(3, NETX_SYSTEM_IOC_CR);
-
-       /* GPIO 14 is used for display enable on newer boards */
-       writel(9, NETX_GPIO_CFG(14));
-
-       val = readl(NETX_PIO_OUTPIO);
-       writel(val | 1, NETX_PIO_OUTPIO);
-
-       val = readl(NETX_PIO_OEPIO);
-       writel(val | 1, NETX_PIO_OEPIO);
-       return netx_clcd_setup(fb);
-}
-
-static struct clcd_board clcd_data = {
-       .name           = "netX",
-       .check          = nxeb500hmi_check,
-       .decode         = clcdfb_decode,
-       .enable         = netx_clcd_enable,
-       .setup          = nxeb500hmi_clcd_setup,
-       .mmap           = netx_clcd_mmap,
-       .remove         = netx_clcd_remove,
-};
-
-static struct netxeth_platform_data eth0_platform_data = {
-       .xcno = 0,
-};
-
-static struct platform_device netx_eth0_device = {
-       .name           = "netx-eth",
-       .id             = 0,
-       .num_resources  = 0,
-       .resource       = NULL,
-       .dev = {
-               .platform_data = &eth0_platform_data,
-       }
-};
-
-static struct netxeth_platform_data eth1_platform_data = {
-       .xcno = 1,
-};
-
-static struct platform_device netx_eth1_device = {
-       .name           = "netx-eth",
-       .id             = 1,
-       .num_resources  = 0,
-       .resource       = NULL,
-       .dev = {
-               .platform_data = &eth1_platform_data,
-       }
-};
-
-static struct resource netx_cf_resources[] = {
-       [0] = {
-               .start  = 0x20000000,
-               .end    = 0x25ffffff,
-               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
-       },
-};
-
-static struct platform_device netx_cf_device = {
-       .name           = "netx-cf",
-       .id             = 0,
-       .resource       = netx_cf_resources,
-       .num_resources  = ARRAY_SIZE(netx_cf_resources),
-};
-
-static struct resource netx_uart0_resources[] = {
-       [0] = {
-               .start  = 0x00100A00,
-               .end    = 0x00100A3F,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = (NETX_IRQ_UART0),
-               .end    = (NETX_IRQ_UART0),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device netx_uart0_device = {
-       .name           = "netx-uart",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(netx_uart0_resources),
-       .resource       = netx_uart0_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
-       &netx_eth0_device,
-       &netx_eth1_device,
-       &netx_cf_device,
-       &netx_uart0_device,
-};
-
-static void __init nxeb500hmi_init(void)
-{
-       netx_fb_init(&clcd_data, &qvga);
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
-       .atag_offset    = 0x100,
-       .map_io         = netx_map_io,
-       .init_irq       = netx_init_irq,
-       .init_time      = netx_timer_init,
-       .init_machine   = nxeb500hmi_init,
-       .restart        = netx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-netx/pfifo.c b/arch/arm/mach-netx/pfifo.c
deleted file mode 100644 (file)
index 2e5cc77..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/pfifo.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/netx-regs.h>
-#include <mach/pfifo.h>
-
-static DEFINE_MUTEX(pfifo_lock);
-
-static unsigned int pfifo_used = 0;
-
-int pfifo_request(unsigned int pfifo_mask)
-{
-       int err = 0;
-       unsigned int val;
-
-       mutex_lock(&pfifo_lock);
-
-       if (pfifo_mask & pfifo_used) {
-               err = -EBUSY;
-               goto out;
-       }
-
-       pfifo_used |= pfifo_mask;
-
-       val = readl(NETX_PFIFO_RESET);
-       writel(val | pfifo_mask, NETX_PFIFO_RESET);
-       writel(val, NETX_PFIFO_RESET);
-
-out:
-       mutex_unlock(&pfifo_lock);
-       return err;
-}
-
-void pfifo_free(unsigned int pfifo_mask)
-{
-       mutex_lock(&pfifo_lock);
-       pfifo_used &= ~pfifo_mask;
-       mutex_unlock(&pfifo_lock);
-}
-
-EXPORT_SYMBOL(pfifo_push);
-EXPORT_SYMBOL(pfifo_pop);
-EXPORT_SYMBOL(pfifo_fill_level);
-EXPORT_SYMBOL(pfifo_empty);
-EXPORT_SYMBOL(pfifo_request);
-EXPORT_SYMBOL(pfifo_free);
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
deleted file mode 100644 (file)
index d9defa1..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/time.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/time.h>
-#include <mach/netx-regs.h>
-
-#define NETX_CLOCK_FREQ 100000000
-#define NETX_LATCH DIV_ROUND_CLOSEST(NETX_CLOCK_FREQ, HZ)
-
-#define TIMER_CLOCKEVENT 0
-#define TIMER_CLOCKSOURCE 1
-
-static inline void timer_shutdown(struct clock_event_device *evt)
-{
-       /* disable timer */
-       writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
-}
-
-static int netx_shutdown(struct clock_event_device *evt)
-{
-       timer_shutdown(evt);
-
-       return 0;
-}
-
-static int netx_set_oneshot(struct clock_event_device *evt)
-{
-       u32 tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN;
-
-       timer_shutdown(evt);
-       writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
-       writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
-
-       return 0;
-}
-
-static int netx_set_periodic(struct clock_event_device *evt)
-{
-       u32 tmode = NETX_GPIO_COUNTER_CTRL_RST_EN |
-                   NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN;
-
-       timer_shutdown(evt);
-       writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT));
-       writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT));
-
-       return 0;
-}
-
-static int netx_set_next_event(unsigned long evt,
-               struct clock_event_device *clk)
-{
-       writel(0 - evt, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKEVENT));
-       return 0;
-}
-
-static struct clock_event_device netx_clockevent = {
-       .name = "netx-timer" __stringify(TIMER_CLOCKEVENT),
-       .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .set_next_event = netx_set_next_event,
-       .set_state_shutdown = netx_shutdown,
-       .set_state_periodic = netx_set_periodic,
-       .set_state_oneshot = netx_set_oneshot,
-       .tick_resume = netx_shutdown,
-};
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-netx_timer_interrupt(int irq, void *dev_id)
-{
-       struct clock_event_device *evt = &netx_clockevent;
-
-       /* acknowledge interrupt */
-       writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
-
-       evt->event_handler(evt);
-
-       return IRQ_HANDLED;
-}
-
-static struct irqaction netx_timer_irq = {
-       .name           = "NetX Timer Tick",
-       .flags          = IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = netx_timer_interrupt,
-};
-
-/*
- * Set up timer interrupt
- */
-void __init netx_timer_init(void)
-{
-       /* disable timer initially */
-       writel(0, NETX_GPIO_COUNTER_CTRL(0));
-
-       /* Reset the timer value to zero */
-       writel(0, NETX_GPIO_COUNTER_CURRENT(0));
-
-       writel(NETX_LATCH, NETX_GPIO_COUNTER_MAX(0));
-
-       /* acknowledge interrupt */
-       writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
-
-       /* Enable the interrupt in the specific timer
-        * register and start timer
-        */
-       writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE);
-       writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN,
-                       NETX_GPIO_COUNTER_CTRL(0));
-
-       setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq);
-
-       /* Setup timer one for clocksource */
-       writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
-       writel(0, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE));
-       writel(0xffffffff, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKSOURCE));
-
-       writel(NETX_GPIO_COUNTER_CTRL_RUN,
-                       NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
-
-       clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE),
-               "netx_timer", NETX_CLOCK_FREQ, 200, 32, clocksource_mmio_readl_up);
-
-       /* with max_delta_ns >= delta2ns(0x800) the system currently runs fine.
-        * Adding some safety ... */
-       netx_clockevent.cpumask = cpumask_of(0);
-       clockevents_config_and_register(&netx_clockevent, NETX_CLOCK_FREQ,
-                                       0xa00, 0xfffffffe);
-}
diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c
deleted file mode 100644 (file)
index 885a618..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * arch/arm/mach-netx/xc.c
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/export.h>
-
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <mach/netx-regs.h>
-
-#include <mach/xc.h>
-
-static DEFINE_MUTEX(xc_lock);
-
-static int xc_in_use = 0;
-
-struct fw_desc {
-       unsigned int ofs;
-       unsigned int size;
-       unsigned int patch_ofs;
-       unsigned int patch_entries;
-};
-
-struct fw_header {
-       unsigned int magic;
-       unsigned int type;
-       unsigned int version;
-       unsigned int reserved[5];
-       struct fw_desc fw_desc[3];
-} __attribute__ ((packed));
-
-int xc_stop(struct xc *x)
-{
-       writel(RPU_HOLD_PC, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
-       writel(TPU_HOLD_PC, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
-       writel(XPU_HOLD_PC, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
-       return 0;
-}
-
-int xc_start(struct xc *x)
-{
-       writel(0, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
-       writel(0, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
-       writel(0, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
-       return 0;
-}
-
-int xc_running(struct xc *x)
-{
-       return (readl(x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS) & RPU_HOLD_PC)
-           || (readl(x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS) & TPU_HOLD_PC)
-           || (readl(x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS) & XPU_HOLD_PC) ?
-               0 : 1;
-}
-
-int xc_reset(struct xc *x)
-{
-       writel(0, x->xpec_base + NETX_XPEC_PC_OFS);
-       return 0;
-}
-
-static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size)
-{
-       if (adr >= NETX_PA_XMAC(x->no) &&
-           adr + size < NETX_PA_XMAC(x->no) + XMAC_MEM_SIZE)
-               return 0;
-
-       if (adr >= NETX_PA_XPEC(x->no) &&
-           adr + size < NETX_PA_XPEC(x->no) + XPEC_MEM_SIZE)
-               return 0;
-
-       dev_err(x->dev, "Illegal pointer in firmware found. aborting\n");
-
-       return -1;
-}
-
-static int xc_patch(struct xc *x, const void *patch, int count)
-{
-       unsigned int val, adr;
-       const unsigned int *data = patch;
-
-       int i;
-       for (i = 0; i < count; i++) {
-               adr = *data++;
-               val = *data++;
-               if (xc_check_ptr(x, adr, 4) < 0)
-                       return -EINVAL;
-
-               writel(val, (void __iomem *)io_p2v(adr));
-       }
-       return 0;
-}
-
-int xc_request_firmware(struct xc *x)
-{
-       int ret;
-       char name[16];
-       const struct firmware *fw;
-       struct fw_header *head;
-       unsigned int size;
-       int i;
-       const void *src;
-       unsigned long dst;
-
-       sprintf(name, "xc%d.bin", x->no);
-
-       ret = request_firmware(&fw, name, x->dev);
-
-       if (ret < 0) {
-               dev_err(x->dev, "request_firmware failed\n");
-               return ret;
-       }
-
-       head = (struct fw_header *)fw->data;
-       if (head->magic != 0x4e657458) {
-               if (head->magic == 0x5874654e) {
-                       dev_err(x->dev,
-                           "firmware magic is 'XteN'. Endianness problems?\n");
-                       ret = -ENODEV;
-                       goto exit_release_firmware;
-               }
-               dev_err(x->dev, "unrecognized firmware magic 0x%08x\n",
-                       head->magic);
-               ret = -ENODEV;
-               goto exit_release_firmware;
-       }
-
-       x->type = head->type;
-       x->version = head->version;
-
-       ret = -EINVAL;
-
-       for (i = 0; i < 3; i++) {
-               src = fw->data + head->fw_desc[i].ofs;
-               dst = *(unsigned int *)src;
-               src += sizeof (unsigned int);
-               size = head->fw_desc[i].size - sizeof (unsigned int);
-
-               if (xc_check_ptr(x, dst, size))
-                       goto exit_release_firmware;
-
-               memcpy((void *)io_p2v(dst), src, size);
-
-               src = fw->data + head->fw_desc[i].patch_ofs;
-               size = head->fw_desc[i].patch_entries;
-               ret = xc_patch(x, src, size);
-               if (ret < 0)
-                       goto exit_release_firmware;
-       }
-
-       ret = 0;
-
-      exit_release_firmware:
-       release_firmware(fw);
-
-       return ret;
-}
-
-struct xc *request_xc(int xcno, struct device *dev)
-{
-       struct xc *x = NULL;
-
-       mutex_lock(&xc_lock);
-
-       if (xcno > 3)
-               goto exit;
-       if (xc_in_use & (1 << xcno))
-               goto exit;
-
-       x = kmalloc(sizeof (struct xc), GFP_KERNEL);
-       if (!x)
-               goto exit;
-
-       if (!request_mem_region
-           (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, kobject_name(&dev->kobj)))
-               goto exit_free;
-
-       if (!request_mem_region
-           (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, kobject_name(&dev->kobj)))
-               goto exit_release_1;
-
-       if (!request_mem_region
-           (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, kobject_name(&dev->kobj)))
-               goto exit_release_2;
-
-       x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno));
-       x->xmac_base = (void * __iomem)io_p2v(NETX_PA_XMAC(xcno));
-       x->sram_base = ioremap(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
-       if (!x->sram_base)
-               goto exit_release_3;
-
-       x->irq = NETX_IRQ_XPEC(xcno);
-
-       x->no = xcno;
-       x->dev = dev;
-
-       xc_in_use |= (1 << xcno);
-
-       goto exit;
-
-      exit_release_3:
-       release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
-      exit_release_2:
-       release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
-      exit_release_1:
-       release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
-      exit_free:
-       kfree(x);
-       x = NULL;
-      exit:
-       mutex_unlock(&xc_lock);
-       return x;
-}
-
-void free_xc(struct xc *x)
-{
-       int xcno = x->no;
-
-       mutex_lock(&xc_lock);
-
-       iounmap(x->sram_base);
-       release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
-       release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
-       release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
-       xc_in_use &= ~(1 << x->no);
-       kfree(x);
-
-       mutex_unlock(&xc_lock);
-}
-
-EXPORT_SYMBOL(free_xc);
-EXPORT_SYMBOL(request_xc);
-EXPORT_SYMBOL(xc_request_firmware);
-EXPORT_SYMBOL(xc_reset);
-EXPORT_SYMBOL(xc_running);
-EXPORT_SYMBOL(xc_start);
-EXPORT_SYMBOL(xc_stop);
index 81159af44862eecf396f1289e74f6726514b80fd..14a6c3eb329850dab50f29908cade0e8ab68dca6 100644 (file)
@@ -126,6 +126,8 @@ restart:
        orr r11, r11, r13                       @ mask all requested interrupts
        str r11, [r12, #OMAP1510_GPIO_INT_MASK]
 
+       str r13, [r12, #OMAP1510_GPIO_INT_STATUS] @ ack all requested interrupts
+
        ands r10, r13, #KEYBRD_CLK_MASK         @ extract keyboard status - set?
        beq hksw                                @ no - try next source
 
@@ -133,7 +135,6 @@ restart:
        @@@@@@@@@@@@@@@@@@@@@@
        @ Keyboard clock FIQ mode interrupt handler
        @ r10 now contains KEYBRD_CLK_MASK, use it
-       str r10, [r12, #OMAP1510_GPIO_INT_STATUS]       @ ack the interrupt
        bic r11, r11, r10                               @ unmask it
        str r11, [r12, #OMAP1510_GPIO_INT_MASK]
 
index 43899fa5667437a57312858d5375ab6ae3d5f70c..0254eb9cf8c64340e056e2810dd8774f282b887a 100644 (file)
@@ -70,9 +70,7 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id)
                         * interrupts default to since commit 80ac93c27441
                         * requires interrupt already acked and unmasked.
                         */
-                       if (irq_chip->irq_ack)
-                               irq_chip->irq_ack(d);
-                       if (irq_chip->irq_unmask)
+                       if (!WARN_ON_ONCE(!irq_chip->irq_unmask))
                                irq_chip->irq_unmask(d);
                }
                for (; irq_counter[gpio] < fiq_count; irq_counter[gpio]++)
index f9c02f9f1c92199027cecf15f6a4567027b82d02..5c3845730dbf547d8c34040d069bab4b51006be5 100644 (file)
@@ -127,6 +127,9 @@ static int __init omap4_sram_init(void)
        struct device_node *np;
        struct gen_pool *sram_pool;
 
+       if (!soc_is_omap44xx() && !soc_is_omap54xx())
+               return 0;
+
        np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu");
        if (!np)
                pr_warn("%s:Unable to allocate sram needed to handle errata I688\n",
index 4a5b4aee6615a32eada87b5934521aefac09e08f..1ec21e9ba1e99aa565f1a70c8978f7ef58457f12 100644 (file)
@@ -379,7 +379,8 @@ static struct omap_hwmod dra7xx_dcan2_hwmod = {
 static struct omap_hwmod_class_sysconfig dra7xx_epwmss_sysc = {
        .rev_offs       = 0x0,
        .sysc_offs      = 0x4,
-       .sysc_flags     = SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET,
+       .sysc_flags     = SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+                         SYSC_HAS_RESET_STATUS,
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
        .sysc_fields    = &omap_hwmod_sysc_type2,
 };
index 0ce56ad754ceb33655a467138ed9b36d3448991d..ea2c84214bac18a18e03475e48a765156f72e6fa 100644 (file)
@@ -46,6 +46,7 @@ static int __init parse_tag_acorn(const struct tag *tag)
        switch (tag->u.acorn.vram_pages) {
        case 512:
                vram_size += PAGE_SIZE * 256;
+               /* Fall through - ??? */
        case 256:
                vram_size += PAGE_SIZE * 256;
        default:
index 5a67a71f80cc4f9dcd47738cf5c6eead43d45e19..76a65df42d10f2968de89c8e935215ab1da11977 100644 (file)
@@ -70,7 +70,7 @@ static void __init tegra_cpu_reset_handler_enable(void)
        switch (err) {
        case -ENOSYS:
                tegra_cpu_reset_handler_set(reset_address);
-               /* pass-through */
+               /* fall through */
        case 0:
                is_enabled = true;
                break;
index 820b60a50125b9ebe2984ba1d09b76e180329381..c1222c0e9fd3bebb6a64f209e80e8d924375d041 100644 (file)
@@ -663,6 +663,7 @@ config ARM_LPAE
        depends on MMU && CPU_32v7 && !CPU_32v6 && !CPU_32v5 && \
                !CPU_32v4 && !CPU_32v3
        select PHYS_ADDR_T_64BIT
+       select SWIOTLB
        help
          Say Y if you have an ARMv7 processor supporting the LPAE page
          table format and you would like to access memory beyond the
index 8cdb78642e9316612be1deb340c4bf4dd0c45e1f..04b36436cbc04877a060b10670bf453dd2ed0e2d 100644 (file)
@@ -695,7 +695,7 @@ thumb2arm(u16 tinstr)
                        return subset[(L<<1) | ((tinstr & (1<<8)) >> 8)] |
                            (tinstr & 255);             /* register_list */
                }
-               /* Else fall through for illegal instruction case */
+               /* Else, fall through - for illegal instruction case */
 
        default:
                return BAD_INSTR;
@@ -751,6 +751,8 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
        case 0xe8e0:
        case 0xe9e0:
                poffset->un = (tinst2 & 0xff) << 2;
+               /* Fall through */
+
        case 0xe940:
        case 0xe9c0:
                return do_alignment_ldrdstrd;
index 4789c60a86e34552411367282be7309f0d8f779a..d42557ee69c28fbcfd2f7f6c909f5b9b534779a8 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/dma-noncoherent.h>
 #include <linux/dma-contiguous.h>
 #include <linux/highmem.h>
 #include <linux/memblock.h>
@@ -1125,6 +1126,19 @@ int arm_dma_supported(struct device *dev, u64 mask)
 
 static const struct dma_map_ops *arm_get_dma_map_ops(bool coherent)
 {
+       /*
+        * When CONFIG_ARM_LPAE is set, physical address can extend above
+        * 32-bits, which then can't be addressed by devices that only support
+        * 32-bit DMA.
+        * Use the generic dma-direct / swiotlb ops code in that case, as that
+        * handles bounce buffering for us.
+        *
+        * Note: this checks CONFIG_ARM_LPAE instead of CONFIG_SWIOTLB as the
+        * latter is also selected by the Xen code, but that code for now relies
+        * on non-NULL dev_dma_ops.  To be cleaned up later.
+        */
+       if (IS_ENABLED(CONFIG_ARM_LPAE))
+               return NULL;
        return coherent ? &arm_coherent_dma_ops : &arm_dma_ops;
 }
 
@@ -2329,6 +2343,9 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
        const struct dma_map_ops *dma_ops;
 
        dev->archdata.dma_coherent = coherent;
+#ifdef CONFIG_SWIOTLB
+       dev->dma_coherent = coherent;
+#endif
 
        /*
         * Don't override the dma_ops if they have already been set. Ideally
@@ -2363,3 +2380,45 @@ void arch_teardown_dma_ops(struct device *dev)
        /* Let arch_setup_dma_ops() start again from scratch upon re-probe */
        set_dma_ops(dev, NULL);
 }
+
+#ifdef CONFIG_SWIOTLB
+void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_page_cpu_to_dev(phys_to_page(paddr), paddr & (PAGE_SIZE - 1),
+                             size, dir);
+}
+
+void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_page_dev_to_cpu(phys_to_page(paddr), paddr & (PAGE_SIZE - 1),
+                             size, dir);
+}
+
+long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
+               dma_addr_t dma_addr)
+{
+       return dma_to_pfn(dev, dma_addr);
+}
+
+pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
+               unsigned long attrs)
+{
+       return __get_dma_pgprot(attrs, prot);
+}
+
+void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+               gfp_t gfp, unsigned long attrs)
+{
+       return __dma_alloc(dev, size, dma_handle, gfp,
+                          __get_dma_pgprot(attrs, PAGE_KERNEL), false,
+                          attrs, __builtin_return_address(0));
+}
+
+void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
+               dma_addr_t dma_handle, unsigned long attrs)
+{
+       __arm_dma_free(dev, size, cpu_addr, dma_handle, attrs, false);
+}
+#endif /* CONFIG_SWIOTLB */
index 4920a206dce936fe9ab601bfd569f0133c3d757c..b4be3baa83d4d284e96c8f29ff84266473b234bb 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/dma-contiguous.h>
 #include <linux/sizes.h>
 #include <linux/stop_machine.h>
+#include <linux/swiotlb.h>
 
 #include <asm/cp15.h>
 #include <asm/mach-types.h>
@@ -174,6 +175,11 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max_low,
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
+       phys_addr_t addr = __pfn_to_phys(pfn);
+
+       if (__phys_to_pfn(addr) != pfn)
+               return 0;
+
        return memblock_is_map_memory(__pfn_to_phys(pfn));
 }
 EXPORT_SYMBOL(pfn_valid);
@@ -463,6 +469,10 @@ static void __init free_highpages(void)
  */
 void __init mem_init(void)
 {
+#ifdef CONFIG_ARM_LPAE
+       swiotlb_init(1);
+#endif
+
        set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
 
        /* this will put all unused low memory onto the freelists */
@@ -623,7 +633,8 @@ static void update_sections_early(struct section_perm perms[], int n)
                if (t->flags & PF_KTHREAD)
                        continue;
                for_each_thread(t, s)
-                       set_section_perms(perms, n, true, s->mm);
+                       if (s->mm)
+                               set_section_perms(perms, n, true, s->mm);
        }
        set_section_perms(perms, n, true, current->active_mm);
        set_section_perms(perms, n, true, &init_mm);
index 79f43acf9acb541487cad85bf7b49fb7f695d0d6..08c99413d02caac340f9855ebd162a59ac1126ed 100644 (file)
@@ -388,17 +388,15 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
                /*
                 * not supported by current hardware on OMAP1
                 * w |= (0x03 << 7);
-                * fall through
                 */
+               /* fall through */
        case OMAP_DMA_DATA_BURST_16:
                if (dma_omap2plus()) {
                        burst = 0x3;
                        break;
                }
-               /*
-                * OMAP1 don't support burst 16
-                * fall through
-                */
+               /* OMAP1 don't support burst 16 */
+               /* fall through */
        default:
                BUG();
        }
@@ -474,10 +472,8 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
                        burst = 0x3;
                        break;
                }
-               /*
-                * OMAP1 don't support burst 16
-                * fall through
-                */
+               /* OMAP1 don't support burst 16 */
+               /* fall through */
        default:
                printk(KERN_ERR "Invalid DMA burst mode\n");
                BUG();
index bb1f1dbb34e8f9f544cff4f6f22728eec660be54..61de992bbea3fad61895e4f1e796cea460fd9deb 100644 (file)
@@ -52,7 +52,7 @@ ifeq ($(CONFIG_GENERIC_COMPAT_VDSO), y)
 
   ifeq ($(CONFIG_CC_IS_CLANG), y)
     $(warning CROSS_COMPILE_COMPAT is clang, the compat vDSO will not be built)
-  else ifeq ($(CROSS_COMPILE_COMPAT),)
+  else ifeq ($(strip $(CROSS_COMPILE_COMPAT)),)
     $(warning CROSS_COMPILE_COMPAT not defined or empty, the compat vDSO will not be built)
   else ifeq ($(shell which $(CROSS_COMPILE_COMPAT)gcc 2> /dev/null),)
     $(error $(CROSS_COMPILE_COMPAT)gcc not found, check CROSS_COMPILE_COMPAT)
index c7a87368850b03ffbacb0a8f122fd4da6b800e20..12aa7eaeaf6800bb3374114be1027adb58036e74 100644 (file)
        pinctrl-names = "default";
 };
 
+&ir {
+       status = "okay";
+       pinctrl-0 = <&remote_input_ao_pins>;
+       pinctrl-names = "default";
+};
+
 &pwm_ef {
        status = "okay";
        pinctrl-0 = <&pwm_e_pins>;
index f8d43e3dcf20ce4d57d2b17abd6693c4b2dad77a..1785552d450c448066c76d7251745eb54035b9b1 100644 (file)
                                clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
                                clock-names = "ddr";
                                phys = <&usb2_phy1>;
+                               phy-names = "usb2-phy";
                                dr_mode = "peripheral";
                                g-rx-fifo-size = <192>;
                                g-np-tx-fifo-size = <128>;
index 81780ffcc7f0d0d3ff3fa766cdf49e6b4b7ff0c8..4e916e1f71f768623a336eebfecf21d75d825d3c 100644 (file)
@@ -53,6 +53,7 @@
 
                gpio = <&gpio_ao GPIOAO_8 GPIO_ACTIVE_HIGH>;
                enable-active-high;
+               regulator-always-on;
        };
 
        tf_io: gpio-regulator-tf_io {
index e25f7fcd799752e9f28318fb02910832a3015e3a..cffa8991880d1ad9e0a5f931dd84521dfbb1bf0e 100644 (file)
 #define MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28                                   0x1CC 0x434 0x000 0x5 0x0
 #define MX8MM_IOMUXC_SAI3_RXFS_TPSMP_HTRANS0                                0x1CC 0x434 0x000 0x7 0x0
 #define MX8MM_IOMUXC_SAI3_RXC_SAI3_RX_BCLK                                  0x1D0 0x438 0x000 0x0 0x0
-#define MX8MM_IOMUXC_SAI3_RXC_GPT1_CAPTURE2                                 0x1D0 0x438 0x000 0x1 0x0
+#define MX8MM_IOMUXC_SAI3_RXC_GPT1_CLK                                      0x1D0 0x438 0x000 0x1 0x0
 #define MX8MM_IOMUXC_SAI3_RXC_SAI5_RX_BCLK                                  0x1D0 0x438 0x4D0 0x2 0x2
 #define MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29                                    0x1D0 0x438 0x000 0x5 0x0
 #define MX8MM_IOMUXC_SAI3_RXC_TPSMP_HTRANS1                                 0x1D0 0x438 0x000 0x7 0x0
 #define MX8MM_IOMUXC_SAI3_RXD_GPIO4_IO30                                    0x1D4 0x43C 0x000 0x5 0x0
 #define MX8MM_IOMUXC_SAI3_RXD_TPSMP_HDATA0                                  0x1D4 0x43C 0x000 0x7 0x0
 #define MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC                                 0x1D8 0x440 0x000 0x0 0x0
-#define MX8MM_IOMUXC_SAI3_TXFS_GPT1_CLK                                     0x1D8 0x440 0x000 0x1 0x0
+#define MX8MM_IOMUXC_SAI3_TXFS_GPT1_CAPTURE2                                0x1D8 0x440 0x000 0x1 0x0
 #define MX8MM_IOMUXC_SAI3_TXFS_SAI5_RX_DATA1                                0x1D8 0x440 0x4D8 0x2 0x2
 #define MX8MM_IOMUXC_SAI3_TXFS_GPIO4_IO31                                   0x1D8 0x440 0x000 0x5 0x0
 #define MX8MM_IOMUXC_SAI3_TXFS_TPSMP_HDATA1                                 0x1D8 0x440 0x000 0x7 0x0
index d09b808eff87f9dca1cd73f035432346d33e836d..52aae341d0da5046e997026a7bbede672b74318b 100644 (file)
 
                        sai2: sai@308b0000 {
                                #sound-dai-cells = <0>;
-                               compatible = "fsl,imx8mq-sai",
-                                            "fsl,imx6sx-sai";
+                               compatible = "fsl,imx8mq-sai";
                                reg = <0x308b0000 0x10000>;
                                interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MQ_CLK_SAI2_IPG>,
index 3311a982fff89f66fa52c4a435ad2eeeebeec55c..23fd0224ca90e103c20af7dee574abf8af9b590d 100644 (file)
        mmc-hs200-1_8v;
        non-removable;
        fixed-emmc-driver-type = <1>;
+       status = "okay";
 };
 
 &usb_extal_clk {
index 0711170b26b1fe1c6ab4d230cc9acb2fb10a0398..3aa2564dfdc25fff2d09a121f7048390202b2a94 100644 (file)
@@ -97,7 +97,7 @@
                reg = <0x0 0x48000000 0x0 0x18000000>;
        };
 
-       reg_1p8v: regulator0 {
+       reg_1p8v: regulator-1p8v {
                compatible = "regulator-fixed";
                regulator-name = "fixed-1.8V";
                regulator-min-microvolt = <1800000>;
                regulator-always-on;
        };
 
-       reg_3p3v: regulator1 {
+       reg_3p3v: regulator-3p3v {
                compatible = "regulator-fixed";
                regulator-name = "fixed-3.3V";
                regulator-min-microvolt = <3300000>;
                regulator-always-on;
        };
 
-       reg_12p0v: regulator1 {
+       reg_12p0v: regulator-12p0v {
                compatible = "regulator-fixed";
                regulator-name = "D12.0V";
                regulator-min-microvolt = <12000000>;
index 79155a8cfe7c06026a583ea9a5a9f0218b543971..89e4c8b7934905657bd6b4c21eb780540bf80bc0 100644 (file)
@@ -155,6 +155,12 @@ static inline void gic_pmr_mask_irqs(void)
        BUILD_BUG_ON(GICD_INT_DEF_PRI < (GIC_PRIO_IRQOFF |
                                         GIC_PRIO_PSR_I_SET));
        BUILD_BUG_ON(GICD_INT_DEF_PRI >= GIC_PRIO_IRQON);
+       /*
+        * Need to make sure IRQON allows IRQs when SCR_EL3.FIQ is cleared
+        * and non-secure PMR accesses are not subject to the shifts that
+        * are applied to IRQ priorities
+        */
+       BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) >= GIC_PRIO_IRQON);
        gic_write_pmr(GIC_PRIO_IRQOFF);
 }
 
index 407e2bf23676c970fbf37d4e264b39cb8f58cad5..c96ffa4722d33cba234afdc64ce4483926eba26c 100644 (file)
  */
 
 enum ftr_type {
-       FTR_EXACT,      /* Use a predefined safe value */
-       FTR_LOWER_SAFE, /* Smaller value is safe */
-       FTR_HIGHER_SAFE,/* Bigger value is safe */
+       FTR_EXACT,                      /* Use a predefined safe value */
+       FTR_LOWER_SAFE,                 /* Smaller value is safe */
+       FTR_HIGHER_SAFE,                /* Bigger value is safe */
+       FTR_HIGHER_OR_ZERO_SAFE,        /* Bigger value is safe, but 0 is biggest */
 };
 
 #define FTR_STRICT     true    /* SANITY check strict matching required */
index 987926ed535e36e856882c6138ee0f7ea54f6576..063c964af705f0c31da0d44d10687f1e3f00ec6c 100644 (file)
@@ -13,6 +13,8 @@
 #define DAIF_PROCCTX           0
 #define DAIF_PROCCTX_NOIRQ     PSR_I_BIT
 #define DAIF_ERRCTX            (PSR_I_BIT | PSR_A_BIT)
+#define DAIF_MASK              (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
+
 
 /* mask/save/unmask/restore all exceptions, including interrupts. */
 static inline void local_daif_mask(void)
index 8e79ce9c3f5c43eca7a60207051d1ae8c6f5d671..76a14470258693743eb29a09028751e0f710a2c3 100644 (file)
@@ -105,7 +105,11 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
        ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
 
 #define alloc_screen_info(x...)                &screen_info
-#define free_screen_info(x...)
+
+static inline void free_screen_info(efi_system_table_t *sys_table_arg,
+                                   struct screen_info *si)
+{
+}
 
 /* redeclare as 'hidden' so the compiler will generate relative references */
 extern struct screen_info screen_info __attribute__((__visibility__("hidden")));
index 3c7037c6ba9b5593b492ab2893eb6086d8a14b15..b618017205a3f6af4ad612310d0187abdc2d73c1 100644 (file)
@@ -202,7 +202,7 @@ typedef compat_elf_greg_t           compat_elf_gregset_t[COMPAT_ELF_NGREG];
 ({                                                                     \
        set_thread_flag(TIF_32BIT);                                     \
  })
-#ifdef CONFIG_GENERIC_COMPAT_VDSO
+#ifdef CONFIG_COMPAT_VDSO
 #define COMPAT_ARCH_DLINFO                                             \
 do {                                                                   \
        /*                                                              \
index a8b205e5c4a8658ffa255795217e856c6e6080d5..ddf9d762ac62298a9c16bdff5acf348976280247 100644 (file)
 
 #define kvm_arm_exception_class \
        ECN(UNKNOWN), ECN(WFx), ECN(CP15_32), ECN(CP15_64), ECN(CP14_MR), \
-       ECN(CP14_LS), ECN(FP_ASIMD), ECN(CP10_ID), ECN(CP14_64), ECN(SVC64), \
-       ECN(HVC64), ECN(SMC64), ECN(SYS64), ECN(IMP_DEF), ECN(IABT_LOW), \
-       ECN(IABT_CUR), ECN(PC_ALIGN), ECN(DABT_LOW), ECN(DABT_CUR), \
+       ECN(CP14_LS), ECN(FP_ASIMD), ECN(CP10_ID), ECN(PAC), ECN(CP14_64), \
+       ECN(SVC64), ECN(HVC64), ECN(SMC64), ECN(SYS64), ECN(SVE), \
+       ECN(IMP_DEF), ECN(IABT_LOW), ECN(IABT_CUR), \
+       ECN(PC_ALIGN), ECN(DABT_LOW), ECN(DABT_CUR), \
        ECN(SP_ALIGN), ECN(FP_EXC32), ECN(FP_EXC64), ECN(SERROR), \
        ECN(BREAKPT_LOW), ECN(BREAKPT_CUR), ECN(SOFTSTP_LOW), \
        ECN(SOFTSTP_CUR), ECN(WATCHPT_LOW), ECN(WATCHPT_CUR), \
index b7ba75809751e62fb10a024cff7c687721f6e652..fb04f10a78ab35c462e251d0bacce3a05da9be32 100644 (file)
@@ -210,7 +210,11 @@ extern u64                 vabits_user;
 #define __tag_reset(addr)      untagged_addr(addr)
 #define __tag_get(addr)                (__u8)((u64)(addr) >> 56)
 #else
-#define __tag_set(addr, tag)   (addr)
+static inline const void *__tag_set(const void *addr, u8 tag)
+{
+       return addr;
+}
+
 #define __tag_reset(addr)      (addr)
 #define __tag_get(addr)                0
 #endif
@@ -301,8 +305,8 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define page_to_virt(page)     ({                                      \
        unsigned long __addr =                                          \
                ((__page_to_voff(page)) | PAGE_OFFSET);                 \
-       unsigned long __addr_tag =                                      \
-                __tag_set(__addr, page_kasan_tag(page));               \
+       const void *__addr_tag =                                        \
+               __tag_set((void *)__addr, page_kasan_tag(page));        \
        ((void *)__addr_tag);                                           \
 })
 
index 87a4b2ddc1a10b492b8b0d27a416272eeec2ba26..e09760ece844fe55cbd39dc8c32910a7bfdb6708 100644 (file)
@@ -209,7 +209,7 @@ static inline pmd_t pmd_mkcont(pmd_t pmd)
 
 static inline pte_t pte_mkdevmap(pte_t pte)
 {
-       return set_pte_bit(pte, __pgprot(PTE_DEVMAP));
+       return set_pte_bit(pte, __pgprot(PTE_DEVMAP | PTE_SPECIAL));
 }
 
 static inline void set_pte(pte_t *ptep, pte_t pte)
@@ -301,7 +301,6 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
 /*
  * Huge pte definitions.
  */
-#define pte_huge(pte)          (!(pte_val(pte) & PTE_TABLE_BIT))
 #define pte_mkhuge(pte)                (__pte(pte_val(pte) & ~PTE_TABLE_BIT))
 
 /*
@@ -397,7 +396,10 @@ static inline int pmd_protnone(pmd_t pmd)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #define pmd_devmap(pmd)                pte_devmap(pmd_pte(pmd))
 #endif
-#define pmd_mkdevmap(pmd)      pte_pmd(pte_mkdevmap(pmd_pte(pmd)))
+static inline pmd_t pmd_mkdevmap(pmd_t pmd)
+{
+       return pte_pmd(set_pte_bit(pmd_pte(pmd), __pgprot(PTE_DEVMAP)));
+}
 
 #define __pmd_to_phys(pmd)     __pte_to_phys(pmd_pte(pmd))
 #define __phys_to_pmd_val(phys)        __phys_to_pte_val(phys)
@@ -448,8 +450,8 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                                 PMD_TYPE_SECT)
 
 #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3
-#define pud_sect(pud)          (0)
-#define pud_table(pud)         (1)
+static inline bool pud_sect(pud_t pud) { return false; }
+static inline bool pud_table(pud_t pud) { return true; }
 #else
 #define pud_sect(pud)          ((pud_val(pud) & PUD_TYPE_MASK) == \
                                 PUD_TYPE_SECT)
index fd5b1a4efc70eda285ba8941d62f6e0f3ee13f05..844e2964b0f5e5b0aad4b866283f24e26f794afe 100644 (file)
@@ -193,6 +193,16 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
                regs->pmr_save = GIC_PRIO_IRQON;
 }
 
+static inline void set_ssbs_bit(struct pt_regs *regs)
+{
+       regs->pstate |= PSR_SSBS_BIT;
+}
+
+static inline void set_compat_ssbs_bit(struct pt_regs *regs)
+{
+       regs->pstate |= PSR_AA32_SSBS_BIT;
+}
+
 static inline void start_thread(struct pt_regs *regs, unsigned long pc,
                                unsigned long sp)
 {
@@ -200,7 +210,7 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc,
        regs->pstate = PSR_MODE_EL0t;
 
        if (arm64_get_ssbd_state() != ARM64_SSBD_FORCE_ENABLE)
-               regs->pstate |= PSR_SSBS_BIT;
+               set_ssbs_bit(regs);
 
        regs->sp = sp;
 }
@@ -219,7 +229,7 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
 #endif
 
        if (arm64_get_ssbd_state() != ARM64_SSBD_FORCE_ENABLE)
-               regs->pstate |= PSR_AA32_SSBS_BIT;
+               set_compat_ssbs_bit(regs);
 
        regs->compat_sp = sp;
 }
index b1dd039023efb23238e62e555caa5541d042a2ae..1dcf63a9ac1f313975f7fd318f783acd3f21147c 100644 (file)
@@ -30,7 +30,7 @@
  * in the  the priority mask, it indicates that PSR.I should be set and
  * interrupt disabling temporarily does not rely on IRQ priorities.
  */
-#define GIC_PRIO_IRQON                 0xc0
+#define GIC_PRIO_IRQON                 0xe0
 #define GIC_PRIO_IRQOFF                        (GIC_PRIO_IRQON & ~0x80)
 #define GIC_PRIO_PSR_I_SET             (1 << 4)
 
index df45af9314598167e98ffde7876e86dd5f8ef7d0..4d9b1f48dc39e800ac645eb14443367708c8d10e 100644 (file)
@@ -8,19 +8,12 @@
 #include <linux/percpu.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
+#include <linux/types.h>
 
 #include <asm/memory.h>
 #include <asm/ptrace.h>
 #include <asm/sdei.h>
 
-struct stackframe {
-       unsigned long fp;
-       unsigned long pc;
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       int graph;
-#endif
-};
-
 enum stack_type {
        STACK_TYPE_UNKNOWN,
        STACK_TYPE_TASK,
@@ -28,6 +21,7 @@ enum stack_type {
        STACK_TYPE_OVERFLOW,
        STACK_TYPE_SDEI_NORMAL,
        STACK_TYPE_SDEI_CRITICAL,
+       __NR_STACK_TYPES
 };
 
 struct stack_info {
@@ -36,6 +30,37 @@ struct stack_info {
        enum stack_type type;
 };
 
+/*
+ * A snapshot of a frame record or fp/lr register values, along with some
+ * accounting information necessary for robust unwinding.
+ *
+ * @fp:          The fp value in the frame record (or the real fp)
+ * @pc:          The fp value in the frame record (or the real lr)
+ *
+ * @stacks_done: Stacks which have been entirely unwound, for which it is no
+ *               longer valid to unwind to.
+ *
+ * @prev_fp:     The fp that pointed to this frame record, or a synthetic value
+ *               of 0. This is used to ensure that within a stack, each
+ *               subsequent frame record is at an increasing address.
+ * @prev_type:   The type of stack this frame record was on, or a synthetic
+ *               value of STACK_TYPE_UNKNOWN. This is used to detect a
+ *               transition from one stack to another.
+ *
+ * @graph:       When FUNCTION_GRAPH_TRACER is selected, holds the index of a
+ *               replacement lr value in the ftrace graph stack.
+ */
+struct stackframe {
+       unsigned long fp;
+       unsigned long pc;
+       DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
+       unsigned long prev_fp;
+       enum stack_type prev_type;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       int graph;
+#endif
+};
+
 extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
 extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
                            int (*fn)(struct stackframe *, void *), void *data);
@@ -64,8 +89,9 @@ static inline bool on_irq_stack(unsigned long sp,
        return true;
 }
 
-static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp,
-                               struct stack_info *info)
+static inline bool on_task_stack(const struct task_struct *tsk,
+                                unsigned long sp,
+                                struct stack_info *info)
 {
        unsigned long low = (unsigned long)task_stack_page(tsk);
        unsigned long high = low + THREAD_SIZE;
@@ -112,10 +138,13 @@ static inline bool on_overflow_stack(unsigned long sp,
  * We can only safely access per-cpu stacks from current in a non-preemptible
  * context.
  */
-static inline bool on_accessible_stack(struct task_struct *tsk,
-                                       unsigned long sp,
-                                       struct stack_info *info)
+static inline bool on_accessible_stack(const struct task_struct *tsk,
+                                      unsigned long sp,
+                                      struct stack_info *info)
 {
+       if (info)
+               info->type = STACK_TYPE_UNKNOWN;
+
        if (on_task_stack(tsk, sp, info))
                return true;
        if (tsk != current || preemptible())
@@ -130,4 +159,27 @@ static inline bool on_accessible_stack(struct task_struct *tsk,
        return false;
 }
 
+static inline void start_backtrace(struct stackframe *frame,
+                                  unsigned long fp, unsigned long pc)
+{
+       frame->fp = fp;
+       frame->pc = pc;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       frame->graph = 0;
+#endif
+
+       /*
+        * Prime the first unwind.
+        *
+        * In unwind_frame() we'll check that the FP points to a valid stack,
+        * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
+        * treated as a transition to whichever stack that happens to be. The
+        * prev_fp value won't be used, but we set it to 0 such that it is
+        * definitely not an accessible stack address.
+        */
+       bitmap_zero(frame->stacks_done, __NR_STACK_TYPES);
+       frame->prev_fp = 0;
+       frame->prev_type = STACK_TYPE_UNKNOWN;
+}
+
 #endif /* __ASM_STACKTRACE_H */
index f4812777f5c594e234b124e728c9f58c9cd8d431..c50ee1b7d5cd61d2146253f4325dc97c1ad8cfdf 100644 (file)
@@ -16,6 +16,8 @@
 
 #define VDSO_HAS_CLOCK_GETRES          1
 
+#define VDSO_HAS_32BIT_FALLBACK                1
+
 static __always_inline
 int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
                          struct timezone *_tz)
@@ -51,6 +53,23 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
        return ret;
 }
 
+static __always_inline
+long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+       register struct old_timespec32 *ts asm("r1") = _ts;
+       register clockid_t clkid asm("r0") = _clkid;
+       register long ret asm ("r0");
+       register long nr asm("r7") = __NR_compat_clock_gettime;
+
+       asm volatile(
+       "       swi #0\n"
+       : "=r" (ret)
+       : "r" (clkid), "r" (ts), "r" (nr)
+       : "memory");
+
+       return ret;
+}
+
 static __always_inline
 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
@@ -72,6 +91,27 @@ int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
        return ret;
 }
 
+static __always_inline
+int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+       register struct old_timespec32 *ts asm("r1") = _ts;
+       register clockid_t clkid asm("r0") = _clkid;
+       register long ret asm ("r0");
+       register long nr asm("r7") = __NR_compat_clock_getres;
+
+       /* The checks below are required for ABI consistency with arm */
+       if ((_clkid >= MAX_CLOCKS) && (_ts == NULL))
+               return -EINVAL;
+
+       asm volatile(
+       "       swi #0\n"
+       : "=r" (ret)
+       : "r" (clkid), "r" (ts), "r" (nr)
+       : "memory");
+
+       return ret;
+}
+
 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode)
 {
        u64 res;
index b551b741653d251d6155a214023b2215ae02e871..5e1e648aeec4c8216371ce84c92528be39c82eaa 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
 #define _UAPI__ASM_BPF_PERF_EVENT_H__
 
index f29f36a65175c2f0f318710d2909d7635c1f848b..b1fdc486aed8239c681acdcab1d98550bbdf60d9 100644 (file)
@@ -184,9 +184,17 @@ static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = {
 };
 
 static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
-       S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
-       S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
-       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
+       /*
+        * We already refuse to boot CPUs that don't support our configured
+        * page size, so we can only detect mismatches for a page size other
+        * than the one we're currently using. Unfortunately, SoCs like this
+        * exist in the wild so, even though we don't like it, we'll have to go
+        * along with it and treat them as non-strict.
+        */
+       S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
+       S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
+
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
        /* Linux shouldn't care about secure memory */
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
@@ -225,8 +233,8 @@ static const struct arm64_ftr_bits ftr_ctr[] = {
        ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */
        ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DIC_SHIFT, 1, 1),
        ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_IDC_SHIFT, 1, 1),
-       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, CTR_CWG_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, CTR_ERG_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_CWG_SHIFT, 4, 0),
+       ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_ERG_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DMINLINE_SHIFT, 4, 1),
        /*
         * Linux can handle differing I-cache policies. Userspace JITs will
@@ -468,6 +476,10 @@ static s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new,
        case FTR_LOWER_SAFE:
                ret = new < cur ? new : cur;
                break;
+       case FTR_HIGHER_OR_ZERO_SAFE:
+               if (!cur || !new)
+                       break;
+               /* Fallthrough */
        case FTR_HIGHER_SAFE:
                ret = new > cur ? new : cur;
                break;
index f8719bd308501e23c8ee2c15aa5010115fb08aa8..48222a4760c2e65229fc1f1cd39f6ecc3e1451a3 100644 (file)
@@ -207,16 +207,16 @@ static int call_step_hook(struct pt_regs *regs, unsigned int esr)
 
        list = user_mode(regs) ? &user_step_hook : &kernel_step_hook;
 
-       rcu_read_lock();
-
+       /*
+        * Since single-step exception disables interrupt, this function is
+        * entirely not preemptible, and we can use rcu list safely here.
+        */
        list_for_each_entry_rcu(hook, list, node)       {
                retval = hook->fn(regs, esr);
                if (retval == DBG_HOOK_HANDLED)
                        break;
        }
 
-       rcu_read_unlock();
-
        return retval;
 }
 NOKPROBE_SYMBOL(call_step_hook);
@@ -305,14 +305,16 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr)
 
        list = user_mode(regs) ? &user_break_hook : &kernel_break_hook;
 
-       rcu_read_lock();
+       /*
+        * Since brk exception disables interrupt, this function is
+        * entirely not preemptible, and we can use rcu list safely here.
+        */
        list_for_each_entry_rcu(hook, list, node) {
                unsigned int comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK;
 
                if ((comment & ~hook->mask) == hook->imm)
                        fn = hook->fn;
        }
-       rcu_read_unlock();
 
        return fn ? fn(regs, esr) : DBG_HOOK_ERROR;
 }
index 9cdc4592da3efdbd8f1bd8ade319b094f6e8da4f..320a30dbe35efb02e4f7d5bd52c82189e1f4400c 100644 (file)
@@ -586,10 +586,8 @@ el1_sync:
        b.eq    el1_ia
        cmp     x24, #ESR_ELx_EC_SYS64          // configurable trap
        b.eq    el1_undef
-       cmp     x24, #ESR_ELx_EC_SP_ALIGN       // stack alignment exception
-       b.eq    el1_sp_pc
        cmp     x24, #ESR_ELx_EC_PC_ALIGN       // pc alignment exception
-       b.eq    el1_sp_pc
+       b.eq    el1_pc
        cmp     x24, #ESR_ELx_EC_UNKNOWN        // unknown exception in EL1
        b.eq    el1_undef
        cmp     x24, #ESR_ELx_EC_BREAKPT_CUR    // debug exception in EL1
@@ -611,9 +609,11 @@ el1_da:
        bl      do_mem_abort
 
        kernel_exit 1
-el1_sp_pc:
+el1_pc:
        /*
-        * Stack or PC alignment exception handling
+        * PC alignment exception handling. We don't handle SP alignment faults,
+        * since we will have hit a recursive exception when trying to push the
+        * initial pt_regs.
         */
        mrs     x0, far_el1
        inherit_daif    pstate=x23, tmp=x2
@@ -732,9 +732,9 @@ el0_sync:
        ccmp    x24, #ESR_ELx_EC_WFx, #4, ne
        b.eq    el0_sys
        cmp     x24, #ESR_ELx_EC_SP_ALIGN       // stack alignment exception
-       b.eq    el0_sp_pc
+       b.eq    el0_sp
        cmp     x24, #ESR_ELx_EC_PC_ALIGN       // pc alignment exception
-       b.eq    el0_sp_pc
+       b.eq    el0_pc
        cmp     x24, #ESR_ELx_EC_UNKNOWN        // unknown exception in EL0
        b.eq    el0_undef
        cmp     x24, #ESR_ELx_EC_BREAKPT_LOW    // debug exception in EL0
@@ -758,7 +758,7 @@ el0_sync_compat:
        cmp     x24, #ESR_ELx_EC_FP_EXC32       // FP/ASIMD exception
        b.eq    el0_fpsimd_exc
        cmp     x24, #ESR_ELx_EC_PC_ALIGN       // pc alignment exception
-       b.eq    el0_sp_pc
+       b.eq    el0_pc
        cmp     x24, #ESR_ELx_EC_UNKNOWN        // unknown exception in EL0
        b.eq    el0_undef
        cmp     x24, #ESR_ELx_EC_CP15_32        // CP15 MRC/MCR trap
@@ -858,11 +858,15 @@ el0_fpsimd_exc:
        mov     x1, sp
        bl      do_fpsimd_exc
        b       ret_to_user
+el0_sp:
+       ldr     x26, [sp, #S_SP]
+       b       el0_sp_pc
+el0_pc:
+       mrs     x26, far_el1
 el0_sp_pc:
        /*
         * Stack or PC alignment exception handling
         */
-       mrs     x26, far_el1
        gic_prio_kentry_setup tmp=x0
        enable_da_f
 #ifdef CONFIG_TRACE_IRQFLAGS
index eec4776ae5f01a81ebe4c0f57f5626c8866e4d42..37d3912cfe06fc99678d9c85a18cca111357f499 100644 (file)
@@ -406,6 +406,18 @@ static __uint128_t arm64_cpu_to_le128(__uint128_t x)
 
 #define arm64_le128_to_cpu(x) arm64_cpu_to_le128(x)
 
+static void __fpsimd_to_sve(void *sst, struct user_fpsimd_state const *fst,
+                           unsigned int vq)
+{
+       unsigned int i;
+       __uint128_t *p;
+
+       for (i = 0; i < SVE_NUM_ZREGS; ++i) {
+               p = (__uint128_t *)ZREG(sst, vq, i);
+               *p = arm64_cpu_to_le128(fst->vregs[i]);
+       }
+}
+
 /*
  * Transfer the FPSIMD state in task->thread.uw.fpsimd_state to
  * task->thread.sve_state.
@@ -423,17 +435,12 @@ static void fpsimd_to_sve(struct task_struct *task)
        unsigned int vq;
        void *sst = task->thread.sve_state;
        struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;
-       unsigned int i;
-       __uint128_t *p;
 
        if (!system_supports_sve())
                return;
 
        vq = sve_vq_from_vl(task->thread.sve_vl);
-       for (i = 0; i < 32; ++i) {
-               p = (__uint128_t *)ZREG(sst, vq, i);
-               *p = arm64_cpu_to_le128(fst->vregs[i]);
-       }
+       __fpsimd_to_sve(sst, fst, vq);
 }
 
 /*
@@ -459,7 +466,7 @@ static void sve_to_fpsimd(struct task_struct *task)
                return;
 
        vq = sve_vq_from_vl(task->thread.sve_vl);
-       for (i = 0; i < 32; ++i) {
+       for (i = 0; i < SVE_NUM_ZREGS; ++i) {
                p = (__uint128_t const *)ZREG(sst, vq, i);
                fst->vregs[i] = arm64_le128_to_cpu(*p);
        }
@@ -550,8 +557,6 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
        unsigned int vq;
        void *sst = task->thread.sve_state;
        struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;
-       unsigned int i;
-       __uint128_t *p;
 
        if (!test_tsk_thread_flag(task, TIF_SVE))
                return;
@@ -559,11 +564,7 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
        vq = sve_vq_from_vl(task->thread.sve_vl);
 
        memset(sst, 0, SVE_SIG_REGS_SIZE(vq));
-
-       for (i = 0; i < 32; ++i) {
-               p = (__uint128_t *)ZREG(sst, vq, i);
-               *p = arm64_cpu_to_le128(fst->vregs[i]);
-       }
+       __fpsimd_to_sve(sst, fst, vq);
 }
 
 int sve_set_vector_length(struct task_struct *task,
index 1285c7b2947fa74cf50e66b83ec163b2d7a21027..17177325797420cea45062f349f5dde71b72119b 100644 (file)
@@ -73,7 +73,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
        if (offset < -SZ_128M || offset >= SZ_128M) {
 #ifdef CONFIG_ARM64_MODULE_PLTS
-               struct plt_entry trampoline;
+               struct plt_entry trampoline, *dst;
                struct module *mod;
 
                /*
@@ -106,23 +106,27 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
                 * to check if the actual opcodes are in fact identical,
                 * regardless of the offset in memory so use memcmp() instead.
                 */
-               trampoline = get_plt_entry(addr, mod->arch.ftrace_trampoline);
-               if (memcmp(mod->arch.ftrace_trampoline, &trampoline,
-                          sizeof(trampoline))) {
-                       if (plt_entry_is_initialized(mod->arch.ftrace_trampoline)) {
+               dst = mod->arch.ftrace_trampoline;
+               trampoline = get_plt_entry(addr, dst);
+               if (memcmp(dst, &trampoline, sizeof(trampoline))) {
+                       if (plt_entry_is_initialized(dst)) {
                                pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n");
                                return -EINVAL;
                        }
 
                        /* point the trampoline to our ftrace entry point */
                        module_disable_ro(mod);
-                       *mod->arch.ftrace_trampoline = trampoline;
+                       *dst = trampoline;
                        module_enable_ro(mod, true);
 
-                       /* update trampoline before patching in the branch */
-                       smp_wmb();
+                       /*
+                        * Ensure updated trampoline is visible to instruction
+                        * fetch before we patch in the branch.
+                        */
+                       __flush_icache_range((unsigned long)&dst[0],
+                                            (unsigned long)&dst[1]);
                }
-               addr = (unsigned long)(void *)mod->arch.ftrace_trampoline;
+               addr = (unsigned long)dst;
 #else /* CONFIG_ARM64_MODULE_PLTS */
                return -EINVAL;
 #endif /* CONFIG_ARM64_MODULE_PLTS */
index dceb8452094876c58cfacf93f350292084c02998..38ee1514cd9cde9135dc6e272b72a50ee702eb91 100644 (file)
@@ -536,13 +536,18 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
                        /* Aligned */
                        break;
                case 1:
-                       /* Allow single byte watchpoint. */
-                       if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
-                               break;
                case 2:
                        /* Allow halfword watchpoints and breakpoints. */
                        if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2)
                                break;
+
+                       /* Fallthrough */
+               case 3:
+                       /* Allow single byte watchpoint. */
+                       if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
+                               break;
+
+                       /* Fallthrough */
                default:
                        return -EINVAL;
                }
index 46e643e307082c0fee4129724ea74e9a98c99201..03ff15bffbb6db2d2e2cca75a20df06e6f174df0 100644 (file)
@@ -314,18 +314,21 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                /* MOVW instruction relocations. */
                case R_AARCH64_MOVW_UABS_G0_NC:
                        overflow_check = false;
+                       /* Fall through */
                case R_AARCH64_MOVW_UABS_G0:
                        ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0,
                                              AARCH64_INSN_IMM_MOVKZ);
                        break;
                case R_AARCH64_MOVW_UABS_G1_NC:
                        overflow_check = false;
+                       /* Fall through */
                case R_AARCH64_MOVW_UABS_G1:
                        ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16,
                                              AARCH64_INSN_IMM_MOVKZ);
                        break;
                case R_AARCH64_MOVW_UABS_G2_NC:
                        overflow_check = false;
+                       /* Fall through */
                case R_AARCH64_MOVW_UABS_G2:
                        ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32,
                                              AARCH64_INSN_IMM_MOVKZ);
@@ -393,6 +396,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                        break;
                case R_AARCH64_ADR_PREL_PG_HI21_NC:
                        overflow_check = false;
+                       /* Fall through */
                case R_AARCH64_ADR_PREL_PG_HI21:
                        ovf = reloc_insn_adrp(me, sechdrs, loc, val);
                        if (ovf && ovf != -ERANGE)
index 9d63514b983673bfd7ae55603254f48b297dd90f..b0e03e052dd1d5e2d80db3448b37a77b5634e094 100644 (file)
@@ -154,12 +154,7 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
                return;
        }
 
-       frame.fp = regs->regs[29];
-       frame.pc = regs->pc;
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       frame.graph = 0;
-#endif
-
+       start_backtrace(&frame, regs->regs[29], regs->pc);
        walk_stackframe(current, &frame, callchain_trace, entry);
 }
 
index bd5dfffca272c69dc2ccd4d7aa9f0f61aab5ceaa..c4452827419b0b4d947fb92c8bd2d281fc5d825e 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
 #include <asm/debug-monitors.h>
+#include <asm/daifflags.h>
 #include <asm/system_misc.h>
 #include <asm/insn.h>
 #include <linux/uaccess.h>
@@ -167,33 +168,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
        __this_cpu_write(current_kprobe, p);
 }
 
-/*
- * When PSTATE.D is set (masked), then software step exceptions can not be
- * generated.
- * SPSR's D bit shows the value of PSTATE.D immediately before the
- * exception was taken. PSTATE.D is set while entering into any exception
- * mode, however software clears it for any normal (none-debug-exception)
- * mode in the exception entry. Therefore, when we are entering into kprobe
- * breakpoint handler from any normal mode then SPSR.D bit is already
- * cleared, however it is set when we are entering from any debug exception
- * mode.
- * Since we always need to generate single step exception after a kprobe
- * breakpoint exception therefore we need to clear it unconditionally, when
- * we become sure that the current breakpoint exception is for kprobe.
- */
-static void __kprobes
-spsr_set_debug_flag(struct pt_regs *regs, int mask)
-{
-       unsigned long spsr = regs->pstate;
-
-       if (mask)
-               spsr |= PSR_D_BIT;
-       else
-               spsr &= ~PSR_D_BIT;
-
-       regs->pstate = spsr;
-}
-
 /*
  * Interrupts need to be disabled before single-step mode is set, and not
  * reenabled until after single-step mode ends.
@@ -205,17 +179,17 @@ spsr_set_debug_flag(struct pt_regs *regs, int mask)
 static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
                                                struct pt_regs *regs)
 {
-       kcb->saved_irqflag = regs->pstate;
+       kcb->saved_irqflag = regs->pstate & DAIF_MASK;
        regs->pstate |= PSR_I_BIT;
+       /* Unmask PSTATE.D for enabling software step exceptions. */
+       regs->pstate &= ~PSR_D_BIT;
 }
 
 static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
                                                struct pt_regs *regs)
 {
-       if (kcb->saved_irqflag & PSR_I_BIT)
-               regs->pstate |= PSR_I_BIT;
-       else
-               regs->pstate &= ~PSR_I_BIT;
+       regs->pstate &= ~DAIF_MASK;
+       regs->pstate |= kcb->saved_irqflag;
 }
 
 static void __kprobes
@@ -252,8 +226,6 @@ static void __kprobes setup_singlestep(struct kprobe *p,
 
                set_ss_context(kcb, slot);      /* mark pending ss */
 
-               spsr_set_debug_flag(regs, 0);
-
                /* IRQs and single stepping do not mix well. */
                kprobes_save_local_irqflag(kcb, regs);
                kernel_enable_single_step(regs);
index 6a869d9f304f73f4e6d91f52e5c4ac446fc9bf1a..f674f28df663b29aa26f4856aa837c14e1da4234 100644 (file)
@@ -398,7 +398,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
                        childregs->pstate |= PSR_UAO_BIT;
 
                if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE)
-                       childregs->pstate |= PSR_SSBS_BIT;
+                       set_ssbs_bit(childregs);
 
                if (system_uses_irq_prio_masking())
                        childregs->pmr_save = GIC_PRIO_IRQON;
@@ -442,6 +442,32 @@ void uao_thread_switch(struct task_struct *next)
        }
 }
 
+/*
+ * Force SSBS state on context-switch, since it may be lost after migrating
+ * from a CPU which treats the bit as RES0 in a heterogeneous system.
+ */
+static void ssbs_thread_switch(struct task_struct *next)
+{
+       struct pt_regs *regs = task_pt_regs(next);
+
+       /*
+        * Nothing to do for kernel threads, but 'regs' may be junk
+        * (e.g. idle task) so check the flags and bail early.
+        */
+       if (unlikely(next->flags & PF_KTHREAD))
+               return;
+
+       /* If the mitigation is enabled, then we leave SSBS clear. */
+       if ((arm64_get_ssbd_state() == ARM64_SSBD_FORCE_ENABLE) ||
+           test_tsk_thread_flag(next, TIF_SSBD))
+               return;
+
+       if (compat_user_mode(regs))
+               set_compat_ssbs_bit(regs);
+       else if (user_mode(regs))
+               set_ssbs_bit(regs);
+}
+
 /*
  * We store our current task in sp_el0, which is clobbered by userspace. Keep a
  * shadow copy so that we can restore this upon entry from userspace.
@@ -471,6 +497,7 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
        entry_task_switch(next);
        uao_thread_switch(next);
        ptrauth_thread_switch(next);
+       ssbs_thread_switch(next);
 
        /*
         * Complete any pending TLB or cache maintenance on this CPU in case
@@ -498,11 +525,8 @@ unsigned long get_wchan(struct task_struct *p)
        if (!stack_page)
                return 0;
 
-       frame.fp = thread_saved_fp(p);
-       frame.pc = thread_saved_pc(p);
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       frame.graph = 0;
-#endif
+       start_backtrace(&frame, thread_saved_fp(p), thread_saved_pc(p));
+
        do {
                if (unwind_frame(p, &frame))
                        goto out;
index b21cba90f82dd22d51ba63bbf9bd4801c1cb9cff..a5e8b3b9d798301285b2db09b031dbba6c481875 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/export.h>
 #include <linux/ftrace.h>
+#include <linux/kprobes.h>
 
 #include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
@@ -29,6 +30,7 @@ static int save_return_addr(struct stackframe *frame, void *d)
                return 0;
        }
 }
+NOKPROBE_SYMBOL(save_return_addr);
 
 void *return_address(unsigned int level)
 {
@@ -38,12 +40,9 @@ void *return_address(unsigned int level)
        data.level = level + 2;
        data.addr = NULL;
 
-       frame.fp = (unsigned long)__builtin_frame_address(0);
-       frame.pc = (unsigned long)return_address; /* dummy */
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       frame.graph = 0;
-#endif
-
+       start_backtrace(&frame,
+                       (unsigned long)__builtin_frame_address(0),
+                       (unsigned long)return_address);
        walk_stackframe(current, &frame, save_return_addr, &data);
 
        if (!data.level)
@@ -52,3 +51,4 @@ void *return_address(unsigned int level)
                return NULL;
 }
 EXPORT_SYMBOL_GPL(return_address);
+NOKPROBE_SYMBOL(return_address);
index ea90d3bd92539eb7585f768d3b87e565f33af786..018a33e01b0ed2fdac2997b34d6065979bc343e1 100644 (file)
@@ -152,8 +152,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
                                pr_crit("CPU%u: died during early boot\n", cpu);
                                break;
                        }
-                       /* Fall through */
                        pr_crit("CPU%u: may not have shut down cleanly\n", cpu);
+                       /* Fall through */
                case CPU_STUCK_IN_KERNEL:
                        pr_crit("CPU%u: is stuck in kernel\n", cpu);
                        if (status & CPU_STUCK_REASON_52_BIT_VA)
index 62d395151abe650db40e14df52c9061c531a2bfa..a336cb124320f789b35ec778a73e8bc6791b8177 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/ftrace.h>
+#include <linux/kprobes.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
 #include <linux/sched/task_stack.h>
  *     ldp     x29, x30, [sp]
  *     add     sp, sp, #0x10
  */
+
+/*
+ * Unwind from one frame record (A) to the next frame record (B).
+ *
+ * We terminate early if the location of B indicates a malformed chain of frame
+ * records (e.g. a cycle), determined based on the location and fp value of A
+ * and the location (but not the fp value) of B.
+ */
 int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
 {
        unsigned long fp = frame->fp;
+       struct stack_info info;
 
        if (fp & 0xf)
                return -EINVAL;
@@ -39,11 +49,40 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
        if (!tsk)
                tsk = current;
 
-       if (!on_accessible_stack(tsk, fp, NULL))
+       if (!on_accessible_stack(tsk, fp, &info))
+               return -EINVAL;
+
+       if (test_bit(info.type, frame->stacks_done))
                return -EINVAL;
 
+       /*
+        * As stacks grow downward, any valid record on the same stack must be
+        * at a strictly higher address than the prior record.
+        *
+        * Stacks can nest in several valid orders, e.g.
+        *
+        * TASK -> IRQ -> OVERFLOW -> SDEI_NORMAL
+        * TASK -> SDEI_NORMAL -> SDEI_CRITICAL -> OVERFLOW
+        *
+        * ... but the nesting itself is strict. Once we transition from one
+        * stack to another, it's never valid to unwind back to that first
+        * stack.
+        */
+       if (info.type == frame->prev_type) {
+               if (fp <= frame->prev_fp)
+                       return -EINVAL;
+       } else {
+               set_bit(frame->prev_type, frame->stacks_done);
+       }
+
+       /*
+        * Record this frame record's values and location. The prev_fp and
+        * prev_type are only meaningful to the next unwind_frame() invocation.
+        */
        frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
        frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8));
+       frame->prev_fp = fp;
+       frame->prev_type = info.type;
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        if (tsk->ret_stack &&
@@ -73,6 +112,7 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
 
        return 0;
 }
+NOKPROBE_SYMBOL(unwind_frame);
 
 void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
                     int (*fn)(struct stackframe *, void *), void *data)
@@ -87,6 +127,7 @@ void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
                        break;
        }
 }
+NOKPROBE_SYMBOL(walk_stackframe);
 
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
@@ -122,12 +163,7 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
        data.skip = trace->skip;
        data.no_sched_functions = 0;
 
-       frame.fp = regs->regs[29];
-       frame.pc = regs->pc;
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       frame.graph = 0;
-#endif
-
+       start_backtrace(&frame, regs->regs[29], regs->pc);
        walk_stackframe(current, &frame, save_trace, &data);
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_regs);
@@ -146,17 +182,15 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
        data.no_sched_functions = nosched;
 
        if (tsk != current) {
-               frame.fp = thread_saved_fp(tsk);
-               frame.pc = thread_saved_pc(tsk);
+               start_backtrace(&frame, thread_saved_fp(tsk),
+                               thread_saved_pc(tsk));
        } else {
                /* We don't want this function nor the caller */
                data.skip += 2;
-               frame.fp = (unsigned long)__builtin_frame_address(0);
-               frame.pc = (unsigned long)__save_stack_trace;
+               start_backtrace(&frame,
+                               (unsigned long)__builtin_frame_address(0),
+                               (unsigned long)__save_stack_trace);
        }
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       frame.graph = 0;
-#endif
 
        walk_stackframe(tsk, &frame, save_trace, &data);
 
index 9f25aedeac9dddda7cd9293cf38fac4532419139..0b2946414dc9ccc6fdb2b62b4a0de58b239c7fa2 100644 (file)
@@ -38,11 +38,8 @@ unsigned long profile_pc(struct pt_regs *regs)
        if (!in_lock_functions(regs->pc))
                return regs->pc;
 
-       frame.fp = regs->regs[29];
-       frame.pc = regs->pc;
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       frame.graph = 0;
-#endif
+       start_backtrace(&frame, regs->regs[29], regs->pc);
+
        do {
                int ret = unwind_frame(NULL, &frame);
                if (ret < 0)
index 8c03456dade6a477f62a2d051b267ae925704132..32893b3d9164e70ec7d0dcf11619840f07def078 100644 (file)
@@ -100,18 +100,17 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
                return;
 
        if (tsk == current) {
-               frame.fp = (unsigned long)__builtin_frame_address(0);
-               frame.pc = (unsigned long)dump_backtrace;
+               start_backtrace(&frame,
+                               (unsigned long)__builtin_frame_address(0),
+                               (unsigned long)dump_backtrace);
        } else {
                /*
                 * task blocked in __switch_to
                 */
-               frame.fp = thread_saved_fp(tsk);
-               frame.pc = thread_saved_pc(tsk);
+               start_backtrace(&frame,
+                               thread_saved_fp(tsk),
+                               thread_saved_pc(tsk));
        }
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       frame.graph = 0;
-#endif
 
        printk("Call trace:\n");
        do {
@@ -734,6 +733,7 @@ static const char *esr_class_str[] = {
        [ESR_ELx_EC_CP14_LS]            = "CP14 LDC/STC",
        [ESR_ELx_EC_FP_ASIMD]           = "ASIMD",
        [ESR_ELx_EC_CP10_ID]            = "CP10 MRC/VMRS",
+       [ESR_ELx_EC_PAC]                = "PAC",
        [ESR_ELx_EC_CP14_64]            = "CP14 MCRR/MRRC",
        [ESR_ELx_EC_ILL]                = "PSTATE.IL",
        [ESR_ELx_EC_SVC32]              = "SVC (AArch32)",
index 4ab8630451881f19a840189619013277a54b1114..dd2514bb1511fe4fa72271bb9af38564c4fe5607 100644 (file)
@@ -32,10 +32,10 @@ UBSAN_SANITIZE                      := n
 OBJECT_FILES_NON_STANDARD      := y
 KCOV_INSTRUMENT                        := n
 
-ifeq ($(c-gettimeofday-y),)
 CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny
-else
-CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny -include $(c-gettimeofday-y)
+
+ifneq ($(c-gettimeofday-y),)
+  CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
 endif
 
 # Clang versions less than 8 do not support -mcmodel=tiny
@@ -57,8 +57,7 @@ $(obj)/vdso.o : $(obj)/vdso.so
 
 # Link rule for the .so file, .lds has to be first
 $(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
-       $(call if_changed,ld)
-       $(call if_changed,vdso_check)
+       $(call if_changed,vdsold_and_vdso_check)
 
 # Strip rule for the .so file
 $(obj)/%.so: OBJCOPYFLAGS := -S
@@ -74,8 +73,8 @@ include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
        $(call if_changed,vdsosym)
 
 # Actual build commands
-quiet_cmd_vdsocc = VDSOCC   $@
-      cmd_vdsocc = $(CC) $(a_flags) $(c_flags) -c -o $@ $<
+quiet_cmd_vdsold_and_vdso_check = LD      $@
+      cmd_vdsold_and_vdso_check = $(cmd_ld); $(cmd_vdso_check)
 
 # Install commands for the unstripped file
 quiet_cmd_vdso_install = INSTALL $@
index 60a4c6239712522bf5f13350e8a7facb41f5e319..1fba0776ed40edca833e7cabe936dfb909ae91a1 100644 (file)
@@ -144,8 +144,7 @@ $(obj)/vdso.so.dbg: $(obj)/vdso.so.raw $(obj)/$(munge) FORCE
 
 # Link rule for the .so file, .lds has to be first
 $(obj)/vdso.so.raw: $(src)/vdso.lds $(obj-vdso) FORCE
-       $(call if_changed,vdsold)
-       $(call if_changed,vdso_check)
+       $(call if_changed,vdsold_and_vdso_check)
 
 # Compilation rules for the vDSO sources
 $(c-obj-vdso): %.o: %.c FORCE
@@ -156,14 +155,17 @@ $(asm-obj-vdso): %.o: %.S FORCE
        $(call if_changed_dep,vdsoas)
 
 # Actual build commands
-quiet_cmd_vdsold = VDSOL   $@
+quiet_cmd_vdsold_and_vdso_check = LD32    $@
+      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
+
+quiet_cmd_vdsold = LD32    $@
       cmd_vdsold = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_LDFLAGS) \
                    -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
-quiet_cmd_vdsocc = VDSOC   $@
+quiet_cmd_vdsocc = CC32    $@
       cmd_vdsocc = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_CFLAGS) -c -o $@ $<
-quiet_cmd_vdsocc_gettimeofday = VDSOC_GTD   $@
+quiet_cmd_vdsocc_gettimeofday = CC32    $@
       cmd_vdsocc_gettimeofday = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_CFLAGS) $(VDSO_CFLAGS_gettimeofday_o) -c -o $@ $<
-quiet_cmd_vdsoas = VDSOA   $@
+quiet_cmd_vdsoas = AS32    $@
       cmd_vdsoas = $(COMPATCC) -Wp,-MD,$(depfile) $(VDSO_AFLAGS) -c -o $@ $<
 
 quiet_cmd_vdsomunge = MUNGE   $@
index 26781da3ad3e2258153693470ec2d39914133d2e..0fc9872a1467107203dfca22867c6887f3eff551 100644 (file)
 #define save_debug(ptr,reg,nr)                                         \
        switch (nr) {                                                   \
        case 15:        ptr[15] = read_debug(reg, 15);                  \
+                       /* Fall through */                              \
        case 14:        ptr[14] = read_debug(reg, 14);                  \
+                       /* Fall through */                              \
        case 13:        ptr[13] = read_debug(reg, 13);                  \
+                       /* Fall through */                              \
        case 12:        ptr[12] = read_debug(reg, 12);                  \
+                       /* Fall through */                              \
        case 11:        ptr[11] = read_debug(reg, 11);                  \
+                       /* Fall through */                              \
        case 10:        ptr[10] = read_debug(reg, 10);                  \
+                       /* Fall through */                              \
        case 9:         ptr[9] = read_debug(reg, 9);                    \
+                       /* Fall through */                              \
        case 8:         ptr[8] = read_debug(reg, 8);                    \
+                       /* Fall through */                              \
        case 7:         ptr[7] = read_debug(reg, 7);                    \
+                       /* Fall through */                              \
        case 6:         ptr[6] = read_debug(reg, 6);                    \
+                       /* Fall through */                              \
        case 5:         ptr[5] = read_debug(reg, 5);                    \
+                       /* Fall through */                              \
        case 4:         ptr[4] = read_debug(reg, 4);                    \
+                       /* Fall through */                              \
        case 3:         ptr[3] = read_debug(reg, 3);                    \
+                       /* Fall through */                              \
        case 2:         ptr[2] = read_debug(reg, 2);                    \
+                       /* Fall through */                              \
        case 1:         ptr[1] = read_debug(reg, 1);                    \
+                       /* Fall through */                              \
        default:        ptr[0] = read_debug(reg, 0);                    \
        }
 
 #define restore_debug(ptr,reg,nr)                                      \
        switch (nr) {                                                   \
        case 15:        write_debug(ptr[15], reg, 15);                  \
+                       /* Fall through */                              \
        case 14:        write_debug(ptr[14], reg, 14);                  \
+                       /* Fall through */                              \
        case 13:        write_debug(ptr[13], reg, 13);                  \
+                       /* Fall through */                              \
        case 12:        write_debug(ptr[12], reg, 12);                  \
+                       /* Fall through */                              \
        case 11:        write_debug(ptr[11], reg, 11);                  \
+                       /* Fall through */                              \
        case 10:        write_debug(ptr[10], reg, 10);                  \
+                       /* Fall through */                              \
        case 9:         write_debug(ptr[9], reg, 9);                    \
+                       /* Fall through */                              \
        case 8:         write_debug(ptr[8], reg, 8);                    \
+                       /* Fall through */                              \
        case 7:         write_debug(ptr[7], reg, 7);                    \
+                       /* Fall through */                              \
        case 6:         write_debug(ptr[6], reg, 6);                    \
+                       /* Fall through */                              \
        case 5:         write_debug(ptr[5], reg, 5);                    \
+                       /* Fall through */                              \
        case 4:         write_debug(ptr[4], reg, 4);                    \
+                       /* Fall through */                              \
        case 3:         write_debug(ptr[3], reg, 3);                    \
+                       /* Fall through */                              \
        case 2:         write_debug(ptr[2], reg, 2);                    \
+                       /* Fall through */                              \
        case 1:         write_debug(ptr[1], reg, 1);                    \
+                       /* Fall through */                              \
        default:        write_debug(ptr[0], reg, 0);                    \
        }
 
index 0d60e4f0af6659df6ddf4dd7bafe0dc34749c798..a900181e386786a9ae09a7bc49eaa9e5e39db84a 100644 (file)
@@ -178,13 +178,18 @@ void vcpu_write_spsr32(struct kvm_vcpu *vcpu, unsigned long v)
        switch (spsr_idx) {
        case KVM_SPSR_SVC:
                write_sysreg_el1(v, SYS_SPSR);
+               break;
        case KVM_SPSR_ABT:
                write_sysreg(v, spsr_abt);
+               break;
        case KVM_SPSR_UND:
                write_sysreg(v, spsr_und);
+               break;
        case KVM_SPSR_IRQ:
                write_sysreg(v, spsr_irq);
+               break;
        case KVM_SPSR_FIQ:
                write_sysreg(v, spsr_fiq);
+               break;
        }
 }
index f26e181d881c36f3bd15618a3e0813f56b84c446..2071260a275bd236923da5650da86a012eaa5b4a 100644 (file)
@@ -632,7 +632,7 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
         */
        val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
               | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
-       __vcpu_sys_reg(vcpu, PMCR_EL0) = val;
+       __vcpu_sys_reg(vcpu, r->reg) = val;
 }
 
 static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
@@ -981,13 +981,13 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 /* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
 #define DBG_BCR_BVR_WCR_WVR_EL1(n)                                     \
        { SYS_DESC(SYS_DBGBVRn_EL1(n)),                                 \
-         trap_bvr, reset_bvr, n, 0, get_bvr, set_bvr },                \
+         trap_bvr, reset_bvr, 0, 0, get_bvr, set_bvr },                \
        { SYS_DESC(SYS_DBGBCRn_EL1(n)),                                 \
-         trap_bcr, reset_bcr, n, 0, get_bcr, set_bcr },                \
+         trap_bcr, reset_bcr, 0, 0, get_bcr, set_bcr },                \
        { SYS_DESC(SYS_DBGWVRn_EL1(n)),                                 \
-         trap_wvr, reset_wvr, n, 0,  get_wvr, set_wvr },               \
+         trap_wvr, reset_wvr, 0, 0,  get_wvr, set_wvr },               \
        { SYS_DESC(SYS_DBGWCRn_EL1(n)),                                 \
-         trap_wcr, reset_wcr, n, 0,  get_wcr, set_wcr }
+         trap_wcr, reset_wcr, 0, 0,  get_wcr, set_wcr }
 
 /* Macro to expand the PMEVCNTRn_EL0 register */
 #define PMU_PMEVCNTR_EL0(n)                                            \
@@ -1540,7 +1540,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
        { SYS_DESC(SYS_CTR_EL0), access_ctr },
 
-       { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, },
+       { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, PMCR_EL0 },
        { SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
        { SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, NULL, PMCNTENSET_EL0 },
        { SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, NULL, PMOVSSET_EL0 },
@@ -2254,13 +2254,19 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
 }
 
 static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
-                             const struct sys_reg_desc *table, size_t num)
+                               const struct sys_reg_desc *table, size_t num,
+                               unsigned long *bmap)
 {
        unsigned long i;
 
        for (i = 0; i < num; i++)
-               if (table[i].reset)
+               if (table[i].reset) {
+                       int reg = table[i].reg;
+
                        table[i].reset(vcpu, &table[i]);
+                       if (reg > 0 && reg < NR_SYS_REGS)
+                               set_bit(reg, bmap);
+               }
 }
 
 /**
@@ -2774,18 +2780,16 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
 {
        size_t num;
        const struct sys_reg_desc *table;
-
-       /* Catch someone adding a register without putting in reset entry. */
-       memset(&vcpu->arch.ctxt.sys_regs, 0x42, sizeof(vcpu->arch.ctxt.sys_regs));
+       DECLARE_BITMAP(bmap, NR_SYS_REGS) = { 0, };
 
        /* Generic chip reset first (so target could override). */
-       reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
+       reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs), bmap);
 
        table = get_target_table(vcpu->arch.target, true, &num);
-       reset_sys_reg_descs(vcpu, table, num);
+       reset_sys_reg_descs(vcpu, table, num, bmap);
 
        for (num = 1; num < NR_SYS_REGS; num++) {
-               if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242,
+               if (WARN(!test_bit(num, bmap),
                         "Didn't reset __vcpu_sys_reg(%zi)\n", num))
                        break;
        }
index 1d3f0b5a99400757bf361c4127e43f38c3916dee..bd2b039f43a622d6ce190cef0643ac8fb12dbe2d 100644 (file)
@@ -14,9 +14,7 @@
 pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
                unsigned long attrs)
 {
-       if (!dev_is_dma_coherent(dev) || (attrs & DMA_ATTR_WRITE_COMBINE))
-               return pgprot_writecombine(prot);
-       return prot;
+       return pgprot_writecombine(prot);
 }
 
 void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
index 9568c116ac7fc629994790a3d06125d5e2f44ca9..cfd65b63f36fd05f15557e872bb9e6ec96efa973 100644 (file)
@@ -777,6 +777,53 @@ void __init hook_debug_fault_code(int nr,
        debug_fault_info[nr].name       = name;
 }
 
+/*
+ * In debug exception context, we explicitly disable preemption despite
+ * having interrupts disabled.
+ * This serves two purposes: it makes it much less likely that we would
+ * accidentally schedule in exception context and it will force a warning
+ * if we somehow manage to schedule by accident.
+ */
+static void debug_exception_enter(struct pt_regs *regs)
+{
+       /*
+        * Tell lockdep we disabled irqs in entry.S. Do nothing if they were
+        * already disabled to preserve the last enabled/disabled addresses.
+        */
+       if (interrupts_enabled(regs))
+               trace_hardirqs_off();
+
+       if (user_mode(regs)) {
+               RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
+       } else {
+               /*
+                * We might have interrupted pretty much anything.  In
+                * fact, if we're a debug exception, we can even interrupt
+                * NMI processing. We don't want this code makes in_nmi()
+                * to return true, but we need to notify RCU.
+                */
+               rcu_nmi_enter();
+       }
+
+       preempt_disable();
+
+       /* This code is a bit fragile.  Test it. */
+       RCU_LOCKDEP_WARN(!rcu_is_watching(), "exception_enter didn't work");
+}
+NOKPROBE_SYMBOL(debug_exception_enter);
+
+static void debug_exception_exit(struct pt_regs *regs)
+{
+       preempt_enable_no_resched();
+
+       if (!user_mode(regs))
+               rcu_nmi_exit();
+
+       if (interrupts_enabled(regs))
+               trace_hardirqs_on();
+}
+NOKPROBE_SYMBOL(debug_exception_exit);
+
 #ifdef CONFIG_ARM64_ERRATUM_1463225
 DECLARE_PER_CPU(int, __in_cortex_a76_erratum_1463225_wa);
 
@@ -817,12 +864,7 @@ asmlinkage void __exception do_debug_exception(unsigned long addr_if_watchpoint,
        if (cortex_a76_erratum_1463225_debug_handler(regs))
                return;
 
-       /*
-        * Tell lockdep we disabled irqs in entry.S. Do nothing if they were
-        * already disabled to preserve the last enabled/disabled addresses.
-        */
-       if (interrupts_enabled(regs))
-               trace_hardirqs_off();
+       debug_exception_enter(regs);
 
        if (user_mode(regs) && !is_ttbr0_addr(pc))
                arm64_apply_bp_hardening();
@@ -832,7 +874,6 @@ asmlinkage void __exception do_debug_exception(unsigned long addr_if_watchpoint,
                                 inf->sig, inf->code, (void __user *)pc, esr);
        }
 
-       if (interrupts_enabled(regs))
-               trace_hardirqs_on();
+       debug_exception_exit(regs);
 }
 NOKPROBE_SYMBOL(do_debug_exception);
index b079ec715cdf7eaaec2aa7c75f5ce72e014b48e2..d150cd66487333a1c9b3f3b62ca73fd04c6823f9 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
 #ifndef __ASM_CSKY_BYTEORDER_H
index ddf2f39aa9251470ffb88e8ee6a7afb98be0016d..ed7fad1ea20d647c0ba2fcc390ae08210e05094b 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 
 #ifndef __ASM_CSKY_CACHECTL_H
 #define __ASM_CSKY_CACHECTL_H
index ee323d818592c6ce559603f0da15d715b236880c..49d4e147a5596ff8f5683b3373b21dcaf59ba4d2 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
 
 #ifndef _ASM_CSKY_PERF_REGS_H
index 4e248d5b86efa42327bb2aa58a287ad3eab564a4..66b2268e324eb56ca618b9df15ebfe179ade5994 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
 #ifndef _CSKY_PTRACE_H
index e81e7ff11e3602e141c8685e583eddb837fdb260..670c020f2cb89da19e45758c99b8220c27f47314 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
 #ifndef __ASM_CSKY_SIGCONTEXT_H
index ec60e49cea661d16c187bc433bc66969fd9423e7..211c983c7282d13f3b75150e686c8e815fd7777b 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
 #define __ARCH_WANT_SYS_CLONE
index 1f730ded52245739e5aadcb404acdde23a10c573..cc88a08bc1f736422a561a093f3cd24cf757ea2b 100644 (file)
@@ -398,6 +398,7 @@ static int dwc3_octeon_clocks_start(struct device *dev, u64 base)
        default:
                dev_err(dev, "Invalid ref_clk %u, using 100000000 instead\n",
                        clock_rate);
+               /* fall through */
        case 100000000:
                mpll_mul = 0x19;
                if (ref_clk_sel < 2)
index 52cf96ea43e5dfdba220101d5f1f6eef64875148..cbc7cdae1c6a43220cb1c7a4f0f34d779065180e 100644 (file)
@@ -46,6 +46,7 @@ static inline uint64_t CVMX_SLI_PCIE_MSI_RCV_FUNC(void)
        case OCTEON_CN78XX & OCTEON_FAMILY_MASK:
                if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))
                        return 0x0000000000003CB0ull;
+               /* Else, fall through */
        default:
                return 0x0000000000023CB0ull;
        }
index e0dd66881da68ce927bf17a9b9aa0ed064b0cc7a..f777e44653d5767b953483f22158d24e84e6461f 100644 (file)
@@ -69,6 +69,8 @@ static int __populate_cache_leaves(unsigned int cpu)
        if (c->tcache.waysize)
                populate_cache(tcache, this_leaf, 3, CACHE_TYPE_UNIFIED);
 
+       this_cpu_ci->cpu_map_populated = true;
+
        return 0;
 }
 
index 5f209f111e59e3ad9c6e31bee8352623cacc3e68..df7ddd246eaac730333bc24cc361f1893be100aa 100644 (file)
@@ -32,7 +32,8 @@ void __init setup_pit_timer(void)
 
 static int __init init_pit_clocksource(void)
 {
-       if (num_possible_cpus() > 1) /* PIT does not scale! */
+       if (num_possible_cpus() > 1 || /* PIT does not scale! */
+           !clockevent_state_periodic(&i8253_clockevent))
                return 0;
 
        return clocksource_i8253_init();
index e5de6bac81979122f0a8464d66c2df81c1eeafd2..754094b40a75332c1f8cb58266a5181a44ef142d 100644 (file)
@@ -140,6 +140,7 @@ static int kvm_compute_return_epc(struct kvm_vcpu *vcpu, unsigned long instpc,
                /* These are unconditional and in j_format. */
        case jal_op:
                arch->gprs[31] = instpc + 8;
+               /* fall through */
        case j_op:
                epc += 4;
                epc >>= 28;
index 2cfe839f0b3a776898595c480d66807d161910f4..1109924560d8c7c8a437e45fd1af5904a16a4075 100644 (file)
@@ -150,16 +150,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        return 0;
 }
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
-       return 0;
-}
-
 void kvm_mips_free_vcpus(struct kvm *kvm)
 {
        unsigned int i;
index 7c04b17f4a488aa8e50186be84dd0fcc50125ba2..96c13a0ab0788904d7e06319c26927f4a11da260 100644 (file)
@@ -172,12 +172,15 @@ static void mipsxx_cpu_setup(void *args)
        case 4:
                w_c0_perfctrl3(0);
                w_c0_perfcntr3(reg.counter[3]);
+               /* fall through */
        case 3:
                w_c0_perfctrl2(0);
                w_c0_perfcntr2(reg.counter[2]);
+               /* fall through */
        case 2:
                w_c0_perfctrl1(0);
                w_c0_perfcntr1(reg.counter[1]);
+               /* fall through */
        case 1:
                w_c0_perfctrl0(0);
                w_c0_perfcntr0(reg.counter[0]);
@@ -195,10 +198,13 @@ static void mipsxx_cpu_start(void *args)
        switch (counters) {
        case 4:
                w_c0_perfctrl3(WHAT | reg.control[3]);
+               /* fall through */
        case 3:
                w_c0_perfctrl2(WHAT | reg.control[2]);
+               /* fall through */
        case 2:
                w_c0_perfctrl1(WHAT | reg.control[1]);
+               /* fall through */
        case 1:
                w_c0_perfctrl0(WHAT | reg.control[0]);
        }
@@ -215,10 +221,13 @@ static void mipsxx_cpu_stop(void *args)
        switch (counters) {
        case 4:
                w_c0_perfctrl3(0);
+               /* fall through */
        case 3:
                w_c0_perfctrl2(0);
+               /* fall through */
        case 2:
                w_c0_perfctrl1(0);
+               /* fall through */
        case 1:
                w_c0_perfctrl0(0);
        }
@@ -236,6 +245,7 @@ static int mipsxx_perfcount_handler(void)
 
        switch (counters) {
 #define HANDLE_COUNTER(n)                                              \
+       /* fall through */                                              \
        case n + 1:                                                     \
                control = r_c0_perfctrl ## n();                         \
                counter = r_c0_perfcntr ## n();                         \
@@ -297,12 +307,15 @@ static void reset_counters(void *arg)
        case 4:
                w_c0_perfctrl3(0);
                w_c0_perfcntr3(0);
+               /* fall through */
        case 3:
                w_c0_perfctrl2(0);
                w_c0_perfcntr2(0);
+               /* fall through */
        case 2:
                w_c0_perfctrl1(0);
                w_c0_perfcntr1(0);
+               /* fall through */
        case 1:
                w_c0_perfctrl0(0);
                w_c0_perfcntr0(0);
index d02eb9d16b55590e9740d1bde1e1b1178569896a..925c72348fb6ea5c95d1483acb7875c6bc613045 100644 (file)
@@ -474,6 +474,7 @@ static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
                if (PCI_SLOT(devfn) == 0)
                        return bcm_pcie_readl(PCIE_DLSTATUS_REG)
                                        & DLSTATUS_PHYLINKUP;
+               /* else, fall through */
        default:
                return false;
        }
index 14b1931be69c3acf78afc794d4b3f0a3bbac5ecc..b65b169778e31478fcc507c12c88fcb1436cdf6b 100644 (file)
@@ -9,6 +9,7 @@
 #if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT)
 
 /* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */
+#define BUILD_VDSO32_64
 #undef CONFIG_64BIT
 #define CONFIG_32BIT 1
 #ifndef __ASSEMBLY__
index b5d58ea8decbb0a299efeb1c5fc1e4a1c19acff9..bc0b92ab8c15b65afedd67edfc972c10397c2b7a 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2005-2017 Andes Technology Corporation
 
 #ifndef __ASM_AUXVEC_H
index 511e653c709d54692483508f3ae8a71c03e662cd..c264ef12c49c8f8751a4d141924daa0f24573c0e 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2005-2017 Andes Technology Corporation
 
 #ifndef __NDS32_BYTEORDER_H__
index 73793662815c849a4776bfb042e4f9f050dde254..31b9b439d81931a7fb66adb7b134fa298f7392bb 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 1994, 1995, 1996 by Ralf Baechle
 // Copyright (C) 2005-2017 Andes Technology Corporation
 #ifndef        _ASM_CACHECTL
index d54a5d6c65389b8fff804962c052995671be1c5a..f17396db16ece076f26a48f423986d3bea729702 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /* Copyright (C) 2005-2019 Andes Technology Corporation */
 #ifndef        _FP_UDF_IEX_CRTL_H
 #define        _FP_UDF_IEX_CRTL_H
index 2977534a6bd3129df9a1ec5c17a7e1a46a150def..48d00328d3281b80b559bd0f4ea2dc399b9be337 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2005-2017 Andes Technology Corporation
 
 #ifndef __ASM_NDS32_PARAM_H
index 1a6e01c00e6f880607d1e5b43ad0432f5c3abc00..d76217c7c0107cff732691070c8260a872932559 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2005-2017 Andes Technology Corporation
 
 #ifndef __UAPI_ASM_NDS32_PTRACE_H
index dc89af7ddcc3d0ce497c13a04787c78f12df12ba..6c1e6648878fd0b75aacf1c245555adc237d70ff 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2005-2017 Andes Technology Corporation
 
 #ifndef _ASMNDS32_SIGCONTEXT_H
index a0b2f7b9c0f29a8b1b2c5a42f6c7032033590d22..410795e280fef5cf144dd172a45cb4bc1cd174ae 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2005-2017 Andes Technology Corporation
 
 #define __ARCH_WANT_STAT64
index fe61513982b4a916a8ba50b545b8c9bf207d6780..330b19fcd990317d7c34e5a986f677f54e3f2851 100644 (file)
@@ -316,6 +316,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
                                regs->uregs[0] = -EINTR;
                                break;
                        }
+                       /* Else, fall through */
                case -ERESTARTNOINTR:
                        regs->uregs[0] = regs->orig_r0;
                        regs->ipc -= 4;
@@ -360,6 +361,7 @@ static void do_signal(struct pt_regs *regs)
                switch (regs->uregs[0]) {
                case -ERESTART_RESTARTBLOCK:
                        regs->uregs[15] = __NR_restart_syscall;
+                       /* Fall through */
                case -ERESTARTNOHAND:
                case -ERESTARTSYS:
                case -ERESTARTNOINTR:
index 8acb8fa1f8d69fefa3d0d47f2e72797aa392cb78..3b77d729057f94740f4df7bfc6d44c76e84b1319 100644 (file)
@@ -19,8 +19,6 @@
 
 KBUILD_IMAGE := vmlinuz
 
-KBUILD_DEFCONFIG := default_defconfig
-
 NM             = sh $(srctree)/arch/parisc/nm
 CHECKFLAGS     += -D__hppa__=1
 LIBGCC         = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
@@ -182,5 +180,8 @@ define archhelp
        @echo  '  zinstall      - Install compressed vmlinuz kernel'
 endef
 
+archclean:
+       $(Q)$(MAKE) $(clean)=$(boot)
+
 archheaders:
        $(Q)$(MAKE) $(build)=arch/parisc/kernel/syscalls all
index 2da8624e5cf62a9ccebdd01cabe2f32e1465db40..1e5879c6a7522892e38e95334cf1fc3fc4519af9 100644 (file)
@@ -12,6 +12,7 @@ UBSAN_SANITIZE := n
 targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2
 targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4
 targets += misc.o piggy.o sizes.h head.o real2.o firmware.o
+targets += real2.S firmware.c
 
 KBUILD_CFLAGS := -D__KERNEL__ -O2 -DBOOTLOADER
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
@@ -55,7 +56,8 @@ $(obj)/misc.o: $(obj)/sizes.h
 CPPFLAGS_vmlinux.lds += -I$(objtree)/$(obj) -DBOOTLOADER
 $(obj)/vmlinux.lds: $(obj)/sizes.h
 
-$(obj)/vmlinux.bin: vmlinux
+OBJCOPYFLAGS_vmlinux.bin := -R .comment -R .note -S
+$(obj)/vmlinux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
 
 vmlinux.bin.all-y := $(obj)/vmlinux.bin
index bfd7872739a38d7a32b211803af5c60c671f6c0d..2ac3a643f2eb3cc2b4846296dd5ba6dfc9c1ff56 100644 (file)
@@ -48,8 +48,8 @@ SECTIONS
                *(.rodata.compressed)
        }
 
-       /* bootloader code and data starts behind area of extracted kernel */
-       . = (SZ_end - SZparisc_kernel_start + KERNEL_BINARY_TEXT_START);
+       /* bootloader code and data starts at least behind area of extracted kernel */
+       . = MAX(ABSOLUTE(.), (SZ_end - SZparisc_kernel_start + KERNEL_BINARY_TEXT_START));
 
        /* align on next page boundary */
        . = ALIGN(4096);
diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/default_defconfig
deleted file mode 100644 (file)
index 5b877ca..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PA7100LC=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_IOMMU_CCIO=y
-CONFIG_GSC_LASI=y
-CONFIG_GSC_WAX=y
-CONFIG_EISA=y
-CONFIG_PCI=y
-CONFIG_GSC_DINO=y
-CONFIG_PCI_LBA=y
-CONFIG_PCCARD=y
-CONFIG_YENTA=y
-CONFIG_PD6729=y
-CONFIG_I82092=y
-CONFIG_BINFMT_MISC=m
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_DIAG=m
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-CONFIG_LLC2=m
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_PCMCIA=m
-CONFIG_PARPORT_1284=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_NS87415=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_LASI700=y
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_ZALON=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID10=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_NETDEVICES=y
-CONFIG_BONDING=m
-CONFIG_DUMMY=m
-CONFIG_TUN=m
-CONFIG_ACENIC=y
-CONFIG_TIGON3=y
-CONFIG_NET_TULIP=y
-CONFIG_TULIP=y
-CONFIG_LASI_82596=y
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-# CONFIG_KEYBOARD_HIL_OLD is not set
-CONFIG_MOUSE_SERIAL=y
-CONFIG_LEGACY_PTY_COUNT=64
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_CS=y
-CONFIG_SERIAL_8250_NR_UARTS=17
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_PRINTER=m
-CONFIG_PPDEV=m
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-CONFIG_DUMMY_CONSOLE_COLUMNS=128
-CONFIG_DUMMY_CONSOLE_ROWS=48
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_DYNAMIC_MINORS=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_AD1889=y
-CONFIG_SND_HARMONY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_NTRIG=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_HID_TOPSEED=y
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_VFAT_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V4=y
-CONFIG_CIFS=m
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=y
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_FS=y
-CONFIG_HEADERS_INSTALL=y
-CONFIG_HEADERS_CHECK=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_KEYS=y
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-# CONFIG_CRYPTO_HW is not set
-CONFIG_LIBCRC32C=m
-CONFIG_FONTS=y
diff --git a/arch/parisc/configs/defconfig b/arch/parisc/configs/defconfig
new file mode 100644 (file)
index 0000000..5b877ca
--- /dev/null
@@ -0,0 +1,206 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PA7100LC=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_EISA=y
+CONFIG_PCI=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_PCCARD=y
+CONFIG_YENTA=y
+CONFIG_PD6729=y
+CONFIG_I82092=y
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_DIAG=m
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_LLC2=m
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_1284=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_NS87415=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_LASI700=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_ZALON=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_TUN=m
+CONFIG_ACENIC=y
+CONFIG_TIGON3=y
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+CONFIG_LASI_82596=y
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+# CONFIG_KEYBOARD_HIL_OLD is not set
+CONFIG_MOUSE_SERIAL=y
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=17
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_PRINTER=m
+CONFIG_PPDEV=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_AD1889=y
+CONFIG_SND_HARMONY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_USB=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V4=y
+CONFIG_CIFS=m
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_FS=y
+CONFIG_HEADERS_INSTALL=y
+CONFIG_HEADERS_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+# CONFIG_CRYPTO_HW is not set
+CONFIG_LIBCRC32C=m
+CONFIG_FONTS=y
index e09cf2deeafec4961ae630ddb2d2a76cdb4d50b0..904034da4974525e1cac1b6506011eaf20a1b1ae 100644 (file)
@@ -50,6 +50,10 @@ struct kprobe_ctlblk {
 
 int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs);
 int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs);
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+       return 0;
+}
 
 #endif /* CONFIG_KPROBES */
 #endif /* _PARISC_KPROBES_H */
index a39b079e73f25758e184b0acf20209b4fe6fb8f0..6d58c1739b4239619095fe181431cdf7eaa2d4b5 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef _PARISC_PGTABLE_H
 #define _PARISC_PGTABLE_H
 
+#include <asm/page.h>
 #include <asm-generic/4level-fixup.h>
 
 #include <asm/fixmap.h>
@@ -98,8 +99,6 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 
 #endif /* !__ASSEMBLY__ */
 
-#include <asm/page.h>
-
 #define pte_ERROR(e) \
        printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
 #define pmd_ERROR(e) \
index d784ccdd8fef6bfd329c48567c988c43b747d3dc..b6fb30f2e4bfd26531145d8612b2be10b253da21 100644 (file)
@@ -181,8 +181,9 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
        for (i = 0; i < ARRAY_SIZE(insn); i++)
                insn[i] = INSN_NOP;
 
+       __patch_text((void *)rec->ip, INSN_NOP);
        __patch_text_multiple((void *)rec->ip + 4 - sizeof(insn),
-                             insn, sizeof(insn));
+                             insn, sizeof(insn)-4);
        return 0;
 }
 #endif
index ba67893a1d7275ba79a66852a0d089e1cd918ae1..df46b0e5a915fab2cbde7049ad4e4d9e602462fe 100644 (file)
@@ -63,7 +63,7 @@ ENTRY_CFI(flush_tlb_all_local)
 
        /* Flush Instruction Tlb */
 
-       LDREG           ITLB_SID_BASE(%r1), %r20
+88:    LDREG           ITLB_SID_BASE(%r1), %r20
        LDREG           ITLB_SID_STRIDE(%r1), %r21
        LDREG           ITLB_SID_COUNT(%r1), %r22
        LDREG           ITLB_OFF_BASE(%r1), %arg0
@@ -103,6 +103,7 @@ fitonemiddle:                                       /* Loop if LOOP = 1 */
        add             %r21, %r20, %r20                /* increment space */
 
 fitdone:
+       ALTERNATIVE(88b, fitdone, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
 
        /* Flush Data Tlb */
 
index b6c4b254901abb3874d7d51f244a9d9c468e6604..3747a0cbd3b8fc1b150e67fb067c3994149119e1 100644 (file)
@@ -18,3 +18,4 @@ obj-y  := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \
 # other very old or stripped-down PA-RISC CPUs -- not currently supported
 
 obj-$(CONFIG_MATH_EMULATION)   += unimplemented-math-emulation.o
+CFLAGS_REMOVE_fpudispatch.o    = -Wimplicit-fallthrough
index 6dd4669ce7a5572fb48dcd92f9b31b650e731af8..adbd5e2144a34303023372e99b0452b0ce43bafa 100644 (file)
@@ -66,6 +66,7 @@ parisc_acctyp(unsigned long code, unsigned int inst)
        case 0x30000000: /* coproc2 */
                if (bit22set(inst))
                        return VM_WRITE;
+               /* fall through */
 
        case 0x0: /* indexed/memory management */
                if (bit22set(inst)) {
index b3388d95f4510e0d919f8d068cb2b191a675ae26..45e3137ccd71c21fb835a1938c8cd36aa16d5949 100644 (file)
@@ -107,22 +107,22 @@ extern void _set_L3CR(unsigned long);
 
 static inline void dcbz(void *addr)
 {
-       __asm__ __volatile__ ("dcbz %y0" : : "Z"(*(u8 *)addr) : "memory");
+       __asm__ __volatile__ ("dcbz 0, %0" : : "r"(addr) : "memory");
 }
 
 static inline void dcbi(void *addr)
 {
-       __asm__ __volatile__ ("dcbi %y0" : : "Z"(*(u8 *)addr) : "memory");
+       __asm__ __volatile__ ("dcbi 0, %0" : : "r"(addr) : "memory");
 }
 
 static inline void dcbf(void *addr)
 {
-       __asm__ __volatile__ ("dcbf %y0" : : "Z"(*(u8 *)addr) : "memory");
+       __asm__ __volatile__ ("dcbf 0, %0" : : "r"(addr) : "memory");
 }
 
 static inline void dcbst(void *addr)
 {
-       __asm__ __volatile__ ("dcbst %y0" : : "Z"(*(u8 *)addr) : "memory");
+       __asm__ __volatile__ ("dcbst 0, %0" : : "r"(addr) : "memory");
 }
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
index 463c63a9fcf16c34be39be93e963af3c13db6a97..11112023e327d7ccc695323545d396f5aadf49fd 100644 (file)
 #define H_SCM_UNBIND_MEM        0x3F0
 #define H_SCM_QUERY_BLOCK_MEM_BINDING 0x3F4
 #define H_SCM_QUERY_LOGICAL_MEM_BINDING 0x3F8
-#define H_SCM_MEM_QUERY                0x3FC
-#define H_SCM_BLOCK_CLEAR       0x400
-#define MAX_HCALL_OPCODE       H_SCM_BLOCK_CLEAR
+#define H_SCM_UNBIND_ALL        0x3FC
+#define H_SCM_HEALTH            0x400
+#define H_SCM_PERFORMANCE_STATS 0x418
+#define MAX_HCALL_OPCODE       H_SCM_PERFORMANCE_STATS
+
+/* Scope args for H_SCM_UNBIND_ALL */
+#define H_UNBIND_SCOPE_ALL (0x1)
+#define H_UNBIND_SCOPE_DRC (0x2)
 
 /* H_VIOCTL functions */
 #define H_GET_VIOA_DUMP_SIZE   0x01
index dc9a1ca70edf73ed4a8ebb653104dd2593d0816c..c6bbe9778d3cd3d8973dd2e7cb49404b43037093 100644 (file)
@@ -27,11 +27,10 @@ static inline void ppc_set_pmu_inuse(int inuse)
 #ifdef CONFIG_PPC_PSERIES
                get_lppaca()->pmcregs_in_use = inuse;
 #endif
-       } else {
+       }
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
-               get_paca()->pmcregs_in_use = inuse;
+       get_paca()->pmcregs_in_use = inuse;
 #endif
-       }
 #endif
 }
 
index 68473c3c471cacad92b82958f2202ad1ab0ec984..b0720c7c3fcf620ceaa212266e4fc6c02c2a2989 100644 (file)
@@ -49,6 +49,7 @@
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_CLONE3
 
 #endif         /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_UNISTD_H_ */
index b551b741653d251d6155a214023b2215ae02e871..5e1e648aeec4c8216371ce84c92528be39c82eaa 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
 #define _UAPI__ASM_BPF_PERF_EVENT_H__
 
index 01555c6ae0f57e86b40aebd0acd4883754fdf682..be48c2215fa2270be027e2458d60f1d271c2bf38 100644 (file)
@@ -31,7 +31,7 @@
  * Struct fields are always 32 or 64 bit aligned, depending on them being 32
  * or 64 bit wide respectively.
  *
- * See Documentation/virtual/kvm/ppc-pv.txt
+ * See Documentation/virt/kvm/ppc-pv.txt
  */
 struct kvm_vcpu_arch_shared {
        __u64 scratch1;
index 7107ad86de65d1632e29d677d8979824ef0e9908..92045ed649762f0ebea1f7d93b3ff6603f2b68fc 100644 (file)
@@ -176,9 +176,11 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
                        ret |= __get_user_inatomic(temp.v[1], p++);
                        ret |= __get_user_inatomic(temp.v[2], p++);
                        ret |= __get_user_inatomic(temp.v[3], p++);
+                       /* fall through */
                case 4:
                        ret |= __get_user_inatomic(temp.v[4], p++);
                        ret |= __get_user_inatomic(temp.v[5], p++);
+                       /* fall through */
                case 2:
                        ret |= __get_user_inatomic(temp.v[6], p++);
                        ret |= __get_user_inatomic(temp.v[7], p++);
@@ -259,9 +261,11 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
                        ret |= __put_user_inatomic(data.v[1], p++);
                        ret |= __put_user_inatomic(data.v[2], p++);
                        ret |= __put_user_inatomic(data.v[3], p++);
+                       /* fall through */
                case 4:
                        ret |= __put_user_inatomic(data.v[4], p++);
                        ret |= __put_user_inatomic(data.v[5], p++);
+                       /* fall through */
                case 2:
                        ret |= __put_user_inatomic(data.v[6], p++);
                        ret |= __put_user_inatomic(data.v[7], p++);
index 85fdb6d879f174365f828859b5e8a047e5aafcfa..54fab22c9a4355edfdd41e1557b6e27c7c73c7ff 100644 (file)
@@ -597,6 +597,14 @@ ppc_clone:
        stw     r0,_TRAP(r1)            /* register set saved */
        b       sys_clone
 
+       .globl  ppc_clone3
+ppc_clone3:
+       SAVE_NVGPRS(r1)
+       lwz     r0,_TRAP(r1)
+       rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
+       stw     r0,_TRAP(r1)            /* register set saved */
+       b       sys_clone3
+
        .globl  ppc_swapcontext
 ppc_swapcontext:
        SAVE_NVGPRS(r1)
index d9105fcf4021cac77120fc87ed1a70ab961a6201..0a0b5310f54a6fac4664b9180cdd67603b733543 100644 (file)
@@ -487,6 +487,11 @@ _GLOBAL(ppc_clone)
        bl      sys_clone
        b       .Lsyscall_exit
 
+_GLOBAL(ppc_clone3)
+       bl      save_nvgprs
+       bl      sys_clone3
+       b       .Lsyscall_exit
+
 _GLOBAL(ppc32_swapcontext)
        bl      save_nvgprs
        bl      compat_sys_swapcontext
index eee5bef736c8a4160ecabc3fd79d17a1aeaeec77..6ba3cc2ef8abc950fed977388d7f1ce601b3a90d 100644 (file)
@@ -1531,7 +1531,7 @@ EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
  *
  * Call convention:
  *
- * syscall register convention is in Documentation/powerpc/syscall64-abi.txt
+ * syscall register convention is in Documentation/powerpc/syscall64-abi.rst
  *
  * For hypercalls, the register convention is as follows:
  * r0 volatile
index 8fc4de0d22b4ce9cf8b3bbf3e6906211172d6a07..7a84c9f1778e6ade2878ea5387b58d7c91794c8f 100644 (file)
@@ -101,21 +101,8 @@ static void check_if_tm_restore_required(struct task_struct *tsk)
        }
 }
 
-static bool tm_active_with_fp(struct task_struct *tsk)
-{
-       return MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
-               (tsk->thread.ckpt_regs.msr & MSR_FP);
-}
-
-static bool tm_active_with_altivec(struct task_struct *tsk)
-{
-       return MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
-               (tsk->thread.ckpt_regs.msr & MSR_VEC);
-}
 #else
 static inline void check_if_tm_restore_required(struct task_struct *tsk) { }
-static inline bool tm_active_with_fp(struct task_struct *tsk) { return false; }
-static inline bool tm_active_with_altivec(struct task_struct *tsk) { return false; }
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 bool strict_msr_control;
@@ -252,7 +239,7 @@ EXPORT_SYMBOL(enable_kernel_fp);
 
 static int restore_fp(struct task_struct *tsk)
 {
-       if (tsk->thread.load_fp || tm_active_with_fp(tsk)) {
+       if (tsk->thread.load_fp) {
                load_fp_state(&current->thread.fp_state);
                current->thread.load_fp++;
                return 1;
@@ -334,8 +321,7 @@ EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
 
 static int restore_altivec(struct task_struct *tsk)
 {
-       if (cpu_has_feature(CPU_FTR_ALTIVEC) &&
-               (tsk->thread.load_vec || tm_active_with_altivec(tsk))) {
+       if (cpu_has_feature(CPU_FTR_ALTIVEC) && (tsk->thread.load_vec)) {
                load_vr_state(&tsk->thread.vr_state);
                tsk->thread.used_vr = 1;
                tsk->thread.load_vec++;
@@ -497,13 +483,14 @@ void giveup_all(struct task_struct *tsk)
        if (!tsk->thread.regs)
                return;
 
+       check_if_tm_restore_required(tsk);
+
        usermsr = tsk->thread.regs->msr;
 
        if ((usermsr & msr_all_available) == 0)
                return;
 
        msr_check_and_set(msr_all_available);
-       check_if_tm_restore_required(tsk);
 
        WARN_ON((usermsr & MSR_VSX) && !((usermsr & MSR_FP) && (usermsr & MSR_VEC)));
 
index f50b708d6d7716572c1c8e97812548bd6babdb1c..98600b276f764d957fe5f8d91386c921a288cc90 100644 (file)
@@ -1198,6 +1198,9 @@ SYSCALL_DEFINE0(rt_sigreturn)
                        goto bad;
 
                if (MSR_TM_ACTIVE(msr_hi<<32)) {
+                       /* Trying to start TM on non TM system */
+                       if (!cpu_has_feature(CPU_FTR_TM))
+                               goto bad;
                        /* We only recheckpoint on return if we're
                         * transaction.
                         */
index 2f80e270c7b0b7b30986b9adb884a6125d709534..117515564ec7a6e2d13ecdeba37e3973934fba10 100644 (file)
@@ -771,6 +771,11 @@ SYSCALL_DEFINE0(rt_sigreturn)
        if (MSR_TM_ACTIVE(msr)) {
                /* We recheckpoint on return. */
                struct ucontext __user *uc_transact;
+
+               /* Trying to start TM on non TM system */
+               if (!cpu_has_feature(CPU_FTR_TM))
+                       goto badframe;
+
                if (__get_user(uc_transact, &uc->uc_link))
                        goto badframe;
                if (restore_tm_sigcontexts(current, &uc->uc_mcontext,
index 3331749aab20abdd84d21d019240b8cecc60dfba..43f736ed47f28a1dff42ffb7ae7b3e19613e0211 100644 (file)
 432    common  fsmount                         sys_fsmount
 433    common  fspick                          sys_fspick
 434    common  pidfd_open                      sys_pidfd_open
-# 435 reserved for clone3
+435    nospu   clone3                          ppc_clone3
index 6539361778578e8b141b99f77f0b2fc46825cb8d..18f244aad7aaa46c1eb45db0f6a283c3d11d9be0 100644 (file)
@@ -239,6 +239,7 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
                                case 2:
                                case 6:
                                        pte->may_write = true;
+                                       /* fall through */
                                case 3:
                                case 5:
                                case 7:
index e99a14798ab0b833c5566243856187248a38c5fc..c4b606fe73ebcefb3b58594213f5bbea746c6257 100644 (file)
@@ -660,8 +660,10 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
                }
                tce = be64_to_cpu(tce);
 
-               if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua))
-                       return H_PARAMETER;
+               if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua)) {
+                       ret = H_PARAMETER;
+                       goto unlock_exit;
+               }
 
                list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
                        ret = kvmppc_tce_iommu_map(vcpu->kvm, stt,
index f50bbeedfc66b3c4022f56776731e176e6ca51f1..b4f20f13b8604a3fa1f431c2f5c37e7c03ccbf24 100644 (file)
@@ -556,8 +556,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
                unsigned long tce = be64_to_cpu(((u64 *)tces)[i]);
 
                ua = 0;
-               if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua, NULL))
-                       return H_PARAMETER;
+               if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua, NULL)) {
+                       ret = H_PARAMETER;
+                       goto unlock_exit;
+               }
 
                list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
                        ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
index ec1804f822afbed618ce83df4ab0673f9a626737..cde3f5a4b3e4709fe06a0eb27628a3fd537e30b9 100644 (file)
@@ -3569,9 +3569,18 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
        mtspr(SPRN_DEC, vcpu->arch.dec_expires - mftb());
 
        if (kvmhv_on_pseries()) {
+               /*
+                * We need to save and restore the guest visible part of the
+                * psscr (i.e. using SPRN_PSSCR_PR) since the hypervisor
+                * doesn't do this for us. Note only required if pseries since
+                * this is done in kvmhv_load_hv_regs_and_go() below otherwise.
+                */
+               unsigned long host_psscr;
                /* call our hypervisor to load up HV regs and go */
                struct hv_guest_state hvregs;
 
+               host_psscr = mfspr(SPRN_PSSCR_PR);
+               mtspr(SPRN_PSSCR_PR, vcpu->arch.psscr);
                kvmhv_save_hv_regs(vcpu, &hvregs);
                hvregs.lpcr = lpcr;
                vcpu->arch.regs.msr = vcpu->arch.shregs.msr;
@@ -3590,6 +3599,8 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
                vcpu->arch.shregs.msr = vcpu->arch.regs.msr;
                vcpu->arch.shregs.dar = mfspr(SPRN_DAR);
                vcpu->arch.shregs.dsisr = mfspr(SPRN_DSISR);
+               vcpu->arch.psscr = mfspr(SPRN_PSSCR_PR);
+               mtspr(SPRN_PSSCR_PR, host_psscr);
 
                /* H_CEDE has to be handled now, not later */
                if (trap == BOOK3S_INTERRUPT_SYSCALL && !vcpu->arch.nested &&
@@ -3654,6 +3665,8 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
                vcpu->arch.vpa.dirty = 1;
                save_pmu = lp->pmcregs_in_use;
        }
+       /* Must save pmu if this guest is capable of running nested guests */
+       save_pmu |= nesting_enabled(vcpu->kvm);
 
        kvmhv_save_guest_pmu(vcpu, save_pmu);
 
index 6ca0d7376a9f8ec1e2aa72aa8f2744e61c9732cb..e3ba67095895ab35c721b46675a8380fb073e01e 100644 (file)
@@ -1986,10 +1986,8 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type)
 
        xive->single_escalation = xive_native_has_single_escalation();
 
-       if (ret) {
-               kfree(xive);
+       if (ret)
                return ret;
-       }
 
        return 0;
 }
index 5596c8ec221ac627a7e948feb8c9b422006b793d..a998823f68a322cf1b9400d9f2b7efdf916e92b6 100644 (file)
@@ -1090,9 +1090,9 @@ static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type)
        xive->ops = &kvmppc_xive_native_ops;
 
        if (ret)
-               kfree(xive);
+               return ret;
 
-       return ret;
+       return 0;
 }
 
 /*
index 0dba7eb24f92072616460ae7cee6f90205025917..3e566c2e6066748c82cb3c43eed2fe27d255f982 100644 (file)
@@ -50,6 +50,11 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
        return !!(v->arch.pending_exceptions) || kvm_request_pending(v);
 }
 
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+       return kvm_arch_vcpu_runnable(vcpu);
+}
+
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
 {
        return false;
@@ -452,16 +457,6 @@ err_out:
        return -EINVAL;
 }
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
-       return 0;
-}
-
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
        unsigned int i;
index 9a5963e07a8247fc663115da60b28246f2d97016..b8ad14bb11704edb30a71892d871c7e98dd50a4d 100644 (file)
@@ -1899,11 +1899,20 @@ void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
         *
         * For guests on platforms before POWER9, we clamp the it limit to 1G
         * to avoid some funky things such as RTAS bugs etc...
+        *
+        * On POWER9 we limit to 1TB in case the host erroneously told us that
+        * the RMA was >1TB. Effective address bits 0:23 are treated as zero
+        * (meaning the access is aliased to zero i.e. addr = addr % 1TB)
+        * for virtual real mode addressing and so it doesn't make sense to
+        * have an area larger than 1TB as it can't be addressed.
         */
        if (!early_cpu_has_feature(CPU_FTR_HVMODE)) {
                ppc64_rma_size = first_memblock_size;
                if (!early_cpu_has_feature(CPU_FTR_ARCH_300))
                        ppc64_rma_size = min_t(u64, ppc64_rma_size, 0x40000000);
+               else
+                       ppc64_rma_size = min_t(u64, ppc64_rma_size,
+                                              1UL << SID_SHIFT_1T);
 
                /* Finally limit subsequent allocations */
                memblock_set_current_limit(ppc64_rma_size);
index 0d62be3cba47b8f6d22340ccba961800d8b86d4c..74f4555a62ba50cc5bbee38467e912477044e2cb 100644 (file)
@@ -21,7 +21,7 @@ static void kasan_populate_pte(pte_t *ptep, pgprot_t prot)
                __set_pte_at(&init_mm, va, ptep, pfn_pte(PHYS_PFN(pa), prot), 0);
 }
 
-static int kasan_init_shadow_page_tables(unsigned long k_start, unsigned long k_end)
+static int __ref kasan_init_shadow_page_tables(unsigned long k_start, unsigned long k_end)
 {
        pmd_t *pmd;
        unsigned long k_cur, k_next;
@@ -35,7 +35,10 @@ static int kasan_init_shadow_page_tables(unsigned long k_start, unsigned long k_
                if ((void *)pmd_page_vaddr(*pmd) != kasan_early_shadow_pte)
                        continue;
 
-               new = pte_alloc_one_kernel(&init_mm);
+               if (slab_is_available())
+                       new = pte_alloc_one_kernel(&init_mm);
+               else
+                       new = memblock_alloc(PTE_FRAG_SIZE, PTE_FRAG_SIZE);
 
                if (!new)
                        return -ENOMEM;
index 9259337d737466b247d7c5241fff78f2a7856047..9191a66b3bc55666ca94b589ddadd8661cd325bd 100644 (file)
@@ -239,7 +239,7 @@ void __init paging_init(void)
 
 #ifdef CONFIG_ZONE_DMA
        max_zone_pfns[ZONE_DMA] = min(max_low_pfn,
-                       ((1UL << ARCH_ZONE_DMA_BITS) - 1) >> PAGE_SHIFT);
+                                     1UL << (ARCH_ZONE_DMA_BITS - PAGE_SHIFT));
 #endif
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 #ifdef CONFIG_HIGHMEM
index d4acf6fa0596ff8c978fa5b4f47e4268972771c1..bf60983a58c7818c5ba2d36471b37df45cf26c90 100644 (file)
@@ -630,7 +630,6 @@ static void early_init_this_mmu(void)
 #ifdef CONFIG_PPC_FSL_BOOK3E
        if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
                unsigned int num_cams;
-               int __maybe_unused cpu = smp_processor_id();
                bool map = true;
 
                /* use a quarter of the TLBCAM for bolted linear map */
index c8ec670ee924e9d32615a1bf50b8bf0fe4c041fe..a5ac371a3f066ecbabb1c2899a4e36468e598a01 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/sched.h>
 #include <linux/libnvdimm.h>
 #include <linux/platform_device.h>
+#include <linux/delay.h>
 
 #include <asm/plpar_wrappers.h>
 
@@ -43,8 +44,9 @@ struct papr_scm_priv {
 static int drc_pmem_bind(struct papr_scm_priv *p)
 {
        unsigned long ret[PLPAR_HCALL_BUFSIZE];
-       uint64_t rc, token;
        uint64_t saved = 0;
+       uint64_t token;
+       int64_t rc;
 
        /*
         * When the hypervisor cannot map all the requested memory in a single
@@ -64,6 +66,10 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
        } while (rc == H_BUSY);
 
        if (rc) {
+               /* H_OVERLAP needs a separate error path */
+               if (rc == H_OVERLAP)
+                       return -EBUSY;
+
                dev_err(&p->pdev->dev, "bind err: %lld\n", rc);
                return -ENXIO;
        }
@@ -78,22 +84,36 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
 static int drc_pmem_unbind(struct papr_scm_priv *p)
 {
        unsigned long ret[PLPAR_HCALL_BUFSIZE];
-       uint64_t rc, token;
+       uint64_t token = 0;
+       int64_t rc;
 
-       token = 0;
+       dev_dbg(&p->pdev->dev, "unbind drc %x\n", p->drc_index);
 
-       /* NB: unbind has the same retry requirements mentioned above */
+       /* NB: unbind has the same retry requirements as drc_pmem_bind() */
        do {
-               rc = plpar_hcall(H_SCM_UNBIND_MEM, ret, p->drc_index,
-                               p->bound_addr, p->blocks, token);
+
+               /* Unbind of all SCM resources associated with drcIndex */
+               rc = plpar_hcall(H_SCM_UNBIND_ALL, ret, H_UNBIND_SCOPE_DRC,
+                                p->drc_index, token);
                token = ret[0];
-               cond_resched();
+
+               /* Check if we are stalled for some time */
+               if (H_IS_LONG_BUSY(rc)) {
+                       msleep(get_longbusy_msecs(rc));
+                       rc = H_BUSY;
+               } else if (rc == H_BUSY) {
+                       cond_resched();
+               }
+
        } while (rc == H_BUSY);
 
        if (rc)
                dev_err(&p->pdev->dev, "unbind error: %lld\n", rc);
+       else
+               dev_dbg(&p->pdev->dev, "unbind drc %x complete\n",
+                       p->drc_index);
 
-       return !!rc;
+       return rc == H_SUCCESS ? 0 : -ENXIO;
 }
 
 static int papr_scm_meta_get(struct papr_scm_priv *p,
@@ -255,12 +275,32 @@ static const struct attribute_group *papr_scm_dimm_groups[] = {
        NULL,
 };
 
+static inline int papr_scm_node(int node)
+{
+       int min_dist = INT_MAX, dist;
+       int nid, min_node;
+
+       if ((node == NUMA_NO_NODE) || node_online(node))
+               return node;
+
+       min_node = first_online_node;
+       for_each_online_node(nid) {
+               dist = node_distance(node, nid);
+               if (dist < min_dist) {
+                       min_dist = dist;
+                       min_node = nid;
+               }
+       }
+       return min_node;
+}
+
 static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
 {
        struct device *dev = &p->pdev->dev;
        struct nd_mapping_desc mapping;
        struct nd_region_desc ndr_desc;
        unsigned long dimm_flags;
+       int target_nid, online_nid;
 
        p->bus_desc.ndctl = papr_scm_ndctl;
        p->bus_desc.module = THIS_MODULE;
@@ -299,8 +339,10 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
 
        memset(&ndr_desc, 0, sizeof(ndr_desc));
        ndr_desc.attr_groups = region_attr_groups;
-       ndr_desc.numa_node = dev_to_node(&p->pdev->dev);
-       ndr_desc.target_node = ndr_desc.numa_node;
+       target_nid = dev_to_node(&p->pdev->dev);
+       online_nid = papr_scm_node(target_nid);
+       ndr_desc.numa_node = online_nid;
+       ndr_desc.target_node = target_nid;
        ndr_desc.res = &p->res;
        ndr_desc.of_node = p->dn;
        ndr_desc.provider_data = p;
@@ -318,6 +360,9 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
                                ndr_desc.res, p->dn);
                goto err;
        }
+       if (target_nid != online_nid)
+               dev_info(dev, "Region registered with target node %d and online node %d",
+                        target_nid, online_nid);
 
        return 0;
 
@@ -389,6 +434,14 @@ static int papr_scm_probe(struct platform_device *pdev)
 
        /* request the hypervisor to bind this region to somewhere in memory */
        rc = drc_pmem_bind(p);
+
+       /* If phyp says drc memory still bound then force unbound and retry */
+       if (rc == -EBUSY) {
+               dev_warn(&pdev->dev, "Retrying bind after unbinding\n");
+               drc_pmem_unbind(p);
+               rc = drc_pmem_bind(p);
+       }
+
        if (rc)
                goto err;
 
index 082c7e1c20f0372a386b3a7c023ba1fd7f187aca..1cdb39575eae789acfb715d4be45f2281a59b810 100644 (file)
@@ -479,7 +479,7 @@ static int xive_find_target_in_mask(const struct cpumask *mask,
         * Now go through the entire mask until we find a valid
         * target.
         */
-       for (;;) {
+       do {
                /*
                 * We re-check online as the fallback case passes us
                 * an untested affinity mask
@@ -487,12 +487,11 @@ static int xive_find_target_in_mask(const struct cpumask *mask,
                if (cpu_online(cpu) && xive_try_pick_target(cpu))
                        return cpu;
                cpu = cpumask_next(cpu, mask);
-               if (cpu == first)
-                       break;
                /* Wrap around */
                if (cpu >= nr_cpu_ids)
                        cpu = cpumask_first(mask);
-       }
+       } while (cpu != first);
+
        return -1;
 }
 
index 40983491b95fd12b2e616e4a0609e1f9940a5a23..42b5ec2231008ede5252f96b506fd50752eef018 100644 (file)
@@ -21,7 +21,6 @@
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-               timebase-frequency = <1000000>;
                cpu0: cpu@0 {
                        compatible = "sifive,e51", "sifive,rocket0", "riscv";
                        device_type = "cpu";
                        #size-cells = <0>;
                        status = "disabled";
                };
+               eth0: ethernet@10090000 {
+                       compatible = "sifive,fu540-c000-gem";
+                       interrupt-parent = <&plic0>;
+                       interrupts = <53>;
+                       reg = <0x0 0x10090000 0x0 0x2000
+                              0x0 0x100a0000 0x0 0x1000>;
+                       local-mac-address = [00 00 00 00 00 00];
+                       clock-names = "pclk", "hclk";
+                       clocks = <&prci PRCI_CLK_GEMGXLPLL>,
+                                <&prci PRCI_CLK_GEMGXLPLL>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
        };
 };
index 0b55c53c08c7ae56a426914d3c46c8db8a5b8a4e..93d68cbd64fe71ec0026d95e2b845c7c299326cc 100644 (file)
                disable-wp;
        };
 };
+
+&eth0 {
+       status = "okay";
+       phy-mode = "gmii";
+       phy-handle = <&phy0>;
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+};
index b7b749b18853475394ab0545df73156c67740ed6..3efff552a261e2745bd0fd05dd873125d6877e19 100644 (file)
@@ -34,6 +34,7 @@ CONFIG_PCIEPORTBUS=y
 CONFIG_PCI_HOST_GENERIC=y
 CONFIG_PCIE_XILINX=y
 CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_SD=y
@@ -53,6 +54,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
 CONFIG_HVC_RISCV_SBI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_SPI=y
+CONFIG_SPI_SIFIVE=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
@@ -66,8 +71,9 @@ CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_UAS=y
+CONFIG_MMC=y
+CONFIG_MMC_SPI=y
 CONFIG_VIRTIO_MMIO=y
-CONFIG_SPI_SIFIVE=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_AUTOFS4_FS=y
@@ -83,8 +89,4 @@ CONFIG_ROOT_NFS=y
 CONFIG_CRYPTO_USER_API_HASH=y
 CONFIG_CRYPTO_DEV_VIRTIO=y
 CONFIG_PRINTK_TIME=y
-CONFIG_SPI=y
-CONFIG_MMC_SPI=y
-CONFIG_MMC=y
-CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_RCU_TRACE is not set
index d5449ef805a340eba735b3ac7a1688cbdcd2b30e..7da93e494445e10bfbc4e1c715d30a5a387011e2 100644 (file)
@@ -34,6 +34,7 @@ CONFIG_PCIEPORTBUS=y
 CONFIG_PCI_HOST_GENERIC=y
 CONFIG_PCIE_XILINX=y
 CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_SD=y
@@ -53,6 +54,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
 CONFIG_HVC_RISCV_SBI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
index 1efaeddf1e4b97abe1de77dc119cd41ac01e343b..16970f246860c3373465bd40669458ad42035505 100644 (file)
@@ -22,6 +22,7 @@ generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
 generic-y += mm-arch-hooks.h
+generic-y += msi.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
index 9c66033c3a545047f155239022ec63b122ade583..161f28d04a07a2c1075076526e673aabb624d6cd 100644 (file)
@@ -30,10 +30,6 @@ enum fixed_addresses {
        __end_of_fixed_addresses
 };
 
-#define FIXADDR_SIZE           (__end_of_fixed_addresses * PAGE_SIZE)
-#define FIXADDR_TOP            (VMALLOC_START)
-#define FIXADDR_START          (FIXADDR_TOP - FIXADDR_SIZE)
-
 #define FIXMAP_PAGE_IO         PAGE_KERNEL
 
 #define __early_set_fixmap     __set_fixmap
index ef28e106f24723271274b4d8a1ac57b36bf13a90..344db5244547c18b53e10e1183084839fb49960b 100644 (file)
@@ -3,7 +3,8 @@
 #ifndef __ASM_IMAGE_H
 #define __ASM_IMAGE_H
 
-#define RISCV_IMAGE_MAGIC      "RISCV"
+#define RISCV_IMAGE_MAGIC      "RISCV\0\0\0"
+#define RISCV_IMAGE_MAGIC2     "RSC\x05"
 
 #define RISCV_IMAGE_FLAG_BE_SHIFT      0
 #define RISCV_IMAGE_FLAG_BE_MASK       0x1
@@ -23,7 +24,7 @@
 #define __HEAD_FLAGS           (__HEAD_FLAG(BE))
 
 #define RISCV_HEADER_VERSION_MAJOR 0
-#define RISCV_HEADER_VERSION_MINOR 1
+#define RISCV_HEADER_VERSION_MINOR 2
 
 #define RISCV_HEADER_VERSION (RISCV_HEADER_VERSION_MAJOR << 16 | \
                              RISCV_HEADER_VERSION_MINOR)
@@ -39,9 +40,8 @@
  * @version:           version
  * @res1:              reserved
  * @res2:              reserved
- * @magic:             Magic number
- * @res3:              reserved (will be used for additional RISC-V specific
- *                     header)
+ * @magic:             Magic number (RISC-V specific; deprecated)
+ * @magic2:            Magic number 2 (to match the ARM64 'magic' field pos)
  * @res4:              reserved (will be used for PE COFF offset)
  *
  * The intention is for this header format to be shared between multiple
@@ -58,7 +58,7 @@ struct riscv_image_header {
        u32 res1;
        u64 res2;
        u64 magic;
-       u32 res3;
+       u32 magic2;
        u32 res4;
 };
 #endif /* __ASSEMBLY__ */
index a364aba23d551164b1066e2c3fefcb7ee1200cb6..c24a083b3e12d2e19bea16b1b5f6e240d788beff 100644 (file)
@@ -420,14 +420,22 @@ static inline void pgtable_cache_init(void)
 #define VMALLOC_END      (PAGE_OFFSET - 1)
 #define VMALLOC_START    (PAGE_OFFSET - VMALLOC_SIZE)
 
+#define FIXADDR_TOP      VMALLOC_START
+#ifdef CONFIG_64BIT
+#define FIXADDR_SIZE     PMD_SIZE
+#else
+#define FIXADDR_SIZE     PGDIR_SIZE
+#endif
+#define FIXADDR_START    (FIXADDR_TOP - FIXADDR_SIZE)
+
 /*
- * Task size is 0x4000000000 for RV64 or 0xb800000 for RV32.
+ * Task size is 0x4000000000 for RV64 or 0x9fc00000 for RV32.
  * Note that PGDIR_SIZE must evenly divide TASK_SIZE.
  */
 #ifdef CONFIG_64BIT
 #define TASK_SIZE (PGDIR_SIZE * PTRS_PER_PGD / 2)
 #else
-#define TASK_SIZE VMALLOC_START
+#define TASK_SIZE FIXADDR_START
 #endif
 
 #include <asm-generic/pgtable.h>
index 853b65ef656da42d52b5c3c46f9ac8f75ce8774d..f0227bdce0f0614925ae772dc80588b8828f2ec0 100644 (file)
@@ -16,7 +16,13 @@ extern void __fstate_restore(struct task_struct *restore_from);
 
 static inline void __fstate_clean(struct pt_regs *regs)
 {
-       regs->sstatus |= (regs->sstatus & ~(SR_FS)) | SR_FS_CLEAN;
+       regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_CLEAN;
+}
+
+static inline void fstate_off(struct task_struct *task,
+                             struct pt_regs *regs)
+{
+       regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_OFF;
 }
 
 static inline void fstate_save(struct task_struct *task,
index 687dd19735a7e6483afb98a319376706ed426cef..4d9bbe8438bf6a7cff301cfd2c6fec0d268a607c 100644 (file)
@@ -53,10 +53,17 @@ static inline void remote_sfence_vma(struct cpumask *cmask, unsigned long start,
 }
 
 #define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1)
-#define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0)
+
 #define flush_tlb_range(vma, start, end) \
        remote_sfence_vma(mm_cpumask((vma)->vm_mm), start, (end) - (start))
-#define flush_tlb_mm(mm) \
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+                                 unsigned long addr)
+{
+       flush_tlb_range(vma, addr, addr + PAGE_SIZE);
+}
+
+#define flush_tlb_mm(mm)                               \
        remote_sfence_vma(mm_cpumask(mm), 0, -1)
 
 #endif /* CONFIG_SMP */
index 62716653554b8fc7efc99d705fb16b5b14fbd013..d86cb17bbabe628dee4ac2759493838f4e2a0c44 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Copyright (C) 2012 ARM Ltd.
  * Copyright (C) 2015 Regents of the University of California
index 0b9b58b57ff6ea061483375184d0950f34835ae8..7d0b32e3b7017696866b4a0c12d94bd8e0d3b44d 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Copyright (C) 2012 ARM Ltd.
  * Copyright (C) 2015 Regents of the University of California
index 1920debc09c08c51ee6ebf6f49a81cb33c9228d3..f671e16bf6af5ed034b5e3f466fa16bb7a3d3c43 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Copyright (C) 2012 ARM Ltd.
  * Copyright (C) 2015 Regents of the University of California
index 7d786145183b006dbd043fc60317d1c95393fccd..4e76460770562ce8e84efb62c1b89d3471d61e70 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Copied from arch/arm64/include/asm/hwcap.h
  *
index 92d8f7cd8f848ea148a0276f3b209c43b5cade89..882547f6bd5c91d34c376ae81fe38f5634e8380a 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Copyright (C) 2012 Regents of the University of California
  */
index 053f809e52ce5540aa2c46e2710b9180521aa138..84f2dfcfdbce2ee92ba6250822bb2397cbce2768 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Copyright (C) 2012 Regents of the University of California
  */
index b58e00cee2ec5ec70a839b96c0ea52dbe9a0aa92..411dd7b52ed688cd3d4b3c4c7b697c162f8327be 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Copyright (C) 2012 ARM Ltd.
  * Copyright (C) 2017 SiFive, Inc.
index 0e2eeeb1fd27bdca3b4b8e3ca88e2bcd3bdc6fa0..13ce76cc5affef4bff61840c97921a1c63c2dab3 100644 (file)
@@ -18,6 +18,7 @@
 #ifdef __LP64__
 #define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SET_GET_RLIMIT
+#define __ARCH_WANT_SYS_CLONE3
 #endif /* __LP64__ */
 
 #include <asm-generic/unistd.h>
index 0f1ba17e476fdd08749446b0891258e7f630735b..52eec0c1bf30c11079d285f7defdf000b6583f22 100644 (file)
@@ -39,9 +39,9 @@ ENTRY(_start)
        .word RISCV_HEADER_VERSION
        .word 0
        .dword 0
-       .asciz RISCV_IMAGE_MAGIC
-       .word 0
+       .ascii RISCV_IMAGE_MAGIC
        .balign 4
+       .ascii RISCV_IMAGE_MAGIC2
        .word 0
 
 .global _start_kernel
index f23794bd1e90c2f1dad70d1d9ed18507c2b58cd1..fb3a082362eb87554ff297f3e026d9663c5a8044 100644 (file)
@@ -64,8 +64,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
        unsigned long sp)
 {
        regs->sstatus = SR_SPIE;
-       if (has_fpu)
+       if (has_fpu) {
                regs->sstatus |= SR_FS_INITIAL;
+               /*
+                * Restore the initial value to the FP register
+                * before starting the user program.
+                */
+               fstate_restore(current, regs);
+       }
        regs->sepc = pc;
        regs->sp = sp;
        set_fs(USER_DS);
@@ -75,10 +81,11 @@ void flush_thread(void)
 {
 #ifdef CONFIG_FPU
        /*
-        * Reset FPU context
+        * Reset FPU state and context
         *      frm: round to nearest, ties to even (IEEE default)
         *      fflags: accrued exceptions cleared
         */
+       fstate_off(current, task_pt_regs(current));
        memset(&current->thread.fstate, 0, sizeof(current->thread.fstate));
 #endif
 }
index f1d6ffe43e42879e66f75ced65b5b5809feba23f..49a5852fd07dd5a023c1899e80bffe542f6dedeb 100644 (file)
@@ -37,7 +37,7 @@ $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE
 # these symbols in the kernel code rather than hand-coded addresses.
 
 SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
-       -Wl,--hash-style=both
+       -Wl,--build-id -Wl,--hash-style=both
 $(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE
        $(call if_changed,vdsold)
 
index 8e364ebf37dedf325f5a415d866bfdf30b08bb25..267feaa10f6ad2f3ad5a7b8bdf82a86ac434c7aa 100644 (file)
@@ -5,5 +5,3 @@ lib-y   += memset.o
 lib-y  += uaccess.o
 
 lib-$(CONFIG_64BIT) += tishift.o
-
-lib-$(CONFIG_32BIT) += udivdi3.o
index 87ff89e88f2ca95bfc1fb47e10e0cb7e88b0880a..f51c9a03bca1e7ca4c71faecba4c2e4b5f9e0d65 100644 (file)
@@ -81,9 +81,13 @@ EXPORT_SYMBOL(__delay);
 void udelay(unsigned long usecs)
 {
        u64 ucycles = (u64)usecs * lpj_fine * UDELAY_MULT;
+       u64 n;
 
        if (unlikely(usecs > MAX_UDELAY_US)) {
-               __delay((u64)usecs * riscv_timebase / 1000000ULL);
+               n = (u64)usecs * riscv_timebase;
+               do_div(n, 1000000);
+
+               __delay(n);
                return;
        }
 
diff --git a/arch/riscv/lib/udivdi3.S b/arch/riscv/lib/udivdi3.S
deleted file mode 100644 (file)
index 3f07476..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2016-2017 Free Software Foundation, Inc.
- */
-
-#include <linux/linkage.h>
-
-ENTRY(__udivdi3)
-       mv      a2, a1
-       mv      a1, a0
-       li      a0, -1
-       beqz    a2, .L5
-       li      a3, 1
-       bgeu    a2, a1, .L2
-.L1:
-       blez    a2, .L2
-       slli    a2, a2, 1
-       slli    a3, a3, 1
-       bgtu    a1, a2, .L1
-.L2:
-       li      a0, 0
-.L3:
-       bltu    a1, a2, .L4
-       sub     a1, a1, a2
-       or      a0, a0, a3
-.L4:
-       srli    a3, a3, 1
-       srli    a2, a2, 1
-       bnez    a3, .L3
-.L5:
-       ret
-ENDPROC(__udivdi3)
index 7cba96e7587bca0d3d523483884a6c5f5ee48071..4cf0bddb7d92e1496ea16c690871274fc8c6ed47 100644 (file)
@@ -36,7 +36,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
 
 obj-y  := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o
 obj-y  += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
-obj-y  += ctype.o text_dma.o
+obj-y  += version.o ctype.o text_dma.o
 obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST)   += uv.o
 obj-$(CONFIG_RELOCATABLE)      += machine_kexec_reloc.o
 obj-$(CONFIG_RANDOMIZE_BASE)   += kaslr.o
index ad57c2205a71bd9d7a1d854c2e4ff37885fa8f63..1c3b2b25763721899d06b06484104cc47dffee83 100644 (file)
@@ -8,10 +8,12 @@ void store_ipl_parmblock(void);
 void setup_boot_command_line(void);
 void parse_boot_command_line(void);
 void setup_memory_end(void);
+void verify_facilities(void);
 void print_missing_facilities(void);
 unsigned long get_random_base(unsigned long safe_addr);
 
 extern int kaslr_enabled;
+extern const char kernel_version[];
 
 unsigned long read_ipl_report(unsigned long safe_offset);
 
index 028aab03a9e7782ceb5b9b5104091399c39d6e10..2087bed6e60f3e8fd72db7a93b2d78e53c068a55 100644 (file)
@@ -361,6 +361,7 @@ ENTRY(startup_kdump)
        .quad   0                       # INITRD_SIZE
        .quad   0                       # OLDMEM_BASE
        .quad   0                       # OLDMEM_SIZE
+       .quad   kernel_version          # points to kernel version string
 
        .org    COMMAND_LINE
        .byte   "root=/dev/ram0 ro"
index 3c49bde8aa5e3d6f82d3e1c2157b35421e9cd7e4..b8aa6a9f937b2e27839f27ab598adab074e706a3 100644 (file)
@@ -48,9 +48,7 @@ void store_ipl_parmblock(void)
 {
        int rc;
 
-       uv_set_shared(__pa(&ipl_block));
        rc = __diag308(DIAG308_STORE, &ipl_block);
-       uv_remove_shared(__pa(&ipl_block));
        if (rc == DIAG308_RC_OK &&
            ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
                ipl_block_valid = 1;
index 3bdd8132e56bcb1230638e3480c49a2023863018..c34a6387ce384be2a72810d3cd77fa8786ec41ef 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/timex.h>
 #include <asm/sclp.h>
 #include "compressed/decompressor.h"
+#include "boot.h"
 
 #define PRNG_MODE_TDES  1
 #define PRNG_MODE_SHA512 2
diff --git a/arch/s390/boot/version.c b/arch/s390/boot/version.c
new file mode 100644 (file)
index 0000000..d32e58b
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <generated/utsrelease.h>
+#include <generated/compile.h>
+#include "boot.h"
+
+const char kernel_version[] = UTS_RELEASE
+       " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " UTS_VERSION;
index e26d4413d34c139d603ecc180da09c6583f2d0c7..74e78ec5beb688f30eec648db92d14e655be0675 100644 (file)
@@ -3,6 +3,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_AUDIT=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_TASKSTATS=y
@@ -18,55 +19,71 @@ CONFIG_BLK_CGROUP=y
 CONFIG_CFS_BANDWIDTH=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_HUGETLB=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 # CONFIG_SYSFS_SYSCALL is not set
-CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_USERFAULTFD=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
+CONFIG_LIVEPATCH=y
+CONFIG_TUNE_ZEC12=y
+CONFIG_NR_CPUS=512
+CONFIG_NUMA=y
+CONFIG_HZ_100=y
+CONFIG_KEXEC_FILE=y
+CONFIG_EXPOLINE=y
+CONFIG_EXPOLINE_AUTO=y
+CONFIG_CHSC_SCH=y
+CONFIG_VFIO_CCW=m
+CONFIG_VFIO_AP=m
+CONFIG_CRASH_DUMP=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_DEBUG=y
+CONFIG_CMM=m
+CONFIG_APPLDATA_BASE=y
+CONFIG_KVM=m
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_VSOCK=m
 CONFIG_OPROFILE=m
 CONFIG_KPROBES=y
 CONFIG_JUMP_LABEL=y
 CONFIG_STATIC_KEYS_SELFTEST=y
+CONFIG_REFCOUNT_FULL=y
+CONFIG_LOCK_EVENT_COUNTS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_SHA256=y
 CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_BLK_DEV_THROTTLING=y
 CONFIG_BLK_WBT=y
-CONFIG_BLK_WBT_SQ=y
+CONFIG_BLK_CGROUP_IOLATENCY=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_BSD_DISKLABEL=y
 CONFIG_MINIX_SUBPARTITION=y
 CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_CFQ_GROUP_IOSCHED=y
-CONFIG_DEFAULT_DEADLINE=y
-CONFIG_LIVEPATCH=y
-CONFIG_TUNE_ZEC12=y
-CONFIG_NR_CPUS=512
-CONFIG_NUMA=y
-CONFIG_PREEMPT=y
-CONFIG_HZ_100=y
-CONFIG_KEXEC_FILE=y
-CONFIG_KEXEC_VERIFY_SIG=y
-CONFIG_EXPOLINE=y
-CONFIG_EXPOLINE_AUTO=y
+CONFIG_IOSCHED_BFQ=y
+CONFIG_BFQ_GROUP_IOSCHED=y
+CONFIG_BINFMT_MISC=m
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
@@ -82,17 +99,8 @@ CONFIG_ZSMALLOC=m
 CONFIG_ZSMALLOC_STAT=y
 CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
 CONFIG_IDLE_PAGE_TRACKING=y
-CONFIG_PCI=y
-CONFIG_PCI_DEBUG=y
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_S390=y
-CONFIG_CHSC_SCH=y
-CONFIG_VFIO_AP=m
-CONFIG_VFIO_CCW=m
-CONFIG_CRASH_DUMP=y
-CONFIG_BINFMT_MISC=m
-CONFIG_HIBERNATION=y
-CONFIG_PM_DEBUG=y
+CONFIG_PERCPU_STATS=y
+CONFIG_GUP_BENCHMARK=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=m
@@ -121,9 +129,6 @@ CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
 CONFIG_TCP_CONG_ADVANCED=y
@@ -139,10 +144,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_SIT=m
 CONFIG_IPV6_GRE=m
@@ -264,11 +265,8 @@ CONFIG_IP_VS_SED=m
 CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
-CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NF_TABLES_IPV4=y
-CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NF_TABLES_ARP=y
-CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -287,10 +285,7 @@ CONFIG_IP_NF_SECURITY=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NF_TABLES_IPV6=y
-CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -309,7 +304,7 @@ CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
 CONFIG_IP6_NF_NAT=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_RDS=m
 CONFIG_RDS_RDMA=m
 CONFIG_RDS_TCP=m
@@ -375,9 +370,11 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_CGROUP_NET_PRIO=y
 CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
+CONFIG_PCI=y
+CONFIG_PCI_DEBUG=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_DEVTMPFS=y
-CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_CONNECTOR=y
 CONFIG_ZRAM=m
 CONFIG_BLK_DEV_LOOP=m
@@ -395,7 +392,6 @@ CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=m
@@ -415,17 +411,19 @@ CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_HP_SW=m
 CONFIG_SCSI_DH_EMC=m
 CONFIG_SCSI_DH_ALUA=m
-CONFIG_SCSI_OSD_INITIATOR=m
-CONFIG_SCSI_OSD_ULD=m
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
+CONFIG_MD_CLUSTER=m
+CONFIG_BCACHE=m
 CONFIG_BLK_DEV_DM=m
+CONFIG_DM_UNSTRIPED=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_WRITECACHE=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_LOG_USERSPACE=m
 CONFIG_DM_RAID=m
@@ -445,23 +443,78 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
-CONFIG_VXLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
 CONFIG_VIRTIO_NET=m
 CONFIG_NLMON=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
 # CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
 CONFIG_MLX5_CORE=m
 CONFIG_MLX5_CORE_EN=y
+# CONFIG_MLXFW is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_MYRI is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETERION is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
 CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=m
 CONFIG_PPTP=m
 CONFIG_PPPOL2TP=m
@@ -473,10 +526,13 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_NULL_TTY=m
 CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_RAW_DRIVER=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+CONFIG_PPS=m
+# CONFIG_PTP_1588_CLOCK is not set
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
@@ -498,8 +554,8 @@ CONFIG_VFIO_MDEV_DEVICE=m
 CONFIG_VIRTIO_PCI=m
 CONFIG_VIRTIO_BALLOON=m
 CONFIG_VIRTIO_INPUT=y
-CONFIG_S390_AP_IOMMU=y
 CONFIG_S390_CCW_IOMMU=y
+CONFIG_S390_AP_IOMMU=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
@@ -519,6 +575,7 @@ CONFIG_OCFS2_FS=m
 CONFIG_BTRFS_FS=y
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_BTRFS_DEBUG=y
+CONFIG_BTRFS_ASSERT=y
 CONFIG_NILFS2_FS=m
 CONFIG_FS_DAX=y
 CONFIG_EXPORTFS_BLOCK_OPS=y
@@ -552,8 +609,10 @@ CONFIG_ECRYPT_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
 CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
 CONFIG_SQUASHFS_LZO=y
 CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
 CONFIG_ROMFS_FS=m
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3_ACL=y
@@ -564,7 +623,6 @@ CONFIG_NFSD_V3_ACL=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_V4_SECURITY_LABEL=y
 CONFIG_CIFS=m
-CONFIG_CIFS_STATS=y
 CONFIG_CIFS_STATS2=y
 CONFIG_CIFS_WEAK_PW_HASH=y
 CONFIG_CIFS_UPCALL=y
@@ -580,19 +638,112 @@ CONFIG_NLS_ISO8859_1=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=m
 CONFIG_DLM=m
+CONFIG_UNICODE=y
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_BIG_KEYS=y
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_IMA=y
+CONFIG_IMA_DEFAULT_HASH_SHA256=y
+CONFIG_IMA_WRITE_POLICY=y
+CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_USER=m
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
+CONFIG_CRYPTO_ECRDSA=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_AEGIS128L=m
+CONFIG_CRYPTO_AEGIS256=m
+CONFIG_CRYPTO_MORUS640=m
+CONFIG_CRYPTO_MORUS1280=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_XXHASH=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES_TI=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_SM4=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_842=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ZSTD=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
+CONFIG_CRYPTO_STATS=y
+CONFIG_ZCRYPT=m
+CONFIG_PKEY=m
+CONFIG_CRYPTO_PAES_S390=m
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256_S390=m
+CONFIG_CRYPTO_SHA512_S390=m
+CONFIG_CRYPTO_DES_S390=m
+CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_GHASH_S390=m
+CONFIG_CRYPTO_CRC32_S390=y
+CONFIG_CORDIC=m
+CONFIG_CRC32_SELFTEST=y
+CONFIG_CRC4=m
+CONFIG_CRC7=m
+CONFIG_CRC8=m
+CONFIG_RANDOM32_SELFTEST=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=0
+CONFIG_DMA_API_DEBUG=y
+CONFIG_STRING_SELFTEST=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_INFO_DWARF4=y
 CONFIG_GDB_SCRIPTS=y
 CONFIG_FRAME_WARN=1024
-CONFIG_READABLE_ASM=y
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_HEADERS_INSTALL=y
 CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_PAGE_OWNER=y
 CONFIG_DEBUG_RODATA_TEST=y
 CONFIG_DEBUG_OBJECTS=y
 CONFIG_DEBUG_OBJECTS_SELFTEST=y
@@ -645,7 +796,6 @@ CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_FUNCTION_PROFILER=y
 CONFIG_HIST_TRIGGERS=y
-CONFIG_DMA_API_DEBUG=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
 CONFIG_TEST_SORT=y
@@ -657,85 +807,3 @@ CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
 CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_S390_PTDUMP=y
-CONFIG_PERSISTENT_KEYRINGS=y
-CONFIG_BIG_KEYS=y
-CONFIG_ENCRYPTED_KEYS=m
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_FORTIFY_SOURCE=y
-CONFIG_SECURITY_SELINUX=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
-CONFIG_SECURITY_SELINUX_DISABLE=y
-CONFIG_INTEGRITY_SIGNATURE=y
-CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
-CONFIG_IMA=y
-CONFIG_IMA_DEFAULT_HASH_SHA256=y
-CONFIG_IMA_WRITE_POLICY=y
-CONFIG_IMA_APPRAISE=y
-CONFIG_CRYPTO_DH=m
-CONFIG_CRYPTO_ECDH=m
-CONFIG_CRYPTO_USER=m
-# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
-CONFIG_CRYPTO_PCRYPT=m
-CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_AES_TI=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAMELLIA=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
-CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_842=m
-CONFIG_CRYPTO_LZ4=m
-CONFIG_CRYPTO_LZ4HC=m
-CONFIG_CRYPTO_ANSI_CPRNG=m
-CONFIG_CRYPTO_USER_API_HASH=m
-CONFIG_CRYPTO_USER_API_SKCIPHER=m
-CONFIG_CRYPTO_USER_API_RNG=m
-CONFIG_CRYPTO_USER_API_AEAD=m
-CONFIG_ZCRYPT=m
-CONFIG_PKEY=m
-CONFIG_CRYPTO_PAES_S390=m
-CONFIG_CRYPTO_SHA1_S390=m
-CONFIG_CRYPTO_SHA256_S390=m
-CONFIG_CRYPTO_SHA512_S390=m
-CONFIG_CRYPTO_DES_S390=m
-CONFIG_CRYPTO_AES_S390=m
-CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_CRYPTO_CRC32_S390=y
-CONFIG_PKCS7_MESSAGE_PARSER=y
-CONFIG_SYSTEM_TRUSTED_KEYRING=y
-CONFIG_CRC7=m
-CONFIG_CRC8=m
-CONFIG_RANDOM32_SELFTEST=y
-CONFIG_CORDIC=m
-CONFIG_CMM=m
-CONFIG_APPLDATA_BASE=y
-CONFIG_KVM=m
-CONFIG_KVM_S390_UCONTROL=y
-CONFIG_VHOST_NET=m
-CONFIG_VHOST_VSOCK=m
index e4bc40073003f96200f716946f40dd4f23337be7..68d3ca83302b1c2ae61727a974a0188aba1dfe4b 100644 (file)
@@ -12,30 +12,51 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
-# CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
 CONFIG_BLK_CGROUP=y
 CONFIG_CFS_BANDWIDTH=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_HUGETLB=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 # CONFIG_SYSFS_SYSCALL is not set
-CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_USERFAULTFD=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
+CONFIG_LIVEPATCH=y
+CONFIG_TUNE_ZEC12=y
+CONFIG_NR_CPUS=512
+CONFIG_NUMA=y
+# CONFIG_NUMA_EMU is not set
+CONFIG_HZ_100=y
+CONFIG_KEXEC_FILE=y
+CONFIG_EXPOLINE=y
+CONFIG_EXPOLINE_AUTO=y
+CONFIG_CHSC_SCH=y
+CONFIG_VFIO_CCW=m
+CONFIG_VFIO_AP=m
+CONFIG_CRASH_DUMP=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_DEBUG=y
+CONFIG_CMM=m
+CONFIG_APPLDATA_BASE=y
+CONFIG_KVM=m
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_VSOCK=m
 CONFIG_OPROFILE=m
 CONFIG_KPROBES=y
 CONFIG_JUMP_LABEL=y
@@ -47,27 +68,18 @@ CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_MODULE_SIG=y
 CONFIG_MODULE_SIG_SHA256=y
-CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_BLK_DEV_THROTTLING=y
 CONFIG_BLK_WBT=y
-CONFIG_BLK_WBT_SQ=y
+CONFIG_BLK_CGROUP_IOLATENCY=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_BSD_DISKLABEL=y
 CONFIG_MINIX_SUBPARTITION=y
 CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_CFQ_GROUP_IOSCHED=y
-CONFIG_DEFAULT_DEADLINE=y
-CONFIG_LIVEPATCH=y
-CONFIG_TUNE_ZEC12=y
-CONFIG_NR_CPUS=512
-CONFIG_NUMA=y
-CONFIG_HZ_100=y
-CONFIG_KEXEC_FILE=y
-CONFIG_KEXEC_VERIFY_SIG=y
-CONFIG_EXPOLINE=y
-CONFIG_EXPOLINE_AUTO=y
+CONFIG_IOSCHED_BFQ=y
+CONFIG_BFQ_GROUP_IOSCHED=y
+CONFIG_BINFMT_MISC=m
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
@@ -81,16 +93,8 @@ CONFIG_ZSMALLOC=m
 CONFIG_ZSMALLOC_STAT=y
 CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
 CONFIG_IDLE_PAGE_TRACKING=y
-CONFIG_PCI=y
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_S390=y
-CONFIG_CHSC_SCH=y
-CONFIG_VFIO_AP=m
-CONFIG_VFIO_CCW=m
-CONFIG_CRASH_DUMP=y
-CONFIG_BINFMT_MISC=m
-CONFIG_HIBERNATION=y
-CONFIG_PM_DEBUG=y
+CONFIG_PERCPU_STATS=y
+CONFIG_GUP_BENCHMARK=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=m
@@ -119,9 +123,6 @@ CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
 CONFIG_TCP_CONG_ADVANCED=y
@@ -137,10 +138,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_SIT=m
 CONFIG_IPV6_GRE=m
@@ -262,11 +259,8 @@ CONFIG_IP_VS_SED=m
 CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
-CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NF_TABLES_IPV4=y
-CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NF_TABLES_ARP=y
-CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -285,10 +279,7 @@ CONFIG_IP_NF_SECURITY=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NF_TABLES_IPV6=y
-CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -307,7 +298,7 @@ CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
 CONFIG_IP6_NF_NAT=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_NF_TABLES_BRIDGE=y
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_RDS=m
 CONFIG_RDS_RDMA=m
 CONFIG_RDS_TCP=m
@@ -372,9 +363,11 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_CGROUP_NET_PRIO=y
 CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
+CONFIG_PCI=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_S390=y
+CONFIG_UEVENT_HELPER=y
 CONFIG_DEVTMPFS=y
-CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_CONNECTOR=y
 CONFIG_ZRAM=m
 CONFIG_BLK_DEV_LOOP=m
@@ -383,6 +376,7 @@ CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XPRAM is not set
 CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_RBD=m
 CONFIG_BLK_DEV_NVME=m
@@ -392,7 +386,6 @@ CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=m
@@ -412,17 +405,19 @@ CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_HP_SW=m
 CONFIG_SCSI_DH_EMC=m
 CONFIG_SCSI_DH_ALUA=m
-CONFIG_SCSI_OSD_INITIATOR=m
-CONFIG_SCSI_OSD_ULD=m
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
+CONFIG_MD_CLUSTER=m
+CONFIG_BCACHE=m
 CONFIG_BLK_DEV_DM=m
+CONFIG_DM_UNSTRIPED=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_WRITECACHE=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_LOG_USERSPACE=m
 CONFIG_DM_RAID=m
@@ -435,6 +430,7 @@ CONFIG_DM_UEVENT=y
 CONFIG_DM_FLAKEY=m
 CONFIG_DM_VERITY=m
 CONFIG_DM_SWITCH=m
+CONFIG_DM_INTEGRITY=m
 CONFIG_NETDEVICES=y
 CONFIG_BONDING=m
 CONFIG_DUMMY=m
@@ -442,23 +438,78 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
-CONFIG_VXLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
 CONFIG_VIRTIO_NET=m
 CONFIG_NLMON=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
 # CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
 CONFIG_MLX5_CORE=m
 CONFIG_MLX5_CORE_EN=y
+# CONFIG_MLXFW is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_MYRI is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETERION is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
 CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=m
 CONFIG_PPTP=m
 CONFIG_PPPOL2TP=m
@@ -470,17 +521,21 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_NULL_TTY=m
 CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_RAW_DRIVER=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_PTP_1588_CLOCK is not set
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
 CONFIG_DIAG288_WATCHDOG=m
 CONFIG_DRM=y
 CONFIG_DRM_VIRTIO_GPU=y
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
@@ -495,8 +550,8 @@ CONFIG_VFIO_MDEV_DEVICE=m
 CONFIG_VIRTIO_PCI=m
 CONFIG_VIRTIO_BALLOON=m
 CONFIG_VIRTIO_INPUT=y
-CONFIG_S390_AP_IOMMU=y
 CONFIG_S390_CCW_IOMMU=y
+CONFIG_S390_AP_IOMMU=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
@@ -546,8 +601,10 @@ CONFIG_ECRYPT_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
 CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
 CONFIG_SQUASHFS_LZO=y
 CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
 CONFIG_ROMFS_FS=m
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3_ACL=y
@@ -558,7 +615,6 @@ CONFIG_NFSD_V3_ACL=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_V4_SECURITY_LABEL=y
 CONFIG_CIFS=m
-CONFIG_CIFS_STATS=y
 CONFIG_CIFS_STATS2=y
 CONFIG_CIFS_WEAK_PW_HASH=y
 CONFIG_CIFS_UPCALL=y
@@ -574,31 +630,7 @@ CONFIG_NLS_ISO8859_1=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=m
 CONFIG_DLM=m
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_INFO_DWARF4=y
-CONFIG_GDB_SCRIPTS=y
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_FRAME_WARN=1024
-CONFIG_UNUSED_SYMBOLS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_PANIC_ON_OOPS=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_RCU_CPU_STALL_TIMEOUT=60
-CONFIG_LATENCYTOP=y
-CONFIG_SCHED_TRACER=y
-CONFIG_FTRACE_SYSCALLS=y
-CONFIG_STACK_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_FUNCTION_PROFILER=y
-CONFIG_HIST_TRIGGERS=y
-CONFIG_LKDTM=m
-CONFIG_PERCPU_TEST=m
-CONFIG_ATOMIC64_SELFTEST=y
-CONFIG_TEST_BPF=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_S390_PTDUMP=y
+CONFIG_UNICODE=y
 CONFIG_PERSISTENT_KEYRINGS=y
 CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
@@ -606,7 +638,6 @@ CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
 CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_INTEGRITY_SIGNATURE=y
 CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
@@ -615,31 +646,42 @@ CONFIG_IMA_DEFAULT_HASH_SHA256=y
 CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
 CONFIG_CRYPTO_FIPS=y
-CONFIG_CRYPTO_DH=m
-CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
 CONFIG_CRYPTO_PCRYPT=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
+CONFIG_CRYPTO_ECRDSA=m
 CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_AEGIS128L=m
+CONFIG_CRYPTO_AEGIS256=m
+CONFIG_CRYPTO_MORUS640=m
+CONFIG_CRYPTO_MORUS1280=m
+CONFIG_CRYPTO_CFB=m
 CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_XXHASH=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_AES_TI=m
 CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_CAST5=m
@@ -649,16 +691,19 @@ CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_SM4=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ZSTD=m
 CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_CRYPTO_USER_API_AEAD=m
+CONFIG_CRYPTO_STATS=y
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
@@ -669,12 +714,34 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
+CONFIG_CORDIC=m
+CONFIG_CRC4=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
-CONFIG_CORDIC=m
-CONFIG_CMM=m
-CONFIG_APPLDATA_BASE=y
-CONFIG_KVM=m
-CONFIG_KVM_S390_UCONTROL=y
-CONFIG_VHOST_NET=m
-CONFIG_VHOST_VSOCK=m
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=0
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
+CONFIG_FRAME_WARN=1024
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_LATENCYTOP=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_STACK_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_HIST_TRIGGERS=y
+CONFIG_LKDTM=m
+CONFIG_PERCPU_TEST=m
+CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_TEST_BPF=m
+CONFIG_BUG_ON_DATA_CORRUPTION=y
+CONFIG_S390_PTDUMP=y
index d92bab844b7352a0b200c67c798bfd4cad6a06cb..be09a208b608437af55f2c3f76d4b444b73ac431 100644 (file)
@@ -1,27 +1,33 @@
 # CONFIG_SWAP is not set
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_CPU_ISOLATION is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_COMPAT_BRK is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_IBM_PARTITION=y
-CONFIG_DEFAULT_DEADLINE=y
 CONFIG_TUNE_ZEC12=y
 # CONFIG_COMPAT is not set
 CONFIG_NR_CPUS=2
-# CONFIG_HOTPLUG_CPU is not set
 CONFIG_HZ_100=y
 # CONFIG_ARCH_RANDOM is not set
-# CONFIG_COMPACTION is not set
-# CONFIG_MIGRATION is not set
-# CONFIG_BOUNCE is not set
-# CONFIG_CHECK_STACK is not set
+# CONFIG_RELOCATABLE is not set
 # CONFIG_CHSC_SCH is not set
 # CONFIG_SCM_BUS is not set
 CONFIG_CRASH_DUMP=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SECCOMP is not set
+# CONFIG_PFAULT is not set
+# CONFIG_S390_HYPFS_FS is not set
+# CONFIG_VIRTUALIZATION is not set
+# CONFIG_S390_GUEST is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IBM_PARTITION=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_COMPACTION is not set
+# CONFIG_MIGRATION is not set
+# CONFIG_BOUNCE is not set
 CONFIG_NET=y
 # CONFIG_IUCV is not set
 CONFIG_DEVTMPFS=y
@@ -43,7 +49,6 @@ CONFIG_ZFCP=y
 # CONFIG_HVC_IUCV is not set
 # CONFIG_HW_RANDOM_S390 is not set
 CONFIG_RAW_DRIVER=y
-# CONFIG_SCLP_ASYNC is not set
 # CONFIG_HMC_DRV is not set
 # CONFIG_S390_TAPE is not set
 # CONFIG_VMCP is not set
@@ -56,6 +61,7 @@ CONFIG_RAW_DRIVER=y
 CONFIG_CONFIGFS_FS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_DIMLIB is not set
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
@@ -64,7 +70,4 @@ CONFIG_PANIC_ON_OOPS=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 # CONFIG_FTRACE is not set
-# CONFIG_PFAULT is not set
-# CONFIG_S390_HYPFS_FS is not set
-# CONFIG_VIRTUALIZATION is not set
-# CONFIG_S390_GUEST is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
index 42f2375c203edc9a44016d6f42dee30c8b232ad9..e1fcc03159ef25c42e90fa55e072f9914602ee5c 100644 (file)
@@ -118,7 +118,7 @@ do { \
                return PTR_ERR(rc); \
 } while(0)
 
-static int hpyfs_vm_create_guest(struct dentry *systems_dir,
+static int hypfs_vm_create_guest(struct dentry *systems_dir,
                                 struct diag2fc_data *data)
 {
        char guest_name[NAME_LEN + 1] = {};
@@ -219,7 +219,7 @@ int hypfs_vm_create_files(struct dentry *root)
        }
 
        for (i = 0; i < count; i++) {
-               rc = hpyfs_vm_create_guest(dir, &(data[i]));
+               rc = hypfs_vm_create_guest(dir, &(data[i]));
                if (rc)
                        goto failed;
        }
index 9900d655014cc309559450316a436d67f90c3717..b8833ac983fac2e94d699069c2394dd3261133d6 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <linux/typecheck.h>
 #include <linux/compiler.h>
+#include <linux/types.h>
 #include <asm/atomic_ops.h>
 #include <asm/barrier.h>
 
@@ -55,7 +56,7 @@ __bitops_byte(unsigned long nr, volatile unsigned long *ptr)
        return ((unsigned char *)ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
 }
 
-static inline void set_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch_set_bit(unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned long *addr = __bitops_word(nr, ptr);
        unsigned long mask;
@@ -76,7 +77,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *ptr)
        __atomic64_or(mask, (long *)addr);
 }
 
-static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch_clear_bit(unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned long *addr = __bitops_word(nr, ptr);
        unsigned long mask;
@@ -97,7 +98,8 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)
        __atomic64_and(mask, (long *)addr);
 }
 
-static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch_change_bit(unsigned long nr,
+                                  volatile unsigned long *ptr)
 {
        unsigned long *addr = __bitops_word(nr, ptr);
        unsigned long mask;
@@ -118,8 +120,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)
        __atomic64_xor(mask, (long *)addr);
 }
 
-static inline int
-test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch_test_and_set_bit(unsigned long nr,
+                                        volatile unsigned long *ptr)
 {
        unsigned long *addr = __bitops_word(nr, ptr);
        unsigned long old, mask;
@@ -129,8 +131,8 @@ test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
        return (old & mask) != 0;
 }
 
-static inline int
-test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch_test_and_clear_bit(unsigned long nr,
+                                          volatile unsigned long *ptr)
 {
        unsigned long *addr = __bitops_word(nr, ptr);
        unsigned long old, mask;
@@ -140,8 +142,8 @@ test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
        return (old & ~mask) != 0;
 }
 
-static inline int
-test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch_test_and_change_bit(unsigned long nr,
+                                           volatile unsigned long *ptr)
 {
        unsigned long *addr = __bitops_word(nr, ptr);
        unsigned long old, mask;
@@ -151,30 +153,31 @@ test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
        return (old & mask) != 0;
 }
 
-static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch___set_bit(unsigned long nr, volatile unsigned long *ptr)
 {
        unsigned char *addr = __bitops_byte(nr, ptr);
 
        *addr |= 1 << (nr & 7);
 }
 
-static inline void 
-__clear_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch___clear_bit(unsigned long nr,
+                                   volatile unsigned long *ptr)
 {
        unsigned char *addr = __bitops_byte(nr, ptr);
 
        *addr &= ~(1 << (nr & 7));
 }
 
-static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline void arch___change_bit(unsigned long nr,
+                                    volatile unsigned long *ptr)
 {
        unsigned char *addr = __bitops_byte(nr, ptr);
 
        *addr ^= 1 << (nr & 7);
 }
 
-static inline int
-__test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch___test_and_set_bit(unsigned long nr,
+                                          volatile unsigned long *ptr)
 {
        unsigned char *addr = __bitops_byte(nr, ptr);
        unsigned char ch;
@@ -184,8 +187,8 @@ __test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
        return (ch >> (nr & 7)) & 1;
 }
 
-static inline int
-__test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch___test_and_clear_bit(unsigned long nr,
+                                            volatile unsigned long *ptr)
 {
        unsigned char *addr = __bitops_byte(nr, ptr);
        unsigned char ch;
@@ -195,8 +198,8 @@ __test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
        return (ch >> (nr & 7)) & 1;
 }
 
-static inline int
-__test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
+static inline bool arch___test_and_change_bit(unsigned long nr,
+                                             volatile unsigned long *ptr)
 {
        unsigned char *addr = __bitops_byte(nr, ptr);
        unsigned char ch;
@@ -206,7 +209,8 @@ __test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
        return (ch >> (nr & 7)) & 1;
 }
 
-static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)
+static inline bool arch_test_bit(unsigned long nr,
+                                const volatile unsigned long *ptr)
 {
        const volatile unsigned char *addr;
 
@@ -215,28 +219,30 @@ static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)
        return (*addr >> (nr & 7)) & 1;
 }
 
-static inline int test_and_set_bit_lock(unsigned long nr,
-                                       volatile unsigned long *ptr)
+static inline bool arch_test_and_set_bit_lock(unsigned long nr,
+                                             volatile unsigned long *ptr)
 {
-       if (test_bit(nr, ptr))
+       if (arch_test_bit(nr, ptr))
                return 1;
-       return test_and_set_bit(nr, ptr);
+       return arch_test_and_set_bit(nr, ptr);
 }
 
-static inline void clear_bit_unlock(unsigned long nr,
-                                   volatile unsigned long *ptr)
+static inline void arch_clear_bit_unlock(unsigned long nr,
+                                        volatile unsigned long *ptr)
 {
        smp_mb__before_atomic();
-       clear_bit(nr, ptr);
+       arch_clear_bit(nr, ptr);
 }
 
-static inline void __clear_bit_unlock(unsigned long nr,
-                                     volatile unsigned long *ptr)
+static inline void arch___clear_bit_unlock(unsigned long nr,
+                                          volatile unsigned long *ptr)
 {
        smp_mb();
-       __clear_bit(nr, ptr);
+       arch___clear_bit(nr, ptr);
 }
 
+#include <asm-generic/bitops-instrumented.h>
+
 /*
  * Functions which use MSB0 bit numbering.
  * The bits are numbered:
@@ -261,7 +267,8 @@ static inline void clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
        return clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
 }
 
-static inline int test_and_clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
+static inline bool test_and_clear_bit_inv(unsigned long nr,
+                                         volatile unsigned long *ptr)
 {
        return test_and_clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
 }
@@ -276,8 +283,8 @@ static inline void __clear_bit_inv(unsigned long nr, volatile unsigned long *ptr
        return __clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
 }
 
-static inline int test_bit_inv(unsigned long nr,
-                              const volatile unsigned long *ptr)
+static inline bool test_bit_inv(unsigned long nr,
+                               const volatile unsigned long *ptr)
 {
        return test_bit(nr ^ (BITS_PER_LONG - 1), ptr);
 }
index a4d38092530abacb2295a3fe08589a8a3b1f7844..823578c6b9e2c15b2081a69647cc0c488b12c297 100644 (file)
@@ -177,6 +177,8 @@ static inline int devmem_is_allowed(unsigned long pfn)
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | \
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#define ARCH_ZONE_DMA_BITS     31
+
 #include <asm-generic/memory_model.h>
 #include <asm-generic/getorder.h>
 
index db5ef22c46e4e959eba66e203495f10c45740c7a..f647d565bd6dc1374151f65ab2f76f84d7322e16 100644 (file)
@@ -28,7 +28,7 @@
  * @sliba: storage list information block address
  * @sla: storage list address
  * @slsba: storage list state block address
- * @akey: access key for DLIB
+ * @akey: access key for SLIB
  * @bkey: access key for SL
  * @ckey: access key for SBALs
  * @dkey: access key for SLSB
@@ -50,11 +50,10 @@ struct qdesfmt0 {
 /**
  * struct qdr - queue description record (QDR)
  * @qfmt: queue format
- * @pfmt: implementation dependent parameter format
  * @ac: adapter characteristics
  * @iqdcnt: input queue descriptor count
  * @oqdcnt: output queue descriptor count
- * @iqdsz: inpout queue descriptor size
+ * @iqdsz: input queue descriptor size
  * @oqdsz: output queue descriptor size
  * @qiba: queue information block address
  * @qkey: queue information block key
@@ -62,8 +61,7 @@ struct qdesfmt0 {
  */
 struct qdr {
        u32 qfmt   : 8;
-       u32 pfmt   : 8;
-       u32        : 8;
+       u32        : 16;
        u32 ac     : 8;
        u32        : 8;
        u32 iqdcnt : 8;
@@ -327,6 +325,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
  * struct qdio_initialize - qdio initialization data
  * @cdev: associated ccw device
  * @q_format: queue format
+ * @qdr_ac: feature flags to set
  * @adapter_name: name for the adapter
  * @qib_param_field_format: format for qib_parm_field
  * @qib_param_field: pointer to 128 bytes or NULL, if no param field
@@ -338,6 +337,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
  * @input_handler: handler to be called for input queues
  * @output_handler: handler to be called for output queues
  * @queue_start_poll_array: polling handlers (one per input queue or NULL)
+ * @scan_threshold: # of in-use buffers that triggers scan on output queue
  * @int_parm: interruption parameter
  * @input_sbal_addr_array:  address of no_input_qs * 128 pointers
  * @output_sbal_addr_array: address of no_output_qs * 128 pointers
index 82deb8fc831969bf7b5ccc17fe7bdaa9df5a4c15..70bd65724ec4c06310380465c39709f6d3b73ff5 100644 (file)
@@ -54,6 +54,7 @@
 #define INITRD_SIZE_OFFSET     0x10410
 #define OLDMEM_BASE_OFFSET     0x10418
 #define OLDMEM_SIZE_OFFSET     0x10420
+#define KERNEL_VERSION_OFFSET  0x10428
 #define COMMAND_LINE_OFFSET    0x10480
 
 #ifndef __ASSEMBLY__
@@ -74,7 +75,8 @@ struct parmarea {
        unsigned long initrd_size;                      /* 0x10410 */
        unsigned long oldmem_base;                      /* 0x10418 */
        unsigned long oldmem_size;                      /* 0x10420 */
-       char pad1[0x10480 - 0x10428];                   /* 0x10428 - 0x10480 */
+       unsigned long kernel_version;                   /* 0x10428 */
+       char pad1[0x10480 - 0x10430];                   /* 0x10430 - 0x10480 */
        char command_line[ARCH_COMMAND_LINE_SIZE];      /* 0x10480 */
 };
 
@@ -82,6 +84,7 @@ extern int noexec_disabled;
 extern int memory_end_set;
 extern unsigned long memory_end;
 extern unsigned long max_physmem_end;
+extern unsigned long __swsusp_reset_dma;
 
 #define MACHINE_IS_VM          (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM         (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
index b6755685c7b88851cd92934616a06aee0c5a3335..9e9f75ef046a8f533c78d1927bc0e6701ff822ca 100644 (file)
@@ -34,5 +34,6 @@
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_CLONE3
 
 #endif /* _ASM_S390_UNISTD_H_ */
index cefe7c7cd4f6f29fabd90e33495d7a6d8ac6dbdd..3ed42ff6da949192ae945ae3ebccd6b4811deb33 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _UAPI__ASM_BPF_PERF_EVENT_H__
 #define _UAPI__ASM_BPF_PERF_EVENT_H__
 
index fd32b1cd80d2944b5376574f85f10db855cacab1..451ba7d08905c0a4d1fa91359e8ac863c228e520 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _ASM_S390_UAPI_IPL_H
 #define _ASM_S390_UAPI_IPL_H
 
index 494c34c507161ecce23e72fc4dd5cca2e2a0cf9a..8c5755f41ddeeef538f2d8452020cc1afd25e84f 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/ioctl.h>
 #include <linux/compiler.h>
+#include <linux/types.h>
 
 /* Name of the zcrypt device driver. */
 #define ZCRYPT_NAME "zcrypt"
@@ -160,17 +161,17 @@ struct ica_xcRB {
  * @payload_len:       Payload length
  */
 struct ep11_cprb {
-       uint16_t        cprb_len;
+       __u16           cprb_len;
        unsigned char   cprb_ver_id;
        unsigned char   pad_000[2];
        unsigned char   flags;
        unsigned char   func_id[2];
-       uint32_t        source_id;
-       uint32_t        target_id;
-       uint32_t        ret_code;
-       uint32_t        reserved1;
-       uint32_t        reserved2;
-       uint32_t        payload_len;
+       __u32           source_id;
+       __u32           target_id;
+       __u32           ret_code;
+       __u32           reserved1;
+       __u32           reserved2;
+       __u32           payload_len;
 } __attribute__((packed));
 
 /**
@@ -179,8 +180,8 @@ struct ep11_cprb {
  * @dom_id:    Usage domain id
  */
 struct ep11_target_dev {
-       uint16_t ap_id;
-       uint16_t dom_id;
+       __u16 ap_id;
+       __u16 dom_id;
 };
 
 /**
@@ -195,14 +196,14 @@ struct ep11_target_dev {
  * @resp:              Addr to response block
  */
 struct ep11_urb {
-       uint16_t                targets_num;
-       uint64_t                targets;
-       uint64_t                weight;
-       uint64_t                req_no;
-       uint64_t                req_len;
-       uint64_t                req;
-       uint64_t                resp_len;
-       uint64_t                resp;
+       __u16           targets_num;
+       __u64           targets;
+       __u64           weight;
+       __u64           req_no;
+       __u64           req_len;
+       __u64           req;
+       __u64           resp_len;
+       __u64           resp;
 } __attribute__((packed));
 
 /**
index ac06c3949ab342eb521a9161a4c1197f428eab39..34bdc60c0b11d348946b2b363e76fb7b6dcdf195 100644 (file)
@@ -114,12 +114,8 @@ recursion_check:
         * If it comes up a second time then there's something wrong going on:
         * just break out and report an unknown stack type.
         */
-       if (*visit_mask & (1UL << info->type)) {
-               printk_deferred_once(KERN_WARNING
-                       "WARNING: stack recursion on stack type %d\n",
-                       info->type);
+       if (*visit_mask & (1UL << info->type))
                goto unknown;
-       }
        *visit_mask |= 1UL << info->type;
        return 0;
 unknown:
index 5aea1a527443004f455f56637f017d023077ab19..f384a18e6c2609ef50c03afb288575893b2730c1 100644 (file)
@@ -60,12 +60,5 @@ ENTRY(startup_continue)
 
        .align  16
 .LPG1:
-.Lpcmsk:.quad  0x0000000180000000
-.L4malign:.quad 0xffffffffffc00000
-.Lscan2g:.quad 0x80000000 + 0x20000 - 8        # 2GB + 128K - 8
-.Lnop: .long   0x07000700
-.Lparmaddr:
-       .quad   PARMAREA
-       .align  64
 .Ldw:  .quad   0x0002000180000000,0x0000000000000000
 .Laregs:.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
index 2c0a515428d61879082bcdcc42fe4558ef8dc664..6837affc19e8185cef726000b5eca49971a1c1d5 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/os_info.h>
 #include <asm/sections.h>
 #include <asm/boot_data.h>
-#include <asm/uv.h>
 #include "entry.h"
 
 #define IPL_PARM_BLOCK_VERSION 0
@@ -892,21 +891,15 @@ static void __reipl_run(void *unused)
 {
        switch (reipl_type) {
        case IPL_TYPE_CCW:
-               uv_set_shared(__pa(reipl_block_ccw));
                diag308(DIAG308_SET, reipl_block_ccw);
-               uv_remove_shared(__pa(reipl_block_ccw));
                diag308(DIAG308_LOAD_CLEAR, NULL);
                break;
        case IPL_TYPE_FCP:
-               uv_set_shared(__pa(reipl_block_fcp));
                diag308(DIAG308_SET, reipl_block_fcp);
-               uv_remove_shared(__pa(reipl_block_fcp));
                diag308(DIAG308_LOAD_CLEAR, NULL);
                break;
        case IPL_TYPE_NSS:
-               uv_set_shared(__pa(reipl_block_nss));
                diag308(DIAG308_SET, reipl_block_nss);
-               uv_remove_shared(__pa(reipl_block_nss));
                diag308(DIAG308_LOAD_CLEAR, NULL);
                break;
        case IPL_TYPE_UNKNOWN:
@@ -1176,9 +1169,7 @@ static struct kset *dump_kset;
 
 static void diag308_dump(void *dump_block)
 {
-       uv_set_shared(__pa(dump_block));
        diag308(DIAG308_SET, dump_block);
-       uv_remove_shared(__pa(dump_block));
        while (1) {
                if (diag308(DIAG308_LOAD_NORMAL_DUMP, NULL) != 0x302)
                        break;
index 1dded39239f86605ef0599159ead4c6143f17978..3b664cb3ec4d3b57ba3ca53fa2c3af1d8f92f9e1 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/elf.h>
+#include <asm/kexec.h>
 
 int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val,
                         unsigned long addr)
index d4e031f7b9c818bb106616ed47736b6dc80e68df..5f1fd1581330fd855201ecfa44650467330fe993 100644 (file)
@@ -34,7 +34,7 @@ struct cf_diag_csd {          /* Counter set data per CPU */
        unsigned char start[PAGE_SIZE]; /* Counter set at event start */
        unsigned char data[PAGE_SIZE];  /* Counter set at event delete */
 };
-DEFINE_PER_CPU(struct cf_diag_csd, cf_diag_csd);
+static DEFINE_PER_CPU(struct cf_diag_csd, cf_diag_csd);
 
 /* Counter sets are stored as data stream in a page sized memory buffer and
  * exported to user space via raw data attached to the event sample data.
index 2b94b0ad358827d4e961a3fbce8be9bd5fb41cd2..2531779009503700f7d117e56f11c81df20d2108 100644 (file)
@@ -1114,8 +1114,7 @@ void __init setup_arch(char **cmdline_p)
 
         ROOT_DEV = Root_RAM0;
 
-       /* Is init_mm really needed? */
-       init_mm.start_code = PAGE_OFFSET;
+       init_mm.start_code = (unsigned long) _text;
        init_mm.end_code = (unsigned long) _etext;
        init_mm.end_data = (unsigned long) _edata;
        init_mm.brk = (unsigned long) _end;
index a90d3e94544576c5e935a7e999453d0e994474ba..3054e9c035a39fa051b33cd4655f91885ce534a3 100644 (file)
 432  common    fsmount                 sys_fsmount                     sys_fsmount
 433  common    fspick                  sys_fspick                      sys_fspick
 434  common    pidfd_open              sys_pidfd_open                  sys_pidfd_open
-# 435 reserved for clone3
+435  common    clone3                  sys_clone3                      sys_clone3
index 243d8b1185bfcdbf39d0480aa7245f11c7eb89cc..c6bc190f3c28c967604fc50d099cc05f25278736 100644 (file)
@@ -216,11 +216,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        if (!vdso_enabled)
                return 0;
-       /*
-        * Only map the vdso for dynamically linked elf binaries.
-        */
-       if (!uses_interp)
-               return 0;
 
        vdso_pages = vdso64_pages;
 #ifdef CONFIG_COMPAT_VDSO
index 49d55327de0bcaa2412d035a58a4f1a4fe3dca79..7e0eb40209177ad1014d34d9c1fc3360fa8d1b24 100644 (file)
@@ -32,10 +32,9 @@ PHDRS {
 SECTIONS
 {
        . = 0x100000;
-       _stext = .;             /* Start of text section */
        .text : {
-               /* Text and read-only data */
-               _text = .;
+               _stext = .;             /* Start of text section */
+               _text = .;              /* Text and read-only data */
                HEAD_TEXT
                TEXT_TEXT
                SCHED_TEXT
@@ -47,11 +46,10 @@ SECTIONS
                *(.text.*_indirect_*)
                *(.fixup)
                *(.gnu.warning)
+               . = ALIGN(PAGE_SIZE);
+               _etext = .;             /* End of text section */
        } :text = 0x0700
 
-       . = ALIGN(PAGE_SIZE);
-       _etext = .;             /* End of text section */
-
        NOTES :text :note
 
        .dummy : { *(.dummy) } :data
index b5fd6e85657c2fb1fabf796f29deba382307400d..d1ccc168c0714604011f859926d256d4830edecb 100644 (file)
@@ -1961,6 +1961,16 @@ int s390int_to_s390irq(struct kvm_s390_interrupt *s390int,
        case KVM_S390_MCHK:
                irq->u.mchk.mcic = s390int->parm64;
                break;
+       case KVM_S390_INT_PFAULT_INIT:
+               irq->u.ext.ext_params = s390int->parm;
+               irq->u.ext.ext_params2 = s390int->parm64;
+               break;
+       case KVM_S390_RESTART:
+       case KVM_S390_INT_CLOCK_COMP:
+       case KVM_S390_INT_CPU_TIMER:
+               break;
+       default:
+               return -EINVAL;
        }
        return 0;
 }
index 3f520cd837fb8ccea849adc1b36d7e4a2026090b..39cff07bf2ebef248e2f9630517e4be31ab3530c 100644 (file)
@@ -1018,6 +1018,8 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
        /* mark all the pages in active slots as dirty */
        for (slotnr = 0; slotnr < slots->used_slots; slotnr++) {
                ms = slots->memslots + slotnr;
+               if (!ms->dirty_bitmap)
+                       return -EINVAL;
                /*
                 * The second half of the bitmap is only used on x86,
                 * and would be wasted otherwise, so we put it to good
@@ -2516,16 +2518,6 @@ out_err:
        return rc;
 }
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
-       return 0;
-}
-
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
        VCPU_EVENT(vcpu, 3, "%s", "free cpu");
@@ -4333,7 +4325,7 @@ long kvm_arch_vcpu_async_ioctl(struct file *filp,
        }
        case KVM_S390_INTERRUPT: {
                struct kvm_s390_interrupt s390int;
-               struct kvm_s390_irq s390irq;
+               struct kvm_s390_irq s390irq = {};
 
                if (copy_from_user(&s390int, argp, sizeof(s390int)))
                        return -EFAULT;
index 96580590ccaf04c4f110c6a3e05c0078945bc3de..29d9470dbcebf9dd511a8d9e363976b8ef30146e 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/export.h>
 #include <linux/raid/xor.h>
+#include <asm/xor.h>
 
 static void xor_xc_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 {
index 3b93ba0b5d8d6e03b3289f861c4f244681e2826f..5d67b81c704a49214b500c3fce7af3f728860353 100644 (file)
@@ -161,9 +161,9 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
        }
 #endif
 
-       for (i = 0; i < PTRS_PER_PMD && addr < max_addr; i++) {
+       pmd = pmd_offset(pud, addr);
+       for (i = 0; i < PTRS_PER_PMD && addr < max_addr; i++, pmd++) {
                st->current_address = addr;
-               pmd = pmd_offset(pud, addr);
                if (!pmd_none(*pmd)) {
                        if (pmd_large(*pmd)) {
                                prot = pmd_val(*pmd) &
@@ -192,9 +192,9 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
        }
 #endif
 
-       for (i = 0; i < PTRS_PER_PUD && addr < max_addr; i++) {
+       pud = pud_offset(p4d, addr);
+       for (i = 0; i < PTRS_PER_PUD && addr < max_addr; i++, pud++) {
                st->current_address = addr;
-               pud = pud_offset(p4d, addr);
                if (!pud_none(*pud))
                        if (pud_large(*pud)) {
                                prot = pud_val(*pud) &
@@ -222,9 +222,9 @@ static void walk_p4d_level(struct seq_file *m, struct pg_state *st,
        }
 #endif
 
-       for (i = 0; i < PTRS_PER_P4D && addr < max_addr; i++) {
+       p4d = p4d_offset(pgd, addr);
+       for (i = 0; i < PTRS_PER_P4D && addr < max_addr; i++, p4d++) {
                st->current_address = addr;
-               p4d = p4d_offset(pgd, addr);
                if (!p4d_none(*p4d))
                        walk_pud_level(m, st, p4d, addr);
                else
index 63507662828fd90e008a7e1b254496a57d548a16..7b0bb475c166496ff054f18a780748a25c028a1c 100644 (file)
@@ -327,6 +327,7 @@ static noinline void do_fault_error(struct pt_regs *regs, int access,
        case VM_FAULT_BADACCESS:
                if (access == VM_EXEC && signal_return(regs) == 0)
                        break;
+               /* fallthrough */
        case VM_FAULT_BADMAP:
                /* Bad memory access. Check if it is kernel or user space. */
                if (user_mode(regs)) {
@@ -336,7 +337,9 @@ static noinline void do_fault_error(struct pt_regs *regs, int access,
                        do_sigsegv(regs, si_code);
                        break;
                }
+               /* fallthrough */
        case VM_FAULT_BADCONTEXT:
+               /* fallthrough */
        case VM_FAULT_PFAULT:
                do_no_context(regs);
                break;
index 1e668b95e0c664352dac7a8ea8c4c4d189d07996..39c3a6e3d26218161bd63e5746d862b9af335edd 100644 (file)
@@ -2424,8 +2424,8 @@ EXPORT_SYMBOL_GPL(gmap_pmdp_idte_global);
  * This function is assumed to be called with the guest_table_lock
  * held.
  */
-bool gmap_test_and_clear_dirty_pmd(struct gmap *gmap, pmd_t *pmdp,
-                                  unsigned long gaddr)
+static bool gmap_test_and_clear_dirty_pmd(struct gmap *gmap, pmd_t *pmdp,
+                                         unsigned long gaddr)
 {
        if (pmd_val(*pmdp) & _SEGMENT_ENTRY_INVALID)
                return false;
index 99e06213a22b7c259ba90831c4cf7cbda6d1a301..54fcdf66ae967c4546bb6c39933de43ac164150a 100644 (file)
@@ -17,8 +17,6 @@
 
 #ifdef CONFIG_PGSTE
 
-static int page_table_allocate_pgste_min = 0;
-static int page_table_allocate_pgste_max = 1;
 int page_table_allocate_pgste = 0;
 EXPORT_SYMBOL(page_table_allocate_pgste);
 
@@ -29,8 +27,8 @@ static struct ctl_table page_table_sysctl[] = {
                .maxlen         = sizeof(int),
                .mode           = S_IRUGO | S_IWUSR,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &page_table_allocate_pgste_min,
-               .extra2         = &page_table_allocate_pgste_max,
+               .extra1         = SYSCTL_ZERO,
+               .extra2         = SYSCTL_ONE,
        },
        { }
 };
index e636728ab452e1818f3566727396945264f3af3b..955eb355c2fdea049412ecbcf81b84427e4cf406 100644 (file)
@@ -863,7 +863,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
                break;
        case BPF_ALU64 | BPF_NEG: /* dst = -dst */
                /* lcgr %dst,%dst */
-               EMIT4(0xb9130000, dst_reg, dst_reg);
+               EMIT4(0xb9030000, dst_reg, dst_reg);
                break;
        /*
         * BPF_FROM_BE/LE
@@ -1049,8 +1049,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
                /* llgf %w1,map.max_entries(%b2) */
                EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_2,
                              offsetof(struct bpf_array, map.max_entries));
-               /* clgrj %b3,%w1,0xa,label0: if %b3 >= %w1 goto out */
-               EMIT6_PCREL_LABEL(0xec000000, 0x0065, BPF_REG_3,
+               /* clrj %b3,%w1,0xa,label0: if (u32)%b3 >= (u32)%w1 goto out */
+               EMIT6_PCREL_LABEL(0xec000000, 0x0077, BPF_REG_3,
                                  REG_W1, 0, 0xa);
 
                /*
@@ -1076,8 +1076,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
                 *         goto out;
                 */
 
-               /* sllg %r1,%b3,3: %r1 = index * 8 */
-               EMIT6_DISP_LH(0xeb000000, 0x000d, REG_1, BPF_REG_3, REG_0, 3);
+               /* llgfr %r1,%b3: %r1 = (u32) index */
+               EMIT4(0xb9160000, REG_1, BPF_REG_3);
+               /* sllg %r1,%r1,3: %r1 *= 8 */
+               EMIT6_DISP_LH(0xeb000000, 0x000d, REG_1, REG_1, REG_0, 3);
                /* lg %r1,prog(%b2,%r1) */
                EMIT6_DISP_LH(0xe3000000, 0x0004, REG_1, BPF_REG_2,
                              REG_1, offsetof(struct bpf_array, ptrs));
index 884a9caff5fb8be71c80fce894d78ef1fe5f955d..f4f4c2c6dee9eeae8a0b197538ed16d7cf1ed51d 100644 (file)
@@ -11,8 +11,7 @@ chkbss: $(addprefix $(obj)/, $(chkbss-files))
 
 quiet_cmd_chkbss = CHKBSS  $<
       cmd_chkbss = \
-       if $(OBJDUMP) -h $< | grep -q "\.bss" && \
-          ! $(OBJDUMP) -j .bss -w -h $< | awk 'END { if ($$3) exit 1 }'; then \
+       if ! $(OBJSIZE) --common $< | $(AWK) 'END { if ($$3) exit 1 }'; then \
                echo "error: $< .bss section is not empty" >&2; exit 1; \
        fi; \
        touch $@;
index 1170dd2fb99892a29bef0ac602a4d0d597a51cf9..4bd19f80f9b0b3134fa2dafb9c7d311515b76423 100644 (file)
@@ -1,2 +1,2 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #include <asm-generic/setup.h>
index f83795fdc0da2f35816f23e689ba690c9ecdce3c..68100e108ea6090d34ca6e6ad5ec3559e0727048 100644 (file)
@@ -1,2 +1,2 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #include <asm-generic/types.h>
index defebf1a9c8af223ad6ea4ed9af2f315acbc2202..845543780cc5501406f0817bf3312ef5aedd4bdb 100644 (file)
@@ -475,8 +475,6 @@ static void print_sh_insn(u32 memaddr, u16 insn)
                                printk("dbr");
                                break;
                        case FD_REG_N:
-                               if (0)
-                                       goto d_reg_n;
                        case F_REG_N:
                                printk("fr%d", rn);
                                break;
@@ -488,7 +486,7 @@ static void print_sh_insn(u32 memaddr, u16 insn)
                                        printk("xd%d", rn & ~1);
                                        break;
                                }
-                       d_reg_n:
+                               /* else, fall through */
                        case D_REG_N:
                                printk("dr%d", rn);
                                break;
@@ -497,6 +495,7 @@ static void print_sh_insn(u32 memaddr, u16 insn)
                                        printk("xd%d", rm & ~1);
                                        break;
                                }
+                               /* else, fall through */
                        case D_REG_M:
                                printk("dr%d", rm);
                                break;
index 3bd010b4c55f58e49f0e761693bab35dd070c36d..f10d64311127baa9aca0a80003fda2ed9aeecf3f 100644 (file)
@@ -157,6 +157,7 @@ int arch_bp_generic_fields(int sh_len, int sh_type,
        switch (sh_type) {
        case SH_BREAKPOINT_READ:
                *gen_type = HW_BREAKPOINT_R;
+               break;
        case SH_BREAKPOINT_WRITE:
                *gen_type = HW_BREAKPOINT_W;
                break;
index 64c67f2ea33fa88f1e92eadca235d085e24214aa..0dace69058abf0df316a016da31443eaa13b519f 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
 /*
  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  */
index ccc88926bc000b9573af14f578d74098f7c7a8ff..9f41a6f5a032da07f280c29233525694bbbf8540 100644 (file)
@@ -336,25 +336,28 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
 {
        long err;
 
+       if (!IS_ENABLED(CONFIG_SYSVIPC))
+               return -ENOSYS;
+
        /* No need for backward compatibility. We can start fresh... */
        if (call <= SEMTIMEDOP) {
                switch (call) {
                case SEMOP:
-                       err = sys_semtimedop(first, ptr,
-                                            (unsigned int)second, NULL);
+                       err = ksys_semtimedop(first, ptr,
+                                             (unsigned int)second, NULL);
                        goto out;
                case SEMTIMEDOP:
-                       err = sys_semtimedop(first, ptr, (unsigned int)second,
+                       err = ksys_semtimedop(first, ptr, (unsigned int)second,
                                (const struct __kernel_timespec __user *)
-                                            (unsigned long) fifth);
+                                             (unsigned long) fifth);
                        goto out;
                case SEMGET:
-                       err = sys_semget(first, (int)second, (int)third);
+                       err = ksys_semget(first, (int)second, (int)third);
                        goto out;
                case SEMCTL: {
-                       err = sys_semctl(first, second,
-                                        (int)third | IPC_64,
-                                        (unsigned long) ptr);
+                       err = ksys_old_semctl(first, second,
+                                             (int)third | IPC_64,
+                                             (unsigned long) ptr);
                        goto out;
                }
                default:
@@ -365,18 +368,18 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
        if (call <= MSGCTL) {
                switch (call) {
                case MSGSND:
-                       err = sys_msgsnd(first, ptr, (size_t)second,
+                       err = ksys_msgsnd(first, ptr, (size_t)second,
                                         (int)third);
                        goto out;
                case MSGRCV:
-                       err = sys_msgrcv(first, ptr, (size_t)second, fifth,
+                       err = ksys_msgrcv(first, ptr, (size_t)second, fifth,
                                         (int)third);
                        goto out;
                case MSGGET:
-                       err = sys_msgget((key_t)first, (int)second);
+                       err = ksys_msgget((key_t)first, (int)second);
                        goto out;
                case MSGCTL:
-                       err = sys_msgctl(first, (int)second | IPC_64, ptr);
+                       err = ksys_old_msgctl(first, (int)second | IPC_64, ptr);
                        goto out;
                default:
                        err = -ENOSYS;
@@ -396,13 +399,13 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
                        goto out;
                }
                case SHMDT:
-                       err = sys_shmdt(ptr);
+                       err = ksys_shmdt(ptr);
                        goto out;
                case SHMGET:
-                       err = sys_shmget(first, (size_t)second, (int)third);
+                       err = ksys_shmget(first, (size_t)second, (int)third);
                        goto out;
                case SHMCTL:
-                       err = sys_shmctl(first, (int)second | IPC_64, ptr);
+                       err = ksys_old_shmctl(first, (int)second | IPC_64, ptr);
                        goto out;
                default:
                        err = -ENOSYS;
index 8574338bf23ba48394fd40a49a564bf11969868e..9991ec2371e44e21626df7b587f486c18dc4641d 100644 (file)
@@ -34,10 +34,13 @@ static inline void time_travel_set_time(unsigned long long ns)
        time_travel_time = ns;
 }
 
-static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
-                                        unsigned long long expiry)
+static inline void time_travel_set_timer_mode(enum time_travel_timer_mode mode)
 {
        time_travel_timer_mode = mode;
+}
+
+static inline void time_travel_set_timer_expiry(unsigned long long expiry)
+{
        time_travel_timer_expiry = expiry;
 }
 #else
@@ -50,8 +53,11 @@ static inline void time_travel_set_time(unsigned long long ns)
 {
 }
 
-static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
-                                        unsigned long long expiry)
+static inline void time_travel_set_timer_mode(enum time_travel_timer_mode mode)
+{
+}
+
+static inline void time_travel_set_timer_expiry(unsigned long long expiry)
 {
 }
 
index 67c0d1a860e980d97ecb6d6bbf7cb349699edbfc..6bede7888fc202f1a268ffcab0f763219a9fba5d 100644 (file)
@@ -213,7 +213,7 @@ static void time_travel_sleep(unsigned long long duration)
        if (time_travel_timer_mode != TT_TMR_DISABLED ||
            time_travel_timer_expiry < next) {
                if (time_travel_timer_mode == TT_TMR_ONESHOT)
-                       time_travel_set_timer(TT_TMR_DISABLED, 0);
+                       time_travel_set_timer_mode(TT_TMR_DISABLED);
                /*
                 * time_travel_time will be adjusted in the timer
                 * IRQ handler so it works even when the signal
index 6a051b078359dd99a4c98fdcea8daa3394da3314..234757233355fb1278bac9f98dca9c0bc637ea46 100644 (file)
@@ -50,7 +50,7 @@ void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
 static int itimer_shutdown(struct clock_event_device *evt)
 {
        if (time_travel_mode != TT_MODE_OFF)
-               time_travel_set_timer(TT_TMR_DISABLED, 0);
+               time_travel_set_timer_mode(TT_TMR_DISABLED);
 
        if (time_travel_mode != TT_MODE_INFCPU)
                os_timer_disable();
@@ -62,9 +62,10 @@ static int itimer_set_periodic(struct clock_event_device *evt)
 {
        unsigned long long interval = NSEC_PER_SEC / HZ;
 
-       if (time_travel_mode != TT_MODE_OFF)
-               time_travel_set_timer(TT_TMR_PERIODIC,
-                                     time_travel_time + interval);
+       if (time_travel_mode != TT_MODE_OFF) {
+               time_travel_set_timer_mode(TT_TMR_PERIODIC);
+               time_travel_set_timer_expiry(time_travel_time + interval);
+       }
 
        if (time_travel_mode != TT_MODE_INFCPU)
                os_timer_set_interval(interval);
@@ -77,9 +78,10 @@ static int itimer_next_event(unsigned long delta,
 {
        delta += 1;
 
-       if (time_travel_mode != TT_MODE_OFF)
-               time_travel_set_timer(TT_TMR_ONESHOT,
-                                     time_travel_time + delta);
+       if (time_travel_mode != TT_MODE_OFF) {
+               time_travel_set_timer_mode(TT_TMR_ONESHOT);
+               time_travel_set_timer_expiry(time_travel_time + delta);
+       }
 
        if (time_travel_mode != TT_MODE_INFCPU)
                return os_timer_one_shot(delta);
index 56e748a7679f4b931b420eaec6bd63f174337e59..94df0868804bcb4b9b37f7abf4985ac95158c4f8 100644 (file)
@@ -38,6 +38,7 @@ REALMODE_CFLAGS       := $(M16_CFLAGS) -g -Os -DDISABLE_BRANCH_PROFILING \
 
 REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding)
 REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector)
+REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -Wno-address-of-packed-member)
 REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), $(cc_stack_align4))
 export REALMODE_CFLAGS
 
index 5f2d03067ae57cdb95555fe423bdafc52bbec200..c8862696a47b949be25235531a39a65db94eb8ba 100644 (file)
@@ -72,6 +72,8 @@ static unsigned long find_trampoline_placement(void)
 
        /* Find the first usable memory region under bios_start. */
        for (i = boot_params->e820_entries - 1; i >= 0; i--) {
+               unsigned long new = bios_start;
+
                entry = &boot_params->e820_table[i];
 
                /* Skip all entries above bios_start. */
@@ -84,15 +86,20 @@ static unsigned long find_trampoline_placement(void)
 
                /* Adjust bios_start to the end of the entry if needed. */
                if (bios_start > entry->addr + entry->size)
-                       bios_start = entry->addr + entry->size;
+                       new = entry->addr + entry->size;
 
                /* Keep bios_start page-aligned. */
-               bios_start = round_down(bios_start, PAGE_SIZE);
+               new = round_down(new, PAGE_SIZE);
 
                /* Skip the entry if it's too small. */
-               if (bios_start - TRAMPOLINE_32BIT_SIZE < entry->addr)
+               if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
                        continue;
 
+               /* Protect against underflow. */
+               if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
+                       break;
+
+               bios_start = new;
                break;
        }
 
index 401e30ca0a7589e73b0ad2bec7b0c28963de2602..8272a44928444ec6a679819db52c6e1adefc5f80 100644 (file)
@@ -37,6 +37,14 @@ int memcmp(const void *s1, const void *s2, size_t len)
        return diff;
 }
 
+/*
+ * Clang may lower `memcmp == 0` to `bcmp == 0`.
+ */
+int bcmp(const void *s1, const void *s2, size_t len)
+{
+       return memcmp(s1, s2, len);
+}
+
 int strcmp(const char *str1, const char *str2)
 {
        const unsigned char *s1 = (const unsigned char *)str1;
index 830bd984182b6bc05c09b868a9100d0917691381..515c0ceeb4a3608bbdd0cb9afad747417e8a7f88 100644 (file)
@@ -314,6 +314,23 @@ For 32-bit we have the following conventions - kernel is built with
 
 #endif
 
+/*
+ * Mitigate Spectre v1 for conditional swapgs code paths.
+ *
+ * FENCE_SWAPGS_USER_ENTRY is used in the user entry swapgs code path, to
+ * prevent a speculative swapgs when coming from kernel space.
+ *
+ * FENCE_SWAPGS_KERNEL_ENTRY is used in the kernel entry non-swapgs code path,
+ * to prevent the swapgs from getting speculatively skipped when coming from
+ * user space.
+ */
+.macro FENCE_SWAPGS_USER_ENTRY
+       ALTERNATIVE "", "lfence", X86_FEATURE_FENCE_SWAPGS_USER
+.endm
+.macro FENCE_SWAPGS_KERNEL_ENTRY
+       ALTERNATIVE "", "lfence", X86_FEATURE_FENCE_SWAPGS_KERNEL
+.endm
+
 .macro STACKLEAK_ERASE_NOCLOBBER
 #ifdef CONFIG_GCC_PLUGIN_STACKLEAK
        PUSH_AND_CLEAR_REGS
index 2bb986f305ace7fdf4de68ee2c32d776c30221e8..4f86928246e7a37ada2b324e84cf6d26be70dff2 100644 (file)
@@ -1443,8 +1443,12 @@ BUILD_INTERRUPT3(hv_stimer0_callback_vector, HYPERV_STIMER0_VECTOR,
 
 ENTRY(page_fault)
        ASM_CLAC
-       pushl   $0; /* %gs's slot on the stack */
+       pushl   $do_page_fault
+       jmp     common_exception_read_cr2
+END(page_fault)
 
+common_exception_read_cr2:
+       /* the function address is in %gs's slot on the stack */
        SAVE_ALL switch_stacks=1 skip_gs=1
 
        ENCODE_FRAME_POINTER
@@ -1452,6 +1456,7 @@ ENTRY(page_fault)
 
        /* fixup %gs */
        GS_TO_REG %ecx
+       movl    PT_GS(%esp), %edi
        REG_TO_PTGS %ecx
        SET_KERNEL_GS %ecx
 
@@ -1463,9 +1468,9 @@ ENTRY(page_fault)
 
        TRACE_IRQS_OFF
        movl    %esp, %eax                      # pt_regs pointer
-       call    do_page_fault
+       CALL_NOSPEC %edi
        jmp     ret_from_exception
-END(page_fault)
+END(common_exception_read_cr2)
 
 common_exception:
        /* the function address is in %gs's slot on the stack */
@@ -1595,7 +1600,7 @@ END(general_protection)
 ENTRY(async_page_fault)
        ASM_CLAC
        pushl   $do_async_page_fault
-       jmp     common_exception
+       jmp     common_exception_read_cr2
 END(async_page_fault)
 #endif
 
index 3f5a978a02a7d0906237e517580b6d5440a7fcba..be9ca198c581aea7ed29f4417aae9c1c1b835473 100644 (file)
@@ -519,7 +519,7 @@ ENTRY(interrupt_entry)
        testb   $3, CS-ORIG_RAX+8(%rsp)
        jz      1f
        SWAPGS
-
+       FENCE_SWAPGS_USER_ENTRY
        /*
         * Switch to the thread stack. The IRET frame and orig_ax are
         * on the stack, as well as the return address. RDI..R12 are
@@ -549,8 +549,10 @@ ENTRY(interrupt_entry)
        UNWIND_HINT_FUNC
 
        movq    (%rdi), %rdi
+       jmp     2f
 1:
-
+       FENCE_SWAPGS_KERNEL_ENTRY
+2:
        PUSH_AND_CLEAR_REGS save_ret=1
        ENCODE_FRAME_POINTER 8
 
@@ -1238,6 +1240,13 @@ ENTRY(paranoid_entry)
         */
        SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14
 
+       /*
+        * The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an
+        * unconditional CR3 write, even in the PTI case.  So do an lfence
+        * to prevent GS speculation, regardless of whether PTI is enabled.
+        */
+       FENCE_SWAPGS_KERNEL_ENTRY
+
        ret
 END(paranoid_entry)
 
@@ -1288,6 +1297,7 @@ ENTRY(error_entry)
         * from user mode due to an IRET fault.
         */
        SWAPGS
+       FENCE_SWAPGS_USER_ENTRY
        /* We have user CR3.  Change to kernel CR3. */
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
 
@@ -1301,6 +1311,8 @@ ENTRY(error_entry)
        pushq   %r12
        ret
 
+.Lerror_entry_done_lfence:
+       FENCE_SWAPGS_KERNEL_ENTRY
 .Lerror_entry_done:
        ret
 
@@ -1318,7 +1330,7 @@ ENTRY(error_entry)
        cmpq    %rax, RIP+8(%rsp)
        je      .Lbstep_iret
        cmpq    $.Lgs_change, RIP+8(%rsp)
-       jne     .Lerror_entry_done
+       jne     .Lerror_entry_done_lfence
 
        /*
         * hack: .Lgs_change can fail with user gsbase.  If this happens, fix up
@@ -1326,6 +1338,7 @@ ENTRY(error_entry)
         * .Lgs_change's error handler with kernel gsbase.
         */
        SWAPGS
+       FENCE_SWAPGS_USER_ENTRY
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
        jmp .Lerror_entry_done
 
@@ -1340,6 +1353,7 @@ ENTRY(error_entry)
         * gsbase and CR3.  Switch to kernel gsbase and CR3:
         */
        SWAPGS
+       FENCE_SWAPGS_USER_ENTRY
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
 
        /*
@@ -1431,6 +1445,7 @@ ENTRY(nmi)
 
        swapgs
        cld
+       FENCE_SWAPGS_USER_ENTRY
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rdx
        movq    %rsp, %rdx
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
index 62f317c9113afc0ff252ffb4b05c82b1ac158bd6..5b35b7ea5d7282d870b7d0d2a519620793deba76 100644 (file)
@@ -661,10 +661,17 @@ fail:
 
        throttle = perf_event_overflow(event, &data, &regs);
 out:
-       if (throttle)
+       if (throttle) {
                perf_ibs_stop(event, 0);
-       else
-               perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
+       } else {
+               period >>= 4;
+
+               if ((ibs_caps & IBS_CAPS_RDWROPCNT) &&
+                   (*config & IBS_OP_CNT_CTL))
+                       period |= *config & IBS_OP_CUR_CNT_RAND;
+
+               perf_ibs_enable_event(perf_ibs, hwc, period);
+       }
 
        perf_event_update_userpage(event);
 
index 81b005e4c7d9f956e632b82cef9302976fc73e6c..325959d19d9a859b0f153d9c3a09ec9fe54833a2 100644 (file)
@@ -1236,7 +1236,7 @@ void x86_pmu_enable_event(struct perf_event *event)
  * Add a single event to the PMU.
  *
  * The event is added to the group of enabled events
- * but only if it can be scehduled with existing events.
+ * but only if it can be scheduled with existing events.
  */
 static int x86_pmu_add(struct perf_event *event, int flags)
 {
index 9e911a96972b51e3b49231bb693ad8dd5469046e..e4c2cb65ea50a15ef8c35a934e87f23dfdf32ee0 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/intel-family.h>
 #include <asm/apic.h>
 #include <asm/cpu_device_id.h>
-#include <asm/hypervisor.h>
 
 #include "../perf_event.h"
 
@@ -263,8 +262,8 @@ static struct event_constraint intel_icl_event_constraints[] = {
 };
 
 static struct extra_reg intel_icl_extra_regs[] __read_mostly = {
-       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffff9fffull, RSP_0),
-       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffff9fffull, RSP_1),
+       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffffbfffull, RSP_0),
+       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffffbfffull, RSP_1),
        INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
        INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff17, FE),
        EVENT_EXTRA_END
@@ -3573,6 +3572,11 @@ static u64 bdw_limit_period(struct perf_event *event, u64 left)
        return left;
 }
 
+static u64 nhm_limit_period(struct perf_event *event, u64 left)
+{
+       return max(left, 32ULL);
+}
+
 PMU_FORMAT_ATTR(event, "config:0-7"    );
 PMU_FORMAT_ATTR(umask, "config:8-15"   );
 PMU_FORMAT_ATTR(edge,  "config:18"     );
@@ -4053,7 +4057,7 @@ static bool check_msr(unsigned long msr, u64 mask)
         * Disable the check for real HW, so we don't
         * mess with potentionaly enabled registers:
         */
-       if (hypervisor_is_type(X86_HYPER_NATIVE))
+       if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
                return true;
 
        /*
@@ -4607,6 +4611,7 @@ __init int intel_pmu_init(void)
                x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
                x86_pmu.enable_all = intel_pmu_nhm_enable_all;
                x86_pmu.extra_regs = intel_nehalem_extra_regs;
+               x86_pmu.limit_period = nhm_limit_period;
 
                mem_attr = nhm_mem_events_attrs;
 
@@ -4955,6 +4960,7 @@ __init int intel_pmu_init(void)
 
        case INTEL_FAM6_SKYLAKE_X:
                pmem = true;
+               /* fall through */
        case INTEL_FAM6_SKYLAKE_MOBILE:
        case INTEL_FAM6_SKYLAKE_DESKTOP:
        case INTEL_FAM6_KABYLAKE_MOBILE:
@@ -5004,6 +5010,7 @@ __init int intel_pmu_init(void)
        case INTEL_FAM6_ICELAKE_X:
        case INTEL_FAM6_ICELAKE_XEON_D:
                pmem = true;
+               /* fall through */
        case INTEL_FAM6_ICELAKE_MOBILE:
        case INTEL_FAM6_ICELAKE_DESKTOP:
                x86_pmu.late_ack = true;
index 2c8db2c19328bcbf95e8c14b4f58e0d2d6d7d7ba..f1269e804e9b70a1e144ede95677d6ddb5f76044 100644 (file)
@@ -851,7 +851,7 @@ struct event_constraint intel_skl_pebs_event_constraints[] = {
 
 struct event_constraint intel_icl_pebs_event_constraints[] = {
        INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x100000000ULL),   /* INST_RETIRED.PREC_DIST */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x400000000ULL),  /* SLOTS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL),  /* SLOTS */
 
        INTEL_PLD_CONSTRAINT(0x1cd, 0xff),                      /* MEM_TRANS_RETIRED.LOAD_LATENCY */
        INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x1d0, 0xf),    /* MEM_INST_RETIRED.LOAD */
index e65d7fe6489f3e80512a7b38724c929ee647d12f..5208ba49c89a96144ba52d82cabc21ad39a743e8 100644 (file)
@@ -37,12 +37,14 @@ static inline int fill_gva_list(u64 gva_list[], int offset,
                 * Lower 12 bits encode the number of additional
                 * pages to flush (in addition to the 'cur' page).
                 */
-               if (diff >= HV_TLB_FLUSH_UNIT)
+               if (diff >= HV_TLB_FLUSH_UNIT) {
                        gva_list[gva_n] |= ~PAGE_MASK;
-               else if (diff)
+                       cur += HV_TLB_FLUSH_UNIT;
+               }  else if (diff) {
                        gva_list[gva_n] |= (diff - 1) >> PAGE_SHIFT;
+                       cur = end;
+               }
 
-               cur += HV_TLB_FLUSH_UNIT;
                gva_n++;
 
        } while (cur < end);
index 101eb944f13c2c8ad6b4d9af9ec8e3264fb1f5a7..981fe923a59fe5983d385ee042e339aa6cfd131f 100644 (file)
  * Note: efi_info is commonly left uninitialized, but that field has a
  * private magic, so it is better to leave it unchanged.
  */
+
+#define sizeof_mbr(type, member) ({ sizeof(((type *)0)->member); })
+
+#define BOOT_PARAM_PRESERVE(struct_member)                             \
+       {                                                               \
+               .start = offsetof(struct boot_params, struct_member),   \
+               .len   = sizeof_mbr(struct boot_params, struct_member), \
+       }
+
+struct boot_params_to_save {
+       unsigned int start;
+       unsigned int len;
+};
+
 static void sanitize_boot_params(struct boot_params *boot_params)
 {
        /* 
@@ -35,21 +49,41 @@ static void sanitize_boot_params(struct boot_params *boot_params)
         * problems again.
         */
        if (boot_params->sentinel) {
-               /* fields in boot_params are left uninitialized, clear them */
-               boot_params->acpi_rsdp_addr = 0;
-               memset(&boot_params->ext_ramdisk_image, 0,
-                      (char *)&boot_params->efi_info -
-                       (char *)&boot_params->ext_ramdisk_image);
-               memset(&boot_params->kbd_status, 0,
-                      (char *)&boot_params->hdr -
-                      (char *)&boot_params->kbd_status);
-               memset(&boot_params->_pad7[0], 0,
-                      (char *)&boot_params->edd_mbr_sig_buffer[0] -
-                       (char *)&boot_params->_pad7[0]);
-               memset(&boot_params->_pad8[0], 0,
-                      (char *)&boot_params->eddbuf[0] -
-                       (char *)&boot_params->_pad8[0]);
-               memset(&boot_params->_pad9[0], 0, sizeof(boot_params->_pad9));
+               static struct boot_params scratch;
+               char *bp_base = (char *)boot_params;
+               char *save_base = (char *)&scratch;
+               int i;
+
+               const struct boot_params_to_save to_save[] = {
+                       BOOT_PARAM_PRESERVE(screen_info),
+                       BOOT_PARAM_PRESERVE(apm_bios_info),
+                       BOOT_PARAM_PRESERVE(tboot_addr),
+                       BOOT_PARAM_PRESERVE(ist_info),
+                       BOOT_PARAM_PRESERVE(hd0_info),
+                       BOOT_PARAM_PRESERVE(hd1_info),
+                       BOOT_PARAM_PRESERVE(sys_desc_table),
+                       BOOT_PARAM_PRESERVE(olpc_ofw_header),
+                       BOOT_PARAM_PRESERVE(efi_info),
+                       BOOT_PARAM_PRESERVE(alt_mem_k),
+                       BOOT_PARAM_PRESERVE(scratch),
+                       BOOT_PARAM_PRESERVE(e820_entries),
+                       BOOT_PARAM_PRESERVE(eddbuf_entries),
+                       BOOT_PARAM_PRESERVE(edd_mbr_sig_buf_entries),
+                       BOOT_PARAM_PRESERVE(edd_mbr_sig_buffer),
+                       BOOT_PARAM_PRESERVE(secure_boot),
+                       BOOT_PARAM_PRESERVE(hdr),
+                       BOOT_PARAM_PRESERVE(e820_table),
+                       BOOT_PARAM_PRESERVE(eddbuf),
+               };
+
+               memset(&scratch, 0, sizeof(scratch));
+
+               for (i = 0; i < ARRAY_SIZE(to_save); i++) {
+                       memcpy(save_base + to_save[i].start,
+                              bp_base + to_save[i].start, to_save[i].len);
+               }
+
+               memcpy(boot_params, save_base, sizeof(*boot_params));
        }
 }
 
index 998c2cc083633f2c564f3cae528b787f7f712f25..e880f2408e29d5e56bb659d851ccb254cc9a148e 100644 (file)
 #define X86_FEATURE_CQM_OCCUP_LLC      (11*32+ 1) /* LLC occupancy monitoring */
 #define X86_FEATURE_CQM_MBM_TOTAL      (11*32+ 2) /* LLC Total MBM monitoring */
 #define X86_FEATURE_CQM_MBM_LOCAL      (11*32+ 3) /* LLC Local MBM monitoring */
+#define X86_FEATURE_FENCE_SWAPGS_USER  (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
+#define X86_FEATURE_FENCE_SWAPGS_KERNEL        (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX512_BF16                (12*32+ 5) /* AVX512 BFLOAT16 instructions */
 #define X86_BUG_L1TF                   X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
 #define X86_BUG_MDS                    X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
 #define X86_BUG_MSBDS_ONLY             X86_BUG(20) /* CPU is only affected by the  MSDBS variant of BUG_MDS */
+#define X86_BUG_SWAPGS                 X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index 287f1f7b2e529419b0401c30c53f3ae7604dcf78..c38a66661576bf7f800de5860b16bd8bae02ccf0 100644 (file)
@@ -16,7 +16,6 @@
 #define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
 
 #ifndef __ASSEMBLY__
-extern void mcount(void);
 extern atomic_t modifying_ftrace_code;
 extern void __fentry__(void);
 
index 0278aa66ef6274eeb91eedf1dfe7d10d60f2d4f2..fe7c205233f1cbb8fcccb7ec413c9322a19cc94c 100644 (file)
  * While adding a new CPUID for a new microarchitecture, add a new
  * group to keep logically sorted out in chronological order. Within
  * that group keep the CPUID for the variants sorted by model number.
+ *
+ * The defined symbol names have the following form:
+ *     INTEL_FAM6{OPTFAMILY}_{MICROARCH}{OPTDIFF}
+ * where:
+ * OPTFAMILY   Describes the family of CPUs that this belongs to. Default
+ *             is assumed to be "_CORE" (and should be omitted). Other values
+ *             currently in use are _ATOM and _XEON_PHI
+ * MICROARCH   Is the code name for the micro-architecture for this core.
+ *             N.B. Not the platform name.
+ * OPTDIFF     If needed, a short string to differentiate by market segment.
+ *             Exact strings here will vary over time. _DESKTOP, _MOBILE, and
+ *             _X (short for Xeon server) should be used when they are
+ *             appropriate.
+ *
+ * The #define line may optionally include a comment including platform names.
  */
 
 #define INTEL_FAM6_CORE_YONAH          0x0E
index 8282b8d41209898937c6effa51ce7fcfa13365d5..bdc16b0aa7c6f8846a0c6864f3d098592542892c 100644 (file)
@@ -35,6 +35,8 @@
 #include <asm/kvm_vcpu_regs.h>
 #include <asm/hyperv-tlfs.h>
 
+#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
+
 #define KVM_MAX_VCPUS 288
 #define KVM_SOFT_MAX_VCPUS 240
 #define KVM_MAX_VCPU_ID 1023
@@ -333,6 +335,7 @@ struct kvm_mmu_page {
        int root_count;          /* Currently serving as active root */
        unsigned int unsync_children;
        struct kvm_rmap_head parent_ptes; /* rmap pointers to parent sptes */
+       unsigned long mmu_valid_gen;
        DECLARE_BITMAP(unsync_child_bitmap, 512);
 
 #ifdef CONFIG_X86_32
@@ -607,15 +610,16 @@ struct kvm_vcpu_arch {
 
        /*
         * QEMU userspace and the guest each have their own FPU state.
-        * In vcpu_run, we switch between the user, maintained in the
-        * task_struct struct, and guest FPU contexts. While running a VCPU,
-        * the VCPU thread will have the guest FPU context.
+        * In vcpu_run, we switch between the user and guest FPU contexts.
+        * While running a VCPU, the VCPU thread will have the guest FPU
+        * context.
         *
         * Note that while the PKRU state lives inside the fpu registers,
         * it is switched out separately at VMENTER and VMEXIT time. The
         * "guest_fpu" state here contains the guest FPU context, with the
         * host PRKU bits.
         */
+       struct fpu *user_fpu;
        struct fpu *guest_fpu;
 
        u64 xcr0;
@@ -853,6 +857,7 @@ struct kvm_arch {
        unsigned long n_requested_mmu_pages;
        unsigned long n_max_mmu_pages;
        unsigned int indirect_shadow_pages;
+       unsigned long mmu_valid_gen;
        struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
        /*
         * Hash table of struct kvm_mmu_page.
@@ -1174,6 +1179,7 @@ struct kvm_x86_ops {
        int (*update_pi_irte)(struct kvm *kvm, unsigned int host_irq,
                              uint32_t guest_irq, bool set);
        void (*apicv_post_state_restore)(struct kvm_vcpu *vcpu);
+       bool (*dy_apicv_has_pending_interrupt)(struct kvm_vcpu *vcpu);
 
        int (*set_hv_timer)(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
                            bool *expired);
index 6b4fc2788078d7c5add77acd65af094cc1230543..271d837d69a8868118d811dabaa5739d482c2c0c 100644 (file)
 #define MSR_AMD64_PATCH_LEVEL          0x0000008b
 #define MSR_AMD64_TSC_RATIO            0xc0000104
 #define MSR_AMD64_NB_CFG               0xc001001f
+#define MSR_AMD64_CPUID_FN_1           0xc0011004
 #define MSR_AMD64_PATCH_LOADER         0xc0010020
 #define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
 #define MSR_AMD64_OSVW_STATUS          0xc0010141
index 109f974f983532041ab48e020e1fda9d5539f8f5..80bc209c07081b73dfab7c7632829db3d1e47bff 100644 (file)
        "       lfence;\n"                                      \
        "       jmp    902b;\n"                                 \
        "       .align 16\n"                                    \
-       "903:   addl   $4, %%esp;\n"                            \
+       "903:   lea    4(%%esp), %%esp;\n"                      \
        "       pushl  %[thunk_target];\n"                      \
        "       ret;\n"                                         \
        "       .align 16\n"                                    \
index 1392d5e6e8d671fe7d503646399c193dfce2dafa..ee26e9215f18745085ec2e9d13a807558c8de9c9 100644 (file)
@@ -252,16 +252,20 @@ struct pebs_lbr {
 #define IBSCTL_LVT_OFFSET_VALID                (1ULL<<8)
 #define IBSCTL_LVT_OFFSET_MASK         0x0F
 
-/* ibs fetch bits/masks */
+/* IBS fetch bits/masks */
 #define IBS_FETCH_RAND_EN      (1ULL<<57)
 #define IBS_FETCH_VAL          (1ULL<<49)
 #define IBS_FETCH_ENABLE       (1ULL<<48)
 #define IBS_FETCH_CNT          0xFFFF0000ULL
 #define IBS_FETCH_MAX_CNT      0x0000FFFFULL
 
-/* ibs op bits/masks */
-/* lower 4 bits of the current count are ignored: */
-#define IBS_OP_CUR_CNT         (0xFFFF0ULL<<32)
+/*
+ * IBS op bits/masks
+ * The lower 7 bits of the current count are random bits
+ * preloaded by hardware and ignored in software
+ */
+#define IBS_OP_CUR_CNT         (0xFFF80ULL<<32)
+#define IBS_OP_CUR_CNT_RAND    (0x0007FULL<<32)
 #define IBS_OP_CNT_CTL         (1ULL<<19)
 #define IBS_OP_VAL             (1ULL<<18)
 #define IBS_OP_ENABLE          (1ULL<<17)
index 9c4435307ff89b92dde662b5d0d4adb31cb9f220..35c225ede0e4fb55476c94b6055325a64486d534 100644 (file)
@@ -444,8 +444,10 @@ __pu_label:                                                        \
 ({                                                                     \
        int __gu_err;                                                   \
        __inttype(*(ptr)) __gu_val;                                     \
+       __typeof__(ptr) __gu_ptr = (ptr);                               \
+       __typeof__(size) __gu_size = (size);                            \
        __uaccess_begin_nospec();                                       \
-       __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT);    \
+       __get_user_size(__gu_val, __gu_ptr, __gu_size, __gu_err, -EFAULT);      \
        __uaccess_end();                                                \
        (x) = (__force __typeof__(*(ptr)))__gu_val;                     \
        __builtin_expect(__gu_err, 0);                                  \
index ae91429129a6411b8cd324f911ec1b5b57085365..ba71a63cdac479d6428159ffbb0e24ba6c5a40f3 100644 (file)
@@ -96,6 +96,8 @@ long clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 
 #else
 
+#define VDSO_HAS_32BIT_FALLBACK        1
+
 static __always_inline
 long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
@@ -113,6 +115,23 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
        return ret;
 }
 
+static __always_inline
+long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+       long ret;
+
+       asm (
+               "mov %%ebx, %%edx \n"
+               "mov %[clock], %%ebx \n"
+               "call __kernel_vsyscall \n"
+               "mov %%edx, %%ebx \n"
+               : "=a" (ret), "=m" (*_ts)
+               : "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts)
+               : "edx");
+
+       return ret;
+}
+
 static __always_inline
 long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
                           struct timezone *_tz)
@@ -148,6 +167,23 @@ clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
        return ret;
 }
 
+static __always_inline
+long clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+       long ret;
+
+       asm (
+               "mov %%ebx, %%edx \n"
+               "mov %[clock], %%ebx \n"
+               "call __kernel_vsyscall \n"
+               "mov %%edx, %%ebx \n"
+               : "=a" (ret), "=m" (*_ts)
+               : "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts)
+               : "edx");
+
+       return ret;
+}
+
 #endif
 
 #ifdef CONFIG_PARAVIRT_CLOCK
index 484e3cfd7ef2df9852f3af72e85072681841d5f6..149143cab9ff8ec6914fddc5fe43f6a061f29726 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _ASM_X86_BYTEORDER_H
 #define _ASM_X86_BYTEORDER_H
 
index 6ebaae90e207983d45fad59c8407ec682e85abab..8b2effe6efb82f0ac7e599a8ce8a1c5aa38bf6ec 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _ASM_X86_HWCAP2_H
 #define _ASM_X86_HWCAP2_H
 
index 6b18e88de8a613f4d7a90c1300e517716d210f22..7114801d04991aac97ec8f9e0e745676e2be027e 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _ASM_X86_SIGCONTEXT32_H
 #define _ASM_X86_SIGCONTEXT32_H
 
index df55e1ddb0c929b5b6b80e37917aff300efbbf4f..9d5c11a24279c62069fdfe347ae1260dc4aec9cc 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _ASM_X86_TYPES_H
 #define _ASM_X86_TYPES_H
 
index f5291362da1ad72877aa8d9f7bcf621a83e5c1f4..08fb79f377936c7725af66bf7bdeaf8f94c70c02 100644 (file)
@@ -722,7 +722,7 @@ static __initdata unsigned long lapic_cal_pm1, lapic_cal_pm2;
 static __initdata unsigned long lapic_cal_j1, lapic_cal_j2;
 
 /*
- * Temporary interrupt handler.
+ * Temporary interrupt handler and polled calibration function.
  */
 static void __init lapic_cal_handler(struct clock_event_device *dev)
 {
@@ -834,6 +834,10 @@ bool __init apic_needs_pit(void)
        if (!boot_cpu_has(X86_FEATURE_APIC))
                return true;
 
+       /* Virt guests may lack ARAT, but still have DEADLINE */
+       if (!boot_cpu_has(X86_FEATURE_ARAT))
+               return true;
+
        /* Deadline timer is based on TSC so no further PIT action required */
        if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
                return false;
@@ -851,7 +855,8 @@ bool __init apic_needs_pit(void)
 static int __init calibrate_APIC_clock(void)
 {
        struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
-       void (*real_handler)(struct clock_event_device *dev);
+       u64 tsc_perj = 0, tsc_start = 0;
+       unsigned long jif_start;
        unsigned long deltaj;
        long delta, deltatsc;
        int pm_referenced = 0;
@@ -878,28 +883,64 @@ static int __init calibrate_APIC_clock(void)
        apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
                    "calibrating APIC timer ...\n");
 
+       /*
+        * There are platforms w/o global clockevent devices. Instead of
+        * making the calibration conditional on that, use a polling based
+        * approach everywhere.
+        */
        local_irq_disable();
 
-       /* Replace the global interrupt handler */
-       real_handler = global_clock_event->event_handler;
-       global_clock_event->event_handler = lapic_cal_handler;
-
        /*
         * Setup the APIC counter to maximum. There is no way the lapic
         * can underflow in the 100ms detection time frame
         */
        __setup_APIC_LVTT(0xffffffff, 0, 0);
 
-       /* Let the interrupts run */
+       /*
+        * Methods to terminate the calibration loop:
+        *  1) Global clockevent if available (jiffies)
+        *  2) TSC if available and frequency is known
+        */
+       jif_start = READ_ONCE(jiffies);
+
+       if (tsc_khz) {
+               tsc_start = rdtsc();
+               tsc_perj = div_u64((u64)tsc_khz * 1000, HZ);
+       }
+
+       /*
+        * Enable interrupts so the tick can fire, if a global
+        * clockevent device is available
+        */
        local_irq_enable();
 
-       while (lapic_cal_loops <= LAPIC_CAL_LOOPS)
-               cpu_relax();
+       while (lapic_cal_loops <= LAPIC_CAL_LOOPS) {
+               /* Wait for a tick to elapse */
+               while (1) {
+                       if (tsc_khz) {
+                               u64 tsc_now = rdtsc();
+                               if ((tsc_now - tsc_start) >= tsc_perj) {
+                                       tsc_start += tsc_perj;
+                                       break;
+                               }
+                       } else {
+                               unsigned long jif_now = READ_ONCE(jiffies);
 
-       local_irq_disable();
+                               if (time_after(jif_now, jif_start)) {
+                                       jif_start = jif_now;
+                                       break;
+                               }
+                       }
+                       cpu_relax();
+               }
 
-       /* Restore the real event handler */
-       global_clock_event->event_handler = real_handler;
+               /* Invoke the calibration routine */
+               local_irq_disable();
+               lapic_cal_handler(NULL);
+               local_irq_enable();
+       }
+
+       local_irq_disable();
 
        /* Build delta t1-t2 as apic timer counts down */
        delta = lapic_cal_t1 - lapic_cal_t2;
@@ -943,10 +984,11 @@ static int __init calibrate_APIC_clock(void)
        levt->features &= ~CLOCK_EVT_FEAT_DUMMY;
 
        /*
-        * PM timer calibration failed or not turned on
-        * so lets try APIC timer based calibration
+        * PM timer calibration failed or not turned on so lets try APIC
+        * timer based calibration, if a global clockevent device is
+        * available.
         */
-       if (!pm_referenced) {
+       if (!pm_referenced && global_clock_event) {
                apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
 
                /*
index afee386ff711e95132dd5c01e79317ac22bd9a56..caedd8d60d3610b8b9bc11f5669de16521b3ac2a 100644 (file)
@@ -38,32 +38,12 @@ static int bigsmp_early_logical_apicid(int cpu)
        return early_per_cpu(x86_cpu_to_apicid, cpu);
 }
 
-static inline unsigned long calculate_ldr(int cpu)
-{
-       unsigned long val, id;
-
-       val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
-       id = per_cpu(x86_bios_cpu_apicid, cpu);
-       val |= SET_APIC_LOGICAL_ID(id);
-
-       return val;
-}
-
 /*
- * Set up the logical destination ID.
- *
- * Intel recommends to set DFR, LDR and TPR before enabling
- * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
- * document number 292116).  So here it goes...
+ * bigsmp enables physical destination mode
+ * and doesn't use LDR and DFR
  */
 static void bigsmp_init_apic_ldr(void)
 {
-       unsigned long val;
-       int cpu = smp_processor_id();
-
-       apic_write(APIC_DFR, APIC_DFR_FLAT);
-       val = calculate_ldr(cpu);
-       apic_write(APIC_LDR, val);
 }
 
 static void bigsmp_setup_apic_routing(void)
index c7bb6c69f21c98cbc24c9684820ee01122a5045b..d6af97fd170a98262a4618e613dd576f3e9f9f0b 100644 (file)
@@ -2438,7 +2438,13 @@ unsigned int arch_dynirq_lower_bound(unsigned int from)
         * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
         * gsi_top if ioapic_dynirq_base hasn't been initialized yet.
         */
-       return ioapic_initialized ? ioapic_dynirq_base : gsi_top;
+       if (!ioapic_initialized)
+               return gsi_top;
+       /*
+        * For DT enabled machines ioapic_dynirq_base is irrelevant and not
+        * updated. So simply return @from if ioapic_dynirq_base == 0.
+        */
+       return ioapic_dynirq_base ? : from;
 }
 
 #ifdef CONFIG_X86_32
index 1492799b8f43f93b3cc9c196893cfea1a5719a4f..ee2d91e382f1c576aead6dc28b719c5129c85a16 100644 (file)
@@ -184,7 +184,8 @@ void __init default_setup_apic_routing(void)
                                def_to_bigsmp = 0;
                                break;
                        }
-                       /* If P4 and above fall through */
+                       /* P4 and above */
+                       /* fall through */
                case X86_VENDOR_HYGON:
                case X86_VENDOR_AMD:
                        def_to_bigsmp = 1;
index 8d4e50428b684783310f5420dbe7d03751f9f464..68c363c341bf2a3794ec26f29df4dd28281d4dc5 100644 (file)
@@ -804,6 +804,64 @@ static void init_amd_ln(struct cpuinfo_x86 *c)
        msr_set_bit(MSR_AMD64_DE_CFG, 31);
 }
 
+static bool rdrand_force;
+
+static int __init rdrand_cmdline(char *str)
+{
+       if (!str)
+               return -EINVAL;
+
+       if (!strcmp(str, "force"))
+               rdrand_force = true;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+early_param("rdrand", rdrand_cmdline);
+
+static void clear_rdrand_cpuid_bit(struct cpuinfo_x86 *c)
+{
+       /*
+        * Saving of the MSR used to hide the RDRAND support during
+        * suspend/resume is done by arch/x86/power/cpu.c, which is
+        * dependent on CONFIG_PM_SLEEP.
+        */
+       if (!IS_ENABLED(CONFIG_PM_SLEEP))
+               return;
+
+       /*
+        * The nordrand option can clear X86_FEATURE_RDRAND, so check for
+        * RDRAND support using the CPUID function directly.
+        */
+       if (!(cpuid_ecx(1) & BIT(30)) || rdrand_force)
+               return;
+
+       msr_clear_bit(MSR_AMD64_CPUID_FN_1, 62);
+
+       /*
+        * Verify that the CPUID change has occurred in case the kernel is
+        * running virtualized and the hypervisor doesn't support the MSR.
+        */
+       if (cpuid_ecx(1) & BIT(30)) {
+               pr_info_once("BIOS may not properly restore RDRAND after suspend, but hypervisor does not support hiding RDRAND via CPUID.\n");
+               return;
+       }
+
+       clear_cpu_cap(c, X86_FEATURE_RDRAND);
+       pr_info_once("BIOS may not properly restore RDRAND after suspend, hiding RDRAND via CPUID. Use rdrand=force to reenable.\n");
+}
+
+static void init_amd_jg(struct cpuinfo_x86 *c)
+{
+       /*
+        * Some BIOS implementations do not restore proper RDRAND support
+        * across suspend and resume. Check on whether to hide the RDRAND
+        * instruction support via CPUID.
+        */
+       clear_rdrand_cpuid_bit(c);
+}
+
 static void init_amd_bd(struct cpuinfo_x86 *c)
 {
        u64 value;
@@ -818,6 +876,13 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
                        wrmsrl_safe(MSR_F15H_IC_CFG, value);
                }
        }
+
+       /*
+        * Some BIOS implementations do not restore proper RDRAND support
+        * across suspend and resume. Check on whether to hide the RDRAND
+        * instruction support via CPUID.
+        */
+       clear_rdrand_cpuid_bit(c);
 }
 
 static void init_amd_zn(struct cpuinfo_x86 *c)
@@ -860,6 +925,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 0x16: init_amd_jg(c); break;
        case 0x17: init_amd_zn(c); break;
        }
 
index 66ca906aa7909a094fc1dd88c57abaca4d8e9fae..c6fa3ef10b4ef2f400ac256973958b51861479db 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "cpu.h"
 
+static void __init spectre_v1_select_mitigation(void);
 static void __init spectre_v2_select_mitigation(void);
 static void __init ssb_select_mitigation(void);
 static void __init l1tf_select_mitigation(void);
@@ -98,17 +99,11 @@ void __init check_bugs(void)
        if (boot_cpu_has(X86_FEATURE_STIBP))
                x86_spec_ctrl_mask |= SPEC_CTRL_STIBP;
 
-       /* Select the proper spectre mitigation before patching alternatives */
+       /* Select the proper CPU mitigations before patching alternatives: */
+       spectre_v1_select_mitigation();
        spectre_v2_select_mitigation();
-
-       /*
-        * Select proper mitigation for any exposure to the Speculative Store
-        * Bypass vulnerability.
-        */
        ssb_select_mitigation();
-
        l1tf_select_mitigation();
-
        mds_select_mitigation();
 
        arch_smt_update();
@@ -273,6 +268,98 @@ static int __init mds_cmdline(char *str)
 }
 early_param("mds", mds_cmdline);
 
+#undef pr_fmt
+#define pr_fmt(fmt)     "Spectre V1 : " fmt
+
+enum spectre_v1_mitigation {
+       SPECTRE_V1_MITIGATION_NONE,
+       SPECTRE_V1_MITIGATION_AUTO,
+};
+
+static enum spectre_v1_mitigation spectre_v1_mitigation __ro_after_init =
+       SPECTRE_V1_MITIGATION_AUTO;
+
+static const char * const spectre_v1_strings[] = {
+       [SPECTRE_V1_MITIGATION_NONE] = "Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers",
+       [SPECTRE_V1_MITIGATION_AUTO] = "Mitigation: usercopy/swapgs barriers and __user pointer sanitization",
+};
+
+/*
+ * Does SMAP provide full mitigation against speculative kernel access to
+ * userspace?
+ */
+static bool smap_works_speculatively(void)
+{
+       if (!boot_cpu_has(X86_FEATURE_SMAP))
+               return false;
+
+       /*
+        * On CPUs which are vulnerable to Meltdown, SMAP does not
+        * prevent speculative access to user data in the L1 cache.
+        * Consider SMAP to be non-functional as a mitigation on these
+        * CPUs.
+        */
+       if (boot_cpu_has(X86_BUG_CPU_MELTDOWN))
+               return false;
+
+       return true;
+}
+
+static void __init spectre_v1_select_mitigation(void)
+{
+       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V1) || cpu_mitigations_off()) {
+               spectre_v1_mitigation = SPECTRE_V1_MITIGATION_NONE;
+               return;
+       }
+
+       if (spectre_v1_mitigation == SPECTRE_V1_MITIGATION_AUTO) {
+               /*
+                * With Spectre v1, a user can speculatively control either
+                * path of a conditional swapgs with a user-controlled GS
+                * value.  The mitigation is to add lfences to both code paths.
+                *
+                * If FSGSBASE is enabled, the user can put a kernel address in
+                * GS, in which case SMAP provides no protection.
+                *
+                * [ NOTE: Don't check for X86_FEATURE_FSGSBASE until the
+                *         FSGSBASE enablement patches have been merged. ]
+                *
+                * If FSGSBASE is disabled, the user can only put a user space
+                * address in GS.  That makes an attack harder, but still
+                * possible if there's no SMAP protection.
+                */
+               if (!smap_works_speculatively()) {
+                       /*
+                        * Mitigation can be provided from SWAPGS itself or
+                        * PTI as the CR3 write in the Meltdown mitigation
+                        * is serializing.
+                        *
+                        * If neither is there, mitigate with an LFENCE to
+                        * stop speculation through swapgs.
+                        */
+                       if (boot_cpu_has_bug(X86_BUG_SWAPGS) &&
+                           !boot_cpu_has(X86_FEATURE_PTI))
+                               setup_force_cpu_cap(X86_FEATURE_FENCE_SWAPGS_USER);
+
+                       /*
+                        * Enable lfences in the kernel entry (non-swapgs)
+                        * paths, to prevent user entry from speculatively
+                        * skipping swapgs.
+                        */
+                       setup_force_cpu_cap(X86_FEATURE_FENCE_SWAPGS_KERNEL);
+               }
+       }
+
+       pr_info("%s\n", spectre_v1_strings[spectre_v1_mitigation]);
+}
+
+static int __init nospectre_v1_cmdline(char *str)
+{
+       spectre_v1_mitigation = SPECTRE_V1_MITIGATION_NONE;
+       return 0;
+}
+early_param("nospectre_v1", nospectre_v1_cmdline);
+
 #undef pr_fmt
 #define pr_fmt(fmt)     "Spectre V2 : " fmt
 
@@ -1226,7 +1313,7 @@ static ssize_t l1tf_show_state(char *buf)
 
 static ssize_t mds_show_state(char *buf)
 {
-       if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
+       if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
                return sprintf(buf, "%s; SMT Host state unknown\n",
                               mds_strings[mds_mitigation]);
        }
@@ -1290,7 +1377,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
                break;
 
        case X86_BUG_SPECTRE_V1:
-               return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+               return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
 
        case X86_BUG_SPECTRE_V2:
                return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
index 11472178e17f5b45f6de5dfb20a8987cbba75a2f..f125bf7ecb6fbca590df390956f53b46d95aec48 100644 (file)
@@ -1022,6 +1022,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
 #define NO_L1TF                BIT(3)
 #define NO_MDS         BIT(4)
 #define MSBDS_ONLY     BIT(5)
+#define NO_SWAPGS      BIT(6)
 
 #define VULNWL(_vendor, _family, _model, _whitelist)   \
        { X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
@@ -1048,30 +1049,38 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
        VULNWL_INTEL(ATOM_BONNELL,              NO_SPECULATION),
        VULNWL_INTEL(ATOM_BONNELL_MID,          NO_SPECULATION),
 
-       VULNWL_INTEL(ATOM_SILVERMONT,           NO_SSB | NO_L1TF | MSBDS_ONLY),
-       VULNWL_INTEL(ATOM_SILVERMONT_X,         NO_SSB | NO_L1TF | MSBDS_ONLY),
-       VULNWL_INTEL(ATOM_SILVERMONT_MID,       NO_SSB | NO_L1TF | MSBDS_ONLY),
-       VULNWL_INTEL(ATOM_AIRMONT,              NO_SSB | NO_L1TF | MSBDS_ONLY),
-       VULNWL_INTEL(XEON_PHI_KNL,              NO_SSB | NO_L1TF | MSBDS_ONLY),
-       VULNWL_INTEL(XEON_PHI_KNM,              NO_SSB | NO_L1TF | MSBDS_ONLY),
+       VULNWL_INTEL(ATOM_SILVERMONT,           NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+       VULNWL_INTEL(ATOM_SILVERMONT_X,         NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+       VULNWL_INTEL(ATOM_SILVERMONT_MID,       NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+       VULNWL_INTEL(ATOM_AIRMONT,              NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+       VULNWL_INTEL(XEON_PHI_KNL,              NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
+       VULNWL_INTEL(XEON_PHI_KNM,              NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
 
        VULNWL_INTEL(CORE_YONAH,                NO_SSB),
 
-       VULNWL_INTEL(ATOM_AIRMONT_MID,          NO_L1TF | MSBDS_ONLY),
+       VULNWL_INTEL(ATOM_AIRMONT_MID,          NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
 
-       VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF),
-       VULNWL_INTEL(ATOM_GOLDMONT_X,           NO_MDS | NO_L1TF),
-       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF),
+       VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF | NO_SWAPGS),
+       VULNWL_INTEL(ATOM_GOLDMONT_X,           NO_MDS | NO_L1TF | NO_SWAPGS),
+       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF | NO_SWAPGS),
+
+       /*
+        * Technically, swapgs isn't serializing on AMD (despite it previously
+        * being documented as such in the APM).  But according to AMD, %gs is
+        * updated non-speculatively, and the issuing of %gs-relative memory
+        * operands will be blocked until the %gs update completes, which is
+        * good enough for our purposes.
+        */
 
        /* AMD Family 0xf - 0x12 */
-       VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
-       VULNWL_AMD(0x10,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
-       VULNWL_AMD(0x11,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
-       VULNWL_AMD(0x12,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
+       VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
+       VULNWL_AMD(0x10,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
+       VULNWL_AMD(0x11,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
+       VULNWL_AMD(0x12,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
 
        /* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
-       VULNWL_AMD(X86_FAMILY_ANY,      NO_MELTDOWN | NO_L1TF | NO_MDS),
-       VULNWL_HYGON(X86_FAMILY_ANY,    NO_MELTDOWN | NO_L1TF | NO_MDS),
+       VULNWL_AMD(X86_FAMILY_ANY,      NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
+       VULNWL_HYGON(X86_FAMILY_ANY,    NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
        {}
 };
 
@@ -1108,6 +1117,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
                        setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
        }
 
+       if (!cpu_matches(NO_SWAPGS))
+               setup_force_cpu_bug(X86_BUG_SWAPGS);
+
        if (cpu_matches(NO_MELTDOWN))
                return;
 
index 4296c702a3f71bdc33fa83081b5ea797a564980e..72182809b3339bc610c5c1fa23633ee236d66359 100644 (file)
@@ -98,6 +98,7 @@ cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg)
        case 7:
                if (size < 0x40)
                        break;
+               /* Else, fall through */
        case 6:
        case 5:
        case 4:
index 6a204e7336c12211de4de8fcf3ba1477f1d39160..32b4dc9030aa9fbcd482b39ef427b5804ec6499c 100644 (file)
  */
 static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
 
+/*
+ * Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
+ * hardware or BIOS before kernel boot.
+ */
+static u32 orig_umwait_control_cached __ro_after_init;
+
 /*
  * Serialize access to umwait_control_cached and IA32_UMWAIT_CONTROL MSR in
  * the sysfs write functions.
@@ -52,6 +58,23 @@ static int umwait_cpu_online(unsigned int cpu)
        return 0;
 }
 
+/*
+ * The CPU hotplug callback sets the control MSR to the original control
+ * value.
+ */
+static int umwait_cpu_offline(unsigned int cpu)
+{
+       /*
+        * This code is protected by the CPU hotplug already and
+        * orig_umwait_control_cached is never changed after it caches
+        * the original control MSR value in umwait_init(). So there
+        * is no race condition here.
+        */
+       wrmsr(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached, 0);
+
+       return 0;
+}
+
 /*
  * On resume, restore IA32_UMWAIT_CONTROL MSR on the boot processor which
  * is the only active CPU at this time. The MSR is set up on the APs via the
@@ -185,8 +208,22 @@ static int __init umwait_init(void)
        if (!boot_cpu_has(X86_FEATURE_WAITPKG))
                return -ENODEV;
 
+       /*
+        * Cache the original control MSR value before the control MSR is
+        * changed. This is the only place where orig_umwait_control_cached
+        * is modified.
+        */
+       rdmsrl(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached);
+
        ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "umwait:online",
-                               umwait_cpu_online, NULL);
+                               umwait_cpu_online, umwait_cpu_offline);
+       if (ret < 0) {
+               /*
+                * On failure, the control MSR on all CPUs has the
+                * original control value.
+                */
+               return ret;
+       }
 
        register_syscore_ops(&umwait_syscore_ops);
 
index a6342c899be596cccd6eff9663369e98c7eaafd0..f3d3e9646a99bafdc69257ecd1d2bcc5fae60067 100644 (file)
@@ -193,10 +193,10 @@ ENTRY(secondary_startup_64)
 
        /* Set up %gs.
         *
-        * The base of %gs always points to the bottom of the irqstack
-        * union.  If the stack protector canary is enabled, it is
-        * located at %gs:40.  Note that, on SMP, the boot cpu uses
-        * init data section till per cpu areas are set up.
+        * The base of %gs always points to fixed_percpu_data. If the
+        * stack protector canary is enabled, it is located at %gs:40.
+        * Note that, on SMP, the boot cpu uses init data section until
+        * the per cpu areas are set up.
         */
        movl    $MSR_GS_BASE,%ecx
        movl    initial_gs(%rip),%eax
index c43e96a938d0692343aaf16213d6d52a494007a9..c6f791bc481eb19d5fb4cb34989c2b485c82c038 100644 (file)
@@ -827,10 +827,6 @@ int __init hpet_enable(void)
        if (!hpet_cfg_working())
                goto out_nohpet;
 
-       /* Validate that the counter is counting */
-       if (!hpet_counting())
-               goto out_nohpet;
-
        /*
         * Read the period and check for a sane value:
         */
@@ -896,6 +892,14 @@ int __init hpet_enable(void)
        }
        hpet_print_config();
 
+       /*
+        * Validate that the counter is counting. This needs to be done
+        * after sanitizing the config registers to properly deal with
+        * force enabled HPETs.
+        */
+       if (!hpet_counting())
+               goto out_nohpet;
+
        clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 
        if (id & HPET_ID_LEGSUP) {
index b7f34fe2171e472f7f64bf7f93c9bdfcaefba710..4ab377c9fffede8af8c93b620bdb9d90803fd353 100644 (file)
@@ -308,9 +308,6 @@ static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val)
 
 static void kvm_guest_cpu_init(void)
 {
-       if (!kvm_para_available())
-               return;
-
        if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF) && kvmapf) {
                u64 pa = slow_virt_to_phys(this_cpu_ptr(&apf_reason));
 
@@ -625,9 +622,6 @@ static void __init kvm_guest_init(void)
 {
        int i;
 
-       if (!kvm_para_available())
-               return;
-
        paravirt_ops_setup();
        register_reboot_notifier(&kvm_pv_reboot_nb);
        for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++)
@@ -848,8 +842,6 @@ asm(
  */
 void __init kvm_spinlock_init(void)
 {
-       if (!kvm_para_available())
-               return;
        /* Does host kernel support KVM_FEATURE_PV_UNHALT? */
        if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
                return;
index 0fdbe89d0754058c6d61be12e42134b1a4359045..3c5bbe8e412087f15cf3280a43c921fe32f54e0a 100644 (file)
@@ -201,6 +201,7 @@ static int set_segment_reg(struct task_struct *task,
        case offsetof(struct user_regs_struct, ss):
                if (unlikely(value == 0))
                        return -EIO;
+               /* Else, fall through */
 
        default:
                *pt_regs_access(task_pt_regs(task), offset) = value;
index 4f36d3241faf46e08ecd479e815519d0dc2e074b..2d6898c2cb647505b9148d598bd8c2bfcab717ac 100644 (file)
@@ -100,7 +100,7 @@ copy_stack_frame(const void __user *fp, struct stack_frame_user *frame)
 {
        int ret;
 
-       if (!access_ok(fp, sizeof(*frame)))
+       if (__range_not_ok(fp, sizeof(*frame), TASK_SIZE))
                return 0;
 
        ret = 1;
index 8eb67a670b101ca147d6697625ec2eacf5ba02e6..653b7f617b61bfce19ccf0e0254462c00e18c5e5 100644 (file)
@@ -230,9 +230,55 @@ static const struct dmi_system_id efifb_dmi_system_table[] __initconst = {
        {},
 };
 
+/*
+ * Some devices have a portrait LCD but advertise a landscape resolution (and
+ * pitch). We simply swap width and height for these devices so that we can
+ * correctly deal with some of them coming with multiple resolutions.
+ */
+static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
+       {
+               /*
+                * Lenovo MIIX310-10ICR, only some batches have the troublesome
+                * 800x1280 portrait screen. Luckily the portrait version has
+                * its own BIOS version, so we match on that.
+                */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10ICR"),
+                       DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1HCN44WW"),
+               },
+       },
+       {
+               /* Lenovo MIIX 320-10ICR with 800x1280 portrait screen */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
+                                       "Lenovo MIIX 320-10ICR"),
+               },
+       },
+       {
+               /* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
+                                       "Lenovo ideapad D330-10IGM"),
+               },
+       },
+       {},
+};
+
 __init void sysfb_apply_efi_quirks(void)
 {
        if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
            !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
                dmi_check_system(efifb_dmi_system_table);
+
+       if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI &&
+           dmi_check_system(efifb_dmi_swap_width_height)) {
+               u16 temp = screen_info.lfb_width;
+
+               screen_info.lfb_width = screen_info.lfb_height;
+               screen_info.lfb_height = temp;
+               screen_info.lfb_linelength = 4 * screen_info.lfb_width;
+       }
 }
index d8359ebeea70c26bb7f621a3f8fea1ffb3fbb421..8cd745ef8c7b78662b561cb46e2d6c2beb388876 100644 (file)
@@ -508,9 +508,12 @@ struct uprobe_xol_ops {
        void    (*abort)(struct arch_uprobe *, struct pt_regs *);
 };
 
-static inline int sizeof_long(void)
+static inline int sizeof_long(struct pt_regs *regs)
 {
-       return in_ia32_syscall() ? 4 : 8;
+       /*
+        * Check registers for mode as in_xxx_syscall() does not apply here.
+        */
+       return user_64bit_mode(regs) ? 8 : 4;
 }
 
 static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
@@ -521,9 +524,9 @@ static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
 
 static int emulate_push_stack(struct pt_regs *regs, unsigned long val)
 {
-       unsigned long new_sp = regs->sp - sizeof_long();
+       unsigned long new_sp = regs->sp - sizeof_long(regs);
 
-       if (copy_to_user((void __user *)new_sp, &val, sizeof_long()))
+       if (copy_to_user((void __user *)new_sp, &val, sizeof_long(regs)))
                return -EFAULT;
 
        regs->sp = new_sp;
@@ -556,7 +559,7 @@ static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs
                long correction = utask->vaddr - utask->xol_vaddr;
                regs->ip += correction;
        } else if (auprobe->defparam.fixups & UPROBE_FIX_CALL) {
-               regs->sp += sizeof_long(); /* Pop incorrect return address */
+               regs->sp += sizeof_long(regs); /* Pop incorrect return address */
                if (emulate_push_stack(regs, utask->vaddr + auprobe->defparam.ilen))
                        return -ERESTART;
        }
@@ -675,7 +678,7 @@ static int branch_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
         * "call" insn was executed out-of-line. Just restore ->sp and restart.
         * We could also restore ->ip and try to call branch_emulate_op() again.
         */
-       regs->sp += sizeof_long();
+       regs->sp += sizeof_long(regs);
        return -ERESTART;
 }
 
@@ -1056,7 +1059,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 unsigned long
 arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs)
 {
-       int rasize = sizeof_long(), nleft;
+       int rasize = sizeof_long(regs), nleft;
        unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
 
        if (copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize))
index 329361b69d5e38fbb598fd40b652112f92057ac8..018aebce33ff407f764d17151c3d3647e8014263 100644 (file)
@@ -8,11 +8,6 @@
 #include <linux/debugfs.h>
 #include "lapic.h"
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return true;
-}
-
 static int vcpu_get_timer_advance_ns(void *data, u64 *val)
 {
        struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
@@ -48,37 +43,22 @@ static int vcpu_get_tsc_scaling_frac_bits(void *data, u64 *val)
 
 DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_frac_fops, vcpu_get_tsc_scaling_frac_bits, NULL, "%llu\n");
 
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
+void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
 {
-       struct dentry *ret;
-
-       ret = debugfs_create_file("tsc-offset", 0444,
-                                                       vcpu->debugfs_dentry,
-                                                       vcpu, &vcpu_tsc_offset_fops);
-       if (!ret)
-               return -ENOMEM;
+       debugfs_create_file("tsc-offset", 0444, vcpu->debugfs_dentry, vcpu,
+                           &vcpu_tsc_offset_fops);
 
-       if (lapic_in_kernel(vcpu)) {
-               ret = debugfs_create_file("lapic_timer_advance_ns", 0444,
-                                                               vcpu->debugfs_dentry,
-                                                               vcpu, &vcpu_timer_advance_ns_fops);
-               if (!ret)
-                       return -ENOMEM;
-       }
+       if (lapic_in_kernel(vcpu))
+               debugfs_create_file("lapic_timer_advance_ns", 0444,
+                                   vcpu->debugfs_dentry, vcpu,
+                                   &vcpu_timer_advance_ns_fops);
 
        if (kvm_has_tsc_control) {
-               ret = debugfs_create_file("tsc-scaling-ratio", 0444,
-                                                       vcpu->debugfs_dentry,
-                                                       vcpu, &vcpu_tsc_scaling_fops);
-               if (!ret)
-                       return -ENOMEM;
-               ret = debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444,
-                                                       vcpu->debugfs_dentry,
-                                                       vcpu, &vcpu_tsc_scaling_frac_fops);
-               if (!ret)
-                       return -ENOMEM;
-
+               debugfs_create_file("tsc-scaling-ratio", 0444,
+                                   vcpu->debugfs_dentry, vcpu,
+                                   &vcpu_tsc_scaling_fops);
+               debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444,
+                                   vcpu->debugfs_dentry, vcpu,
+                                   &vcpu_tsc_scaling_frac_fops);
        }
-
-       return 0;
 }
index c10a8b10b203b706ce2b84b28e45fa0042bb1d77..fff790a3f4ee9484606d4d6aa1614715fe01ad4e 100644 (file)
@@ -1781,7 +1781,7 @@ int kvm_vm_ioctl_hv_eventfd(struct kvm *kvm, struct kvm_hyperv_eventfd *args)
 int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
                                struct kvm_cpuid_entry2 __user *entries)
 {
-       uint16_t evmcs_ver = kvm_x86_ops->nested_get_evmcs_version(vcpu);
+       uint16_t evmcs_ver = 0;
        struct kvm_cpuid_entry2 cpuid_entries[] = {
                { .function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS },
                { .function = HYPERV_CPUID_INTERFACE },
@@ -1793,6 +1793,9 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
        };
        int i, nent = ARRAY_SIZE(cpuid_entries);
 
+       if (kvm_x86_ops->nested_get_evmcs_version)
+               evmcs_ver = kvm_x86_ops->nested_get_evmcs_version(vcpu);
+
        /* Skip NESTED_FEATURES if eVMCS is not supported */
        if (!evmcs_ver)
                --nent;
index 0aa158657f20cff83270f4251d1294030076c1bb..e904ff06a83d84c9ab5ccd08bdfcc14b1cc3768a 100644 (file)
@@ -216,6 +216,9 @@ static void recalculate_apic_map(struct kvm *kvm)
                if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id])
                        new->phys_map[xapic_id] = apic;
 
+               if (!kvm_apic_sw_enabled(apic))
+                       continue;
+
                ldr = kvm_lapic_get_reg(apic, APIC_LDR);
 
                if (apic_x2apic_mode(apic)) {
@@ -258,6 +261,8 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
                        static_key_slow_dec_deferred(&apic_sw_disabled);
                else
                        static_key_slow_inc(&apic_sw_disabled.key);
+
+               recalculate_apic_map(apic->vcpu->kvm);
        }
 }
 
@@ -1548,7 +1553,6 @@ static void kvm_apic_inject_pending_timer_irqs(struct kvm_lapic *apic)
 static void apic_timer_expired(struct kvm_lapic *apic)
 {
        struct kvm_vcpu *vcpu = apic->vcpu;
-       struct swait_queue_head *q = &vcpu->wq;
        struct kvm_timer *ktimer = &apic->lapic_timer;
 
        if (atomic_read(&apic->lapic_timer.pending))
@@ -1566,13 +1570,6 @@ static void apic_timer_expired(struct kvm_lapic *apic)
 
        atomic_inc(&apic->lapic_timer.pending);
        kvm_set_pending_timer(vcpu);
-
-       /*
-        * For x86, the atomic_inc() is serialized, thus
-        * using swait_active() is safe.
-        */
-       if (swait_active(q))
-               swake_up_one(q);
 }
 
 static void start_sw_tscdeadline(struct kvm_lapic *apic)
index 8f72526e2f68140b49f0e122aba18eaef3bbf335..a63964e7cec7bdd67f2b1886adefe98f03972185 100644 (file)
@@ -2095,6 +2095,12 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, int direct
        if (!direct)
                sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache);
        set_page_private(virt_to_page(sp->spt), (unsigned long)sp);
+
+       /*
+        * active_mmu_pages must be a FIFO list, as kvm_zap_obsolete_pages()
+        * depends on valid pages being added to the head of the list.  See
+        * comments in kvm_zap_obsolete_pages().
+        */
        list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages);
        kvm_mod_used_mmu_pages(vcpu->kvm, +1);
        return sp;
@@ -2244,7 +2250,7 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
 #define for_each_valid_sp(_kvm, _sp, _gfn)                             \
        hlist_for_each_entry(_sp,                                       \
          &(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)], hash_link) \
-               if ((_sp)->role.invalid) {    \
+               if (is_obsolete_sp((_kvm), (_sp)) || (_sp)->role.invalid) {    \
                } else
 
 #define for_each_gfn_indirect_valid_sp(_kvm, _sp, _gfn)                        \
@@ -2301,6 +2307,11 @@ static void kvm_mmu_audit(struct kvm_vcpu *vcpu, int point) { }
 static void mmu_audit_disable(void) { }
 #endif
 
+static bool is_obsolete_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
+{
+       return unlikely(sp->mmu_valid_gen != kvm->arch.mmu_valid_gen);
+}
+
 static bool kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
                         struct list_head *invalid_list)
 {
@@ -2525,6 +2536,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
                if (level > PT_PAGE_TABLE_LEVEL && need_sync)
                        flush |= kvm_sync_pages(vcpu, gfn, &invalid_list);
        }
+       sp->mmu_valid_gen = vcpu->kvm->arch.mmu_valid_gen;
        clear_page(sp->spt);
        trace_kvm_mmu_get_page(sp, true);
 
@@ -3466,7 +3478,7 @@ static bool fast_page_fault(struct kvm_vcpu *vcpu, gva_t gva, int level,
                /*
                 * Currently, fast page fault only works for direct mapping
                 * since the gfn is not stable for indirect shadow page. See
-                * Documentation/virtual/kvm/locking.txt to get more detail.
+                * Documentation/virt/kvm/locking.txt to get more detail.
                 */
                fault_handled = fast_pf_fix_direct_spte(vcpu, sp,
                                                        iterator.sptep, spte,
@@ -4233,6 +4245,13 @@ static bool fast_cr3_switch(struct kvm_vcpu *vcpu, gpa_t new_cr3,
                        return false;
 
                if (cached_root_available(vcpu, new_cr3, new_role)) {
+                       /*
+                        * It is possible that the cached previous root page is
+                        * obsolete because of a change in the MMU generation
+                        * number. However, changing the generation number is
+                        * accompanied by KVM_REQ_MMU_RELOAD, which will free
+                        * the root set here and allocate a new one.
+                        */
                        kvm_make_request(KVM_REQ_LOAD_CR3, vcpu);
                        if (!skip_tlb_flush) {
                                kvm_make_request(KVM_REQ_MMU_SYNC, vcpu);
@@ -5649,44 +5668,91 @@ int kvm_mmu_create(struct kvm_vcpu *vcpu)
        return alloc_mmu_pages(vcpu);
 }
 
-static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
-                       struct kvm_memory_slot *slot,
-                       struct kvm_page_track_notifier_node *node)
+
+static void kvm_zap_obsolete_pages(struct kvm *kvm)
 {
-       struct kvm_mmu_page *sp;
+       struct kvm_mmu_page *sp, *node;
        LIST_HEAD(invalid_list);
-       unsigned long i;
-       bool flush;
-       gfn_t gfn;
-
-       spin_lock(&kvm->mmu_lock);
-
-       if (list_empty(&kvm->arch.active_mmu_pages))
-               goto out_unlock;
-
-       flush = slot_handle_all_level(kvm, slot, kvm_zap_rmapp, false);
+       int ign;
 
-       for (i = 0; i < slot->npages; i++) {
-               gfn = slot->base_gfn + i;
+restart:
+       list_for_each_entry_safe_reverse(sp, node,
+             &kvm->arch.active_mmu_pages, link) {
+               /*
+                * No obsolete valid page exists before a newly created page
+                * since active_mmu_pages is a FIFO list.
+                */
+               if (!is_obsolete_sp(kvm, sp))
+                       break;
 
-               for_each_valid_sp(kvm, sp, gfn) {
-                       if (sp->gfn != gfn)
-                               continue;
+               /*
+                * Do not repeatedly zap a root page to avoid unnecessary
+                * KVM_REQ_MMU_RELOAD, otherwise we may not be able to
+                * progress:
+                *    vcpu 0                        vcpu 1
+                *                         call vcpu_enter_guest():
+                *                            1): handle KVM_REQ_MMU_RELOAD
+                *                                and require mmu-lock to
+                *                                load mmu
+                * repeat:
+                *    1): zap root page and
+                *        send KVM_REQ_MMU_RELOAD
+                *
+                *    2): if (cond_resched_lock(mmu-lock))
+                *
+                *                            2): hold mmu-lock and load mmu
+                *
+                *                            3): see KVM_REQ_MMU_RELOAD bit
+                *                                on vcpu->requests is set
+                *                                then return 1 to call
+                *                                vcpu_enter_guest() again.
+                *            goto repeat;
+                *
+                * Since we are reversely walking the list and the invalid
+                * list will be moved to the head, skip the invalid page
+                * can help us to avoid the infinity list walking.
+                */
+               if (sp->role.invalid)
+                       continue;
 
-                       kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list);
-               }
                if (need_resched() || spin_needbreak(&kvm->mmu_lock)) {
-                       kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
-                       flush = false;
+                       kvm_mmu_commit_zap_page(kvm, &invalid_list);
                        cond_resched_lock(&kvm->mmu_lock);
+                       goto restart;
                }
+
+               if (__kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list, &ign))
+                       goto restart;
        }
-       kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
 
-out_unlock:
+       kvm_mmu_commit_zap_page(kvm, &invalid_list);
+}
+
+/*
+ * Fast invalidate all shadow pages and use lock-break technique
+ * to zap obsolete pages.
+ *
+ * It's required when memslot is being deleted or VM is being
+ * destroyed, in these cases, we should ensure that KVM MMU does
+ * not use any resource of the being-deleted slot or all slots
+ * after calling the function.
+ */
+static void kvm_mmu_zap_all_fast(struct kvm *kvm)
+{
+       spin_lock(&kvm->mmu_lock);
+       kvm->arch.mmu_valid_gen++;
+
+       kvm_zap_obsolete_pages(kvm);
        spin_unlock(&kvm->mmu_lock);
 }
 
+static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
+                       struct kvm_memory_slot *slot,
+                       struct kvm_page_track_notifier_node *node)
+{
+       kvm_mmu_zap_all_fast(kvm);
+}
+
 void kvm_mmu_init_vm(struct kvm *kvm)
 {
        struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
index 19f69df9675869295764ae3a04bc1c0a5df0ff00..e0368076a1ef90660a460bf64f56bfa7b549fd2c 100644 (file)
@@ -1714,7 +1714,6 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
        if (!entry)
                return -EINVAL;
 
-       new_entry = READ_ONCE(*entry);
        new_entry = __sme_set((page_to_phys(svm->avic_backing_page) &
                              AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK) |
                              AVIC_PHYSICAL_ID_ENTRY_VALID_MASK);
@@ -2143,12 +2142,20 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
                goto out;
        }
 
+       svm->vcpu.arch.user_fpu = kmem_cache_zalloc(x86_fpu_cache,
+                                                    GFP_KERNEL_ACCOUNT);
+       if (!svm->vcpu.arch.user_fpu) {
+               printk(KERN_ERR "kvm: failed to allocate kvm userspace's fpu\n");
+               err = -ENOMEM;
+               goto free_partial_svm;
+       }
+
        svm->vcpu.arch.guest_fpu = kmem_cache_zalloc(x86_fpu_cache,
                                                     GFP_KERNEL_ACCOUNT);
        if (!svm->vcpu.arch.guest_fpu) {
                printk(KERN_ERR "kvm: failed to allocate vcpu's fpu\n");
                err = -ENOMEM;
-               goto free_partial_svm;
+               goto free_user_fpu;
        }
 
        err = kvm_vcpu_init(&svm->vcpu, kvm, id);
@@ -2211,6 +2218,8 @@ uninit:
        kvm_vcpu_uninit(&svm->vcpu);
 free_svm:
        kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.guest_fpu);
+free_user_fpu:
+       kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.user_fpu);
 free_partial_svm:
        kmem_cache_free(kvm_vcpu_cache, svm);
 out:
@@ -2241,6 +2250,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
        __free_page(virt_to_page(svm->nested.hsave));
        __free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER);
        kvm_vcpu_uninit(vcpu);
+       kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.user_fpu);
        kmem_cache_free(x86_fpu_cache, svm->vcpu.arch.guest_fpu);
        kmem_cache_free(kvm_vcpu_cache, svm);
 }
@@ -5179,6 +5189,11 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
                kvm_vcpu_wake_up(vcpu);
 }
 
+static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
+{
+       return false;
+}
+
 static void svm_ir_list_del(struct vcpu_svm *svm, struct amd_iommu_pi_data *pi)
 {
        unsigned long flags;
@@ -7113,12 +7128,6 @@ failed:
        return ret;
 }
 
-static uint16_t nested_get_evmcs_version(struct kvm_vcpu *vcpu)
-{
-       /* Not supported */
-       return 0;
-}
-
 static int nested_enable_evmcs(struct kvm_vcpu *vcpu,
                                   uint16_t *vmcs_version)
 {
@@ -7303,6 +7312,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
 
        .pmu_ops = &amd_pmu_ops,
        .deliver_posted_interrupt = svm_deliver_avic_intr,
+       .dy_apicv_has_pending_interrupt = svm_dy_apicv_has_pending_interrupt,
        .update_pi_irte = svm_update_pi_irte,
        .setup_mce = svm_setup_mce,
 
@@ -7316,7 +7326,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .mem_enc_unreg_region = svm_unregister_enc_region,
 
        .nested_enable_evmcs = nested_enable_evmcs,
-       .nested_get_evmcs_version = nested_get_evmcs_version,
+       .nested_get_evmcs_version = NULL,
 
        .need_emulation_on_page_fault = svm_need_emulation_on_page_fault,
 };
index 0f1378789bd0381e95c703ad658376efa3484d8d..a3cba321b5c5ddb7b2730835c01635c0307e1bb1 100644 (file)
@@ -220,6 +220,8 @@ static void free_nested(struct kvm_vcpu *vcpu)
        if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon)
                return;
 
+       kvm_clear_request(KVM_REQ_GET_VMCS12_PAGES, vcpu);
+
        vmx->nested.vmxon = false;
        vmx->nested.smm.vmxon = false;
        free_vpid(vmx->nested.vpid02);
@@ -232,7 +234,9 @@ static void free_nested(struct kvm_vcpu *vcpu)
                vmx->vmcs01.shadow_vmcs = NULL;
        }
        kfree(vmx->nested.cached_vmcs12);
+       vmx->nested.cached_vmcs12 = NULL;
        kfree(vmx->nested.cached_shadow_vmcs12);
+       vmx->nested.cached_shadow_vmcs12 = NULL;
        /* Unpin physical memory we referred to in the vmcs02 */
        if (vmx->nested.apic_access_page) {
                kvm_release_page_dirty(vmx->nested.apic_access_page);
@@ -4536,6 +4540,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
        int len;
        gva_t gva = 0;
        struct vmcs12 *vmcs12;
+       struct x86_exception e;
        short offset;
 
        if (!nested_vmx_check_permission(vcpu))
@@ -4584,7 +4589,8 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
                                vmx_instruction_info, true, len, &gva))
                        return 1;
                /* _system ok, nested_vmx_check_permission has verified cpl=0 */
-               kvm_write_guest_virt_system(vcpu, gva, &field_value, len, NULL);
+               if (kvm_write_guest_virt_system(vcpu, gva, &field_value, len, &e))
+                       kvm_inject_page_fault(vcpu, &e);
        }
 
        return nested_vmx_succeed(vcpu);
index a279447eb75b6172ac470cd95e84b3e56f92ac90..c030c96fc81a817f6e11e3b1580aa907b8bc63f7 100644 (file)
@@ -6117,6 +6117,11 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
        return max_irr;
 }
 
+static bool vmx_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
+{
+       return pi_test_on(vcpu_to_pi_desc(vcpu));
+}
+
 static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
 {
        if (!kvm_vcpu_apicv_active(vcpu))
@@ -6598,6 +6603,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
        free_loaded_vmcs(vmx->loaded_vmcs);
        kfree(vmx->guest_msrs);
        kvm_vcpu_uninit(vcpu);
+       kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.user_fpu);
        kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.guest_fpu);
        kmem_cache_free(kvm_vcpu_cache, vmx);
 }
@@ -6613,12 +6619,20 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
        if (!vmx)
                return ERR_PTR(-ENOMEM);
 
+       vmx->vcpu.arch.user_fpu = kmem_cache_zalloc(x86_fpu_cache,
+                       GFP_KERNEL_ACCOUNT);
+       if (!vmx->vcpu.arch.user_fpu) {
+               printk(KERN_ERR "kvm: failed to allocate kvm userspace's fpu\n");
+               err = -ENOMEM;
+               goto free_partial_vcpu;
+       }
+
        vmx->vcpu.arch.guest_fpu = kmem_cache_zalloc(x86_fpu_cache,
                        GFP_KERNEL_ACCOUNT);
        if (!vmx->vcpu.arch.guest_fpu) {
                printk(KERN_ERR "kvm: failed to allocate vcpu's fpu\n");
                err = -ENOMEM;
-               goto free_partial_vcpu;
+               goto free_user_fpu;
        }
 
        vmx->vpid = allocate_vpid();
@@ -6721,6 +6735,8 @@ uninit_vcpu:
 free_vcpu:
        free_vpid(vmx->vpid);
        kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.guest_fpu);
+free_user_fpu:
+       kmem_cache_free(x86_fpu_cache, vmx->vcpu.arch.user_fpu);
 free_partial_vcpu:
        kmem_cache_free(kvm_vcpu_cache, vmx);
        return ERR_PTR(err);
@@ -7715,6 +7731,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
        .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
        .sync_pir_to_irr = vmx_sync_pir_to_irr,
        .deliver_posted_interrupt = vmx_deliver_posted_interrupt,
+       .dy_apicv_has_pending_interrupt = vmx_dy_apicv_has_pending_interrupt,
 
        .set_tss_addr = vmx_set_tss_addr,
        .set_identity_map_addr = vmx_set_identity_map_addr,
@@ -7780,6 +7797,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
        .set_nested_state = NULL,
        .get_vmcs12_pages = NULL,
        .nested_enable_evmcs = NULL,
+       .nested_get_evmcs_version = NULL,
        .need_emulation_on_page_fault = vmx_need_emulation_on_page_fault,
 };
 
index 58305cf81182dab02a0a45f5efa85990d2e239b4..91602d310a3fbf0be916d794d0eff9c3beb1b9b2 100644 (file)
@@ -3306,6 +3306,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
        kvm_x86_ops->vcpu_load(vcpu, cpu);
 
+       fpregs_assert_state_consistent();
+       if (test_thread_flag(TIF_NEED_FPU_LOAD))
+               switch_fpu_return();
+
        /* Apply any externally detected TSC adjustments (due to suspend) */
        if (unlikely(vcpu->arch.tsc_offset_adjustment)) {
                adjust_tsc_offset_host(vcpu, vcpu->arch.tsc_offset_adjustment);
@@ -5308,6 +5312,13 @@ int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val,
        /* kvm_write_guest_virt_system can pull in tons of pages. */
        vcpu->arch.l1tf_flush_l1d = true;
 
+       /*
+        * FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED
+        * is returned, but our callers are not ready for that and they blindly
+        * call kvm_inject_page_fault.  Ensure that they at least do not leak
+        * uninitialized kernel stack memory into cr2 and error code.
+        */
+       memset(exception, 0, sizeof(*exception));
        return kvm_write_guest_virt_helper(addr, val, bytes, vcpu,
                                           PFERR_WRITE_MASK, exception);
 }
@@ -6590,12 +6601,13 @@ restart:
                unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
                toggle_interruptibility(vcpu, ctxt->interruptibility);
                vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
-               kvm_rip_write(vcpu, ctxt->eip);
-               if (r == EMULATE_DONE && ctxt->tf)
-                       kvm_vcpu_do_singlestep(vcpu, &r);
                if (!ctxt->have_exception ||
-                   exception_type(ctxt->exception.vector) == EXCPT_TRAP)
+                   exception_type(ctxt->exception.vector) == EXCPT_TRAP) {
+                       kvm_rip_write(vcpu, ctxt->eip);
+                       if (r == EMULATE_DONE && ctxt->tf)
+                               kvm_vcpu_do_singlestep(vcpu, &r);
                        __kvm_set_rflags(vcpu, ctxt->eflags);
+               }
 
                /*
                 * For STI, interrupts are shadowed; so KVM_REQ_EVENT will
@@ -7202,7 +7214,7 @@ static void kvm_sched_yield(struct kvm *kvm, unsigned long dest_id)
 
        rcu_read_unlock();
 
-       if (target)
+       if (target && READ_ONCE(target->ready))
                kvm_vcpu_yield_to(target);
 }
 
@@ -7242,6 +7254,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
                break;
        case KVM_HC_KICK_CPU:
                kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1);
+               kvm_sched_yield(vcpu->kvm, a1);
                ret = 0;
                break;
 #ifdef CONFIG_X86_64
@@ -7990,9 +8003,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
        trace_kvm_entry(vcpu->vcpu_id);
        guest_enter_irqoff();
 
-       fpregs_assert_state_consistent();
-       if (test_thread_flag(TIF_NEED_FPU_LOAD))
-               switch_fpu_return();
+       /* The preempt notifier should have taken care of the FPU already.  */
+       WARN_ON_ONCE(test_thread_flag(TIF_NEED_FPU_LOAD));
 
        if (unlikely(vcpu->arch.switch_db_regs)) {
                set_debugreg(0, 7);
@@ -8270,7 +8282,7 @@ static void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
 {
        fpregs_lock();
 
-       copy_fpregs_to_fpstate(&current->thread.fpu);
+       copy_fpregs_to_fpstate(vcpu->arch.user_fpu);
        /* PKRU is separately restored in kvm_x86_ops->run.  */
        __copy_kernel_to_fpregs(&vcpu->arch.guest_fpu->state,
                                ~XFEATURE_MASK_PKRU);
@@ -8287,7 +8299,7 @@ static void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
        fpregs_lock();
 
        copy_fpregs_to_fpstate(vcpu->arch.guest_fpu);
-       copy_kernel_to_fpregs(&current->thread.fpu.state);
+       copy_kernel_to_fpregs(&vcpu->arch.user_fpu->state);
 
        fpregs_mark_activate();
        fpregs_unlock();
@@ -9694,6 +9706,22 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
        return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu);
 }
 
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+       if (READ_ONCE(vcpu->arch.pv.pv_unhalted))
+               return true;
+
+       if (kvm_test_request(KVM_REQ_NMI, vcpu) ||
+               kvm_test_request(KVM_REQ_SMI, vcpu) ||
+                kvm_test_request(KVM_REQ_EVENT, vcpu))
+               return true;
+
+       if (vcpu->arch.apicv_active && kvm_x86_ops->dy_apicv_has_pending_interrupt(vcpu))
+               return true;
+
+       return false;
+}
+
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.preempted_in_kernel;
index 04967cdce5d12c97441c030405a90a7f2e79e1fa..7ad68917a51e8e123eb19b0d5d3956870aee56ed 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <linux/types.h>
 #include <linux/export.h>
+#include <asm/cpu.h>
 
 unsigned int x86_family(unsigned int sig)
 {
index 6b468517ab7167fcffd0fed7f4f0134e71f70b50..73dc66d887f354a78d9e48efcee214be22cb866a 100644 (file)
@@ -178,13 +178,15 @@ void FPU_printall(void)
        for (i = 0; i < 8; i++) {
                FPU_REG *r = &st(i);
                u_char tagi = FPU_gettagi(i);
+
                switch (tagi) {
                case TAG_Empty:
                        continue;
-                       break;
                case TAG_Zero:
                case TAG_Special:
+                       /* Update tagi for the printk below */
                        tagi = FPU_Special(r);
+                       /* fall through */
                case TAG_Valid:
                        printk("st(%d)  %c .%04lx %04lx %04lx %04lx e%+-6d ", i,
                               getsign(r) ? '-' : '+',
@@ -198,7 +200,6 @@ void FPU_printall(void)
                        printk("Whoops! Error in errors.c: tag%d is %d ", i,
                               tagi);
                        continue;
-                       break;
                }
                printk("%s\n", tag_desc[(int)(unsigned)tagi]);
        }
index 783c509f957a6975401d5c9a5693468f5027d57e..127ea54122d75f48b97633cfa96b589ada8f5f19 100644 (file)
@@ -1352,7 +1352,7 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
                case TW_Denormal:
                        if (denormal_operand() < 0)
                                return;
-
+                       /* fall through */
                case TAG_Zero:
                case TAG_Valid:
                        setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));
index 6c46095cd0d95297bb6e894a06b837ada471f320..9ceacd1156dbc06c801f86c66e9aa79d104a0cde 100644 (file)
@@ -177,13 +177,14 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
 
        pmd = pmd_offset(pud, address);
        pmd_k = pmd_offset(pud_k, address);
-       if (!pmd_present(*pmd_k))
-               return NULL;
 
-       if (!pmd_present(*pmd))
+       if (pmd_present(*pmd) != pmd_present(*pmd_k))
                set_pmd(pmd, *pmd_k);
+
+       if (!pmd_present(*pmd_k))
+               return NULL;
        else
-               BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+               BUG_ON(pmd_pfn(*pmd) != pmd_pfn(*pmd_k));
 
        return pmd_k;
 }
@@ -203,17 +204,13 @@ void vmalloc_sync_all(void)
                spin_lock(&pgd_lock);
                list_for_each_entry(page, &pgd_list, lru) {
                        spinlock_t *pgt_lock;
-                       pmd_t *ret;
 
                        /* the pgt_lock only for Xen */
                        pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
 
                        spin_lock(pgt_lock);
-                       ret = vmalloc_sync_one(page_address(page), address);
+                       vmalloc_sync_one(page_address(page), address);
                        spin_unlock(pgt_lock);
-
-                       if (!ret)
-                               break;
                }
                spin_unlock(&pgd_lock);
        }
index 6a9a77a403c928e642a754f68c168ebfa6f7b3c1..e14e95ea7338a3adaf013acb7cd848d909f4dd95 100644 (file)
@@ -516,7 +516,7 @@ static inline void check_conflict(int warnlvl, pgprot_t prot, pgprotval_t val,
  */
 static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
                                          unsigned long pfn, unsigned long npg,
-                                         int warnlvl)
+                                         unsigned long lpsize, int warnlvl)
 {
        pgprotval_t forbidden, res;
        unsigned long end;
@@ -535,9 +535,17 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
        check_conflict(warnlvl, prot, res, start, end, pfn, "Text NX");
        forbidden = res;
 
-       res = protect_kernel_text_ro(start, end);
-       check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO");
-       forbidden |= res;
+       /*
+        * Special case to preserve a large page. If the change spawns the
+        * full large page mapping then there is no point to split it
+        * up. Happens with ftrace and is going to be removed once ftrace
+        * switched to text_poke().
+        */
+       if (lpsize != (npg * PAGE_SIZE) || (start & (lpsize - 1))) {
+               res = protect_kernel_text_ro(start, end);
+               check_conflict(warnlvl, prot, res, start, end, pfn, "Text RO");
+               forbidden |= res;
+       }
 
        /* Check the PFN directly */
        res = protect_pci_bios(pfn, pfn + npg - 1);
@@ -819,7 +827,7 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
         * extra conditional required here.
         */
        chk_prot = static_protections(old_prot, lpaddr, old_pfn, numpages,
-                                     CPA_CONFLICT);
+                                     psize, CPA_CONFLICT);
 
        if (WARN_ON_ONCE(pgprot_val(chk_prot) != pgprot_val(old_prot))) {
                /*
@@ -855,7 +863,7 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
         * protection requirement in the large page.
         */
        new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages,
-                                     CPA_DETECT);
+                                     psize, CPA_DETECT);
 
        /*
         * If there is a conflict, split the large page.
@@ -906,7 +914,8 @@ static void split_set_pte(struct cpa_data *cpa, pte_t *pte, unsigned long pfn,
        if (!cpa->force_static_prot)
                goto set;
 
-       prot = static_protections(ref_prot, address, pfn, npg, CPA_PROTECT);
+       /* Hand in lpsize = 0 to enforce the protection mechanism */
+       prot = static_protections(ref_prot, address, pfn, npg, 0, CPA_PROTECT);
 
        if (pgprot_val(prot) == pgprot_val(ref_prot))
                goto set;
@@ -1503,7 +1512,8 @@ repeat:
                pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
 
                cpa_inc_4k_install();
-               new_prot = static_protections(new_prot, address, pfn, 1,
+               /* Hand in lpsize = 0 to enforce the protection mechanism */
+               new_prot = static_protections(new_prot, address, pfn, 1, 0,
                                              CPA_PROTECT);
 
                new_prot = pgprot_clear_protnone_bits(new_prot);
index eaaed5bfc4a4429a92e980252c2f993047eb90bb..991549a1c5f3ae193aedd8ae9abae4148aed0a5f 100644 (file)
@@ -390,8 +390,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
 
        emit_prologue(&prog, bpf_prog->aux->stack_depth,
                      bpf_prog_was_classic(bpf_prog));
+       addrs[0] = prog - temp;
 
-       for (i = 0; i < insn_cnt; i++, insn++) {
+       for (i = 1; i <= insn_cnt; i++, insn++) {
                const s32 imm32 = insn->imm;
                u32 dst_reg = insn->dst_reg;
                u32 src_reg = insn->src_reg;
@@ -1105,7 +1106,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
                extra_pass = true;
                goto skip_init_addrs;
        }
-       addrs = kmalloc_array(prog->len, sizeof(*addrs), GFP_KERNEL);
+       addrs = kmalloc_array(prog->len + 1, sizeof(*addrs), GFP_KERNEL);
        if (!addrs) {
                prog = orig_prog;
                goto out_addrs;
@@ -1115,7 +1116,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
         * Before first pass, make a rough estimation of addrs[]
         * each BPF instruction is translated to less than 64 bytes
         */
-       for (proglen = 0, i = 0; i < prog->len; i++) {
+       for (proglen = 0, i = 0; i <= prog->len; i++) {
                proglen += 64;
                addrs[i] = proglen;
        }
@@ -1180,7 +1181,7 @@ out_image:
 
        if (!image || !prog->is_func || extra_pass) {
                if (image)
-                       bpf_prog_fill_jited_linfo(prog, addrs);
+                       bpf_prog_fill_jited_linfo(prog, addrs + 1);
 out_addrs:
                kfree(addrs);
                kfree(jit_data);
index 24b079e94bc261b6b7b27c4aadf0ff7ec5f7ccda..c9ef6a7a4a1aa4783e515d9378fa2886451bbb02 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/smp.h>
 #include <linux/perf_event.h>
 #include <linux/tboot.h>
+#include <linux/dmi.h>
 
 #include <asm/pgtable.h>
 #include <asm/proto.h>
@@ -23,7 +24,7 @@
 #include <asm/debugreg.h>
 #include <asm/cpu.h>
 #include <asm/mmu_context.h>
-#include <linux/dmi.h>
+#include <asm/cpu_device_id.h>
 
 #ifdef CONFIG_X86_32
 __visible unsigned long saved_context_ebx;
@@ -397,15 +398,14 @@ static int __init bsp_pm_check_init(void)
 
 core_initcall(bsp_pm_check_init);
 
-static int msr_init_context(const u32 *msr_id, const int total_num)
+static int msr_build_context(const u32 *msr_id, const int num)
 {
-       int i = 0;
+       struct saved_msrs *saved_msrs = &saved_context.saved_msrs;
        struct saved_msr *msr_array;
+       int total_num;
+       int i, j;
 
-       if (saved_context.saved_msrs.array || saved_context.saved_msrs.num > 0) {
-               pr_err("x86/pm: MSR quirk already applied, please check your DMI match table.\n");
-               return -EINVAL;
-       }
+       total_num = saved_msrs->num + num;
 
        msr_array = kmalloc_array(total_num, sizeof(struct saved_msr), GFP_KERNEL);
        if (!msr_array) {
@@ -413,19 +413,30 @@ static int msr_init_context(const u32 *msr_id, const int total_num)
                return -ENOMEM;
        }
 
-       for (i = 0; i < total_num; i++) {
-               msr_array[i].info.msr_no        = msr_id[i];
+       if (saved_msrs->array) {
+               /*
+                * Multiple callbacks can invoke this function, so copy any
+                * MSR save requests from previous invocations.
+                */
+               memcpy(msr_array, saved_msrs->array,
+                      sizeof(struct saved_msr) * saved_msrs->num);
+
+               kfree(saved_msrs->array);
+       }
+
+       for (i = saved_msrs->num, j = 0; i < total_num; i++, j++) {
+               msr_array[i].info.msr_no        = msr_id[j];
                msr_array[i].valid              = false;
                msr_array[i].info.reg.q         = 0;
        }
-       saved_context.saved_msrs.num    = total_num;
-       saved_context.saved_msrs.array  = msr_array;
+       saved_msrs->num   = total_num;
+       saved_msrs->array = msr_array;
 
        return 0;
 }
 
 /*
- * The following section is a quirk framework for problematic BIOSen:
+ * The following sections are a quirk framework for problematic BIOSen:
  * Sometimes MSRs are modified by the BIOSen after suspended to
  * RAM, this might cause unexpected behavior after wakeup.
  * Thus we save/restore these specified MSRs across suspend/resume
@@ -440,7 +451,7 @@ static int msr_initialize_bdw(const struct dmi_system_id *d)
        u32 bdw_msr_id[] = { MSR_IA32_THERM_CONTROL };
 
        pr_info("x86/pm: %s detected, MSR saving is needed during suspending.\n", d->ident);
-       return msr_init_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id));
+       return msr_build_context(bdw_msr_id, ARRAY_SIZE(bdw_msr_id));
 }
 
 static const struct dmi_system_id msr_save_dmi_table[] = {
@@ -455,9 +466,58 @@ static const struct dmi_system_id msr_save_dmi_table[] = {
        {}
 };
 
+static int msr_save_cpuid_features(const struct x86_cpu_id *c)
+{
+       u32 cpuid_msr_id[] = {
+               MSR_AMD64_CPUID_FN_1,
+       };
+
+       pr_info("x86/pm: family %#hx cpu detected, MSR saving is needed during suspending.\n",
+               c->family);
+
+       return msr_build_context(cpuid_msr_id, ARRAY_SIZE(cpuid_msr_id));
+}
+
+static const struct x86_cpu_id msr_save_cpu_table[] = {
+       {
+               .vendor = X86_VENDOR_AMD,
+               .family = 0x15,
+               .model = X86_MODEL_ANY,
+               .feature = X86_FEATURE_ANY,
+               .driver_data = (kernel_ulong_t)msr_save_cpuid_features,
+       },
+       {
+               .vendor = X86_VENDOR_AMD,
+               .family = 0x16,
+               .model = X86_MODEL_ANY,
+               .feature = X86_FEATURE_ANY,
+               .driver_data = (kernel_ulong_t)msr_save_cpuid_features,
+       },
+       {}
+};
+
+typedef int (*pm_cpu_match_t)(const struct x86_cpu_id *);
+static int pm_cpu_check(const struct x86_cpu_id *c)
+{
+       const struct x86_cpu_id *m;
+       int ret = 0;
+
+       m = x86_match_cpu(msr_save_cpu_table);
+       if (m) {
+               pm_cpu_match_t fn;
+
+               fn = (pm_cpu_match_t)m->driver_data;
+               ret = fn(m);
+       }
+
+       return ret;
+}
+
 static int pm_check_save_msr(void)
 {
        dmi_check_system(msr_save_dmi_table);
+       pm_cpu_check(msr_save_cpu_table);
+
        return 0;
 }
 
index 3cf302b2633222ff45323b2528f3499233b650c5..10fb42da0007e9d3c914143ec4e427dd1eec42f5 100644 (file)
@@ -6,6 +6,9 @@ purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string
 targets += $(purgatory-y)
 PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
 
+$(obj)/string.o: $(srctree)/arch/x86/boot/compressed/string.c FORCE
+       $(call if_changed_rule,cc_o_c)
+
 $(obj)/sha256.o: $(srctree)/lib/sha256.c FORCE
        $(call if_changed_rule,cc_o_c)
 
@@ -15,13 +18,39 @@ targets += purgatory.ro
 KASAN_SANITIZE := n
 KCOV_INSTRUMENT := n
 
+# These are adjustments to the compiler flags used for objects that
+# make up the standalone purgatory.ro
+
+PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
+PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
+
 # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
 # in turn leaves some undefined symbols like __fentry__ in purgatory and not
-# sure how to relocate those. Like kexec-tools, use custom flags.
+# sure how to relocate those.
+ifdef CONFIG_FUNCTION_TRACER
+PURGATORY_CFLAGS_REMOVE                += $(CC_FLAGS_FTRACE)
+endif
+
+ifdef CONFIG_STACKPROTECTOR
+PURGATORY_CFLAGS_REMOVE                += -fstack-protector
+endif
+
+ifdef CONFIG_STACKPROTECTOR_STRONG
+PURGATORY_CFLAGS_REMOVE                += -fstack-protector-strong
+endif
+
+ifdef CONFIG_RETPOLINE
+PURGATORY_CFLAGS_REMOVE                += $(RETPOLINE_CFLAGS)
+endif
+
+CFLAGS_REMOVE_purgatory.o      += $(PURGATORY_CFLAGS_REMOVE)
+CFLAGS_purgatory.o             += $(PURGATORY_CFLAGS)
+
+CFLAGS_REMOVE_sha256.o         += $(PURGATORY_CFLAGS_REMOVE)
+CFLAGS_sha256.o                        += $(PURGATORY_CFLAGS)
 
-KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -Os -mcmodel=large
-KBUILD_CFLAGS += -m$(BITS)
-KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
+CFLAGS_REMOVE_string.o         += $(PURGATORY_CFLAGS_REMOVE)
+CFLAGS_string.o                        += $(PURGATORY_CFLAGS)
 
 $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
index 6d8d5a34c377245f65d005e34a2c9b0ef7993740..b607bda786f6b9ff0c60cb5889b4f99353d0edcb 100644 (file)
@@ -68,3 +68,9 @@ void purgatory(void)
        }
        copy_backup_region();
 }
+
+/*
+ * Defined in order to reuse memcpy() and memset() from
+ * arch/x86/boot/compressed/string.c
+ */
+void warn(const char *msg) {}
diff --git a/arch/x86/purgatory/string.c b/arch/x86/purgatory/string.c
deleted file mode 100644 (file)
index 01ad438..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Simple string functions.
- *
- * Copyright (C) 2014 Red Hat Inc.
- *
- * Author:
- *       Vivek Goyal <vgoyal@redhat.com>
- */
-
-#include <linux/types.h>
-
-#include "../boot/string.c"
-
-void *memcpy(void *dst, const void *src, size_t len)
-{
-       return __builtin_memcpy(dst, src, len);
-}
-
-void *memset(void *dst, int c, size_t len)
-{
-       return __builtin_memset(dst, c, len);
-}
index 60c2200200547a7ad620cb54deb588deeee39521..80828b95a51f031653fe7be541cf17e536869f52 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/asmmacro.h>
 #include <asm/processor.h>
 #include <asm/coprocessor.h>
 #include <asm/thread_info.h>
index 5cb8a62e091c77619081973fe488b04a79437dd7..7c3106093c7584e44daaa2e6af660afa05ff4132 100644 (file)
@@ -511,6 +511,7 @@ void cpu_reset(void)
                                      "add      %2, %2, %7\n\t"
                                      "addi     %0, %0, -1\n\t"
                                      "bnez     %0, 1b\n\t"
+                                     "isync\n\t"
                                      /* Jump to identity mapping */
                                      "jx       %3\n"
                                      "2:\n\t"
index 72860325245a30bb68b069102bb4243885edfe91..b33be928d164fef34f5d2f00863d9034e38ef1a2 100644 (file)
@@ -1924,12 +1924,13 @@ static void bfq_add_request(struct request *rq)
                 * confirmed no later than during the next
                 * I/O-plugging interval for bfqq.
                 */
-               if (!bfq_bfqq_has_short_ttime(bfqq) &&
+               if (bfqd->last_completed_rq_bfqq &&
+                   !bfq_bfqq_has_short_ttime(bfqq) &&
                    ktime_get_ns() - bfqd->last_completion <
                    200 * NSEC_PER_USEC) {
                        if (bfqd->last_completed_rq_bfqq != bfqq &&
-                                  bfqd->last_completed_rq_bfqq !=
-                                  bfqq->waker_bfqq) {
+                           bfqd->last_completed_rq_bfqq !=
+                           bfqq->waker_bfqq) {
                                /*
                                 * First synchronization detected with
                                 * a candidate waker queue, or with a
@@ -2250,9 +2251,14 @@ static void bfq_request_merged(struct request_queue *q, struct request *req,
            blk_rq_pos(container_of(rb_prev(&req->rb_node),
                                    struct request, rb_node))) {
                struct bfq_queue *bfqq = bfq_init_rq(req);
-               struct bfq_data *bfqd = bfqq->bfqd;
+               struct bfq_data *bfqd;
                struct request *prev, *next_rq;
 
+               if (!bfqq)
+                       return;
+
+               bfqd = bfqq->bfqd;
+
                /* Reposition request in its sort_list */
                elv_rb_del(&bfqq->sort_list, req);
                elv_rb_add(&bfqq->sort_list, req);
@@ -2299,6 +2305,9 @@ static void bfq_requests_merged(struct request_queue *q, struct request *rq,
        struct bfq_queue *bfqq = bfq_init_rq(rq),
                *next_bfqq = bfq_init_rq(next);
 
+       if (!bfqq)
+               return;
+
        /*
         * If next and rq belong to the same bfq_queue and next is older
         * than rq, then reposition rq in the fifo (by substituting next
@@ -3354,38 +3363,57 @@ static void bfq_dispatch_remove(struct request_queue *q, struct request *rq)
  * there is no active group, then the primary expectation for
  * this device is probably a high throughput.
  *
- * We are now left only with explaining the additional
- * compound condition that is checked below for deciding
- * whether the scenario is asymmetric. To explain this
- * compound condition, we need to add that the function
+ * We are now left only with explaining the two sub-conditions in the
+ * additional compound condition that is checked below for deciding
+ * whether the scenario is asymmetric. To explain the first
+ * sub-condition, we need to add that the function
  * bfq_asymmetric_scenario checks the weights of only
- * non-weight-raised queues, for efficiency reasons (see
- * comments on bfq_weights_tree_add()). Then the fact that
- * bfqq is weight-raised is checked explicitly here. More
- * precisely, the compound condition below takes into account
- * also the fact that, even if bfqq is being weight-raised,
- * the scenario is still symmetric if all queues with requests
- * waiting for completion happen to be
- * weight-raised. Actually, we should be even more precise
- * here, and differentiate between interactive weight raising
- * and soft real-time weight raising.
+ * non-weight-raised queues, for efficiency reasons (see comments on
+ * bfq_weights_tree_add()). Then the fact that bfqq is weight-raised
+ * is checked explicitly here. More precisely, the compound condition
+ * below takes into account also the fact that, even if bfqq is being
+ * weight-raised, the scenario is still symmetric if all queues with
+ * requests waiting for completion happen to be
+ * weight-raised. Actually, we should be even more precise here, and
+ * differentiate between interactive weight raising and soft real-time
+ * weight raising.
+ *
+ * The second sub-condition checked in the compound condition is
+ * whether there is a fair amount of already in-flight I/O not
+ * belonging to bfqq. If so, I/O dispatching is to be plugged, for the
+ * following reason. The drive may decide to serve in-flight
+ * non-bfqq's I/O requests before bfqq's ones, thereby delaying the
+ * arrival of new I/O requests for bfqq (recall that bfqq is sync). If
+ * I/O-dispatching is not plugged, then, while bfqq remains empty, a
+ * basically uncontrolled amount of I/O from other queues may be
+ * dispatched too, possibly causing the service of bfqq's I/O to be
+ * delayed even longer in the drive. This problem gets more and more
+ * serious as the speed and the queue depth of the drive grow,
+ * because, as these two quantities grow, the probability to find no
+ * queue busy but many requests in flight grows too. By contrast,
+ * plugging I/O dispatching minimizes the delay induced by already
+ * in-flight I/O, and enables bfqq to recover the bandwidth it may
+ * lose because of this delay.
  *
  * As a side note, it is worth considering that the above
- * device-idling countermeasures may however fail in the
- * following unlucky scenario: if idling is (correctly)
- * disabled in a time period during which all symmetry
- * sub-conditions hold, and hence the device is allowed to
- * enqueue many requests, but at some later point in time some
- * sub-condition stops to hold, then it may become impossible
- * to let requests be served in the desired order until all
- * the requests already queued in the device have been served.
+ * device-idling countermeasures may however fail in the following
+ * unlucky scenario: if I/O-dispatch plugging is (correctly) disabled
+ * in a time period during which all symmetry sub-conditions hold, and
+ * therefore the device is allowed to enqueue many requests, but at
+ * some later point in time some sub-condition stops to hold, then it
+ * may become impossible to make requests be served in the desired
+ * order until all the requests already queued in the device have been
+ * served. The last sub-condition commented above somewhat mitigates
+ * this problem for weight-raised queues.
  */
 static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd,
                                                 struct bfq_queue *bfqq)
 {
        return (bfqq->wr_coeff > 1 &&
-               bfqd->wr_busy_queues <
-               bfq_tot_busy_queues(bfqd)) ||
+               (bfqd->wr_busy_queues <
+                bfq_tot_busy_queues(bfqd) ||
+                bfqd->rq_in_driver >=
+                bfqq->dispatched + 4)) ||
                bfq_asymmetric_scenario(bfqd, bfqq);
 }
 
@@ -4745,6 +4773,8 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
  */
 void bfq_put_queue(struct bfq_queue *bfqq)
 {
+       struct bfq_queue *item;
+       struct hlist_node *n;
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
        struct bfq_group *bfqg = bfqq_group(bfqq);
 #endif
@@ -4789,6 +4819,36 @@ void bfq_put_queue(struct bfq_queue *bfqq)
                        bfqq->bfqd->burst_size--;
        }
 
+       /*
+        * bfqq does not exist any longer, so it cannot be woken by
+        * any other queue, and cannot wake any other queue. Then bfqq
+        * must be removed from the woken list of its possible waker
+        * queue, and all queues in the woken list of bfqq must stop
+        * having a waker queue. Strictly speaking, these updates
+        * should be performed when bfqq remains with no I/O source
+        * attached to it, which happens before bfqq gets freed. In
+        * particular, this happens when the last process associated
+        * with bfqq exits or gets associated with a different
+        * queue. However, both events lead to bfqq being freed soon,
+        * and dangling references would come out only after bfqq gets
+        * freed. So these updates are done here, as a simple and safe
+        * way to handle all cases.
+        */
+       /* remove bfqq from woken list */
+       if (!hlist_unhashed(&bfqq->woken_list_node))
+               hlist_del_init(&bfqq->woken_list_node);
+
+       /* reset waker for all queues in woken list */
+       hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
+                                 woken_list_node) {
+               item->waker_bfqq = NULL;
+               bfq_clear_bfqq_has_waker(item);
+               hlist_del_init(&item->woken_list_node);
+       }
+
+       if (bfqq->bfqd && bfqq->bfqd->last_completed_rq_bfqq == bfqq)
+               bfqq->bfqd->last_completed_rq_bfqq = NULL;
+
        kmem_cache_free(bfq_pool, bfqq);
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
        bfqg_and_blkg_put(bfqg);
@@ -4816,9 +4876,6 @@ static void bfq_put_cooperator(struct bfq_queue *bfqq)
 
 static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
 {
-       struct bfq_queue *item;
-       struct hlist_node *n;
-
        if (bfqq == bfqd->in_service_queue) {
                __bfq_bfqq_expire(bfqd, bfqq, BFQQE_BUDGET_TIMEOUT);
                bfq_schedule_dispatch(bfqd);
@@ -4828,18 +4885,6 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
 
        bfq_put_cooperator(bfqq);
 
-       /* remove bfqq from woken list */
-       if (!hlist_unhashed(&bfqq->woken_list_node))
-               hlist_del_init(&bfqq->woken_list_node);
-
-       /* reset waker for all queues in woken list */
-       hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
-                                 woken_list_node) {
-               item->waker_bfqq = NULL;
-               bfq_clear_bfqq_has_waker(item);
-               hlist_del_init(&item->woken_list_node);
-       }
-
        bfq_put_queue(bfqq); /* release process reference */
 }
 
@@ -5417,12 +5462,12 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
 
        spin_lock_irq(&bfqd->lock);
        bfqq = bfq_init_rq(rq);
-       if (at_head || blk_rq_is_passthrough(rq)) {
+       if (!bfqq || at_head || blk_rq_is_passthrough(rq)) {
                if (at_head)
                        list_add(&rq->queuelist, &bfqd->dispatch);
                else
                        list_add_tail(&rq->queuelist, &bfqd->dispatch);
-       } else { /* bfqq is assumed to be non null here */
+       } else {
                idle_timer_disabled = __bfq_insert_request(bfqd, rq);
                /*
                 * Update bfqq, because, if a queue merge has occurred
index 24ed26957367e2cbba91590040c9454612edad98..55a7dc227dfbd6af883a2832d09c8abf2c16d3d0 100644 (file)
@@ -54,7 +54,7 @@ static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS];
 
 static LIST_HEAD(all_blkcgs);          /* protected by blkcg_pol_mutex */
 
-static bool blkcg_debug_stats = false;
+bool blkcg_debug_stats = false;
 static struct workqueue_struct *blkcg_punt_bio_wq;
 
 static bool blkcg_policy_enabled(struct request_queue *q,
@@ -944,10 +944,7 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
                                         dbytes, dios);
                }
 
-               if (!blkcg_debug_stats)
-                       goto next;
-
-               if (atomic_read(&blkg->use_delay)) {
+               if (blkcg_debug_stats && atomic_read(&blkg->use_delay)) {
                        has_stats = true;
                        off += scnprintf(buf+off, size-off,
                                         " use_delay=%d delay_nsec=%llu",
@@ -967,7 +964,7 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
                                has_stats = true;
                        off += written;
                }
-next:
+
                if (has_stats) {
                        if (off < size - 1) {
                                off += scnprintf(buf+off, size-off, "\n");
index d973c38ee4fd65b502af755e491e1a4bb830c0c3..0fff7b56df0e4d0fa0f82be4102f3ceb03735034 100644 (file)
@@ -917,6 +917,9 @@ static size_t iolatency_pd_stat(struct blkg_policy_data *pd, char *buf,
        unsigned long long avg_lat;
        unsigned long long cur_win;
 
+       if (!blkcg_debug_stats)
+               return 0;
+
        if (iolat->ssd)
                return iolatency_ssd_stat(iolat, buf, size);
 
index cf22ab00fefb68cdc9efda7d9dcad8329307a262..126021fc3a11f9308a5fe0745ba2a6f9f1ee2ee5 100644 (file)
@@ -61,15 +61,6 @@ static inline void blk_mq_sched_completed_request(struct request *rq, u64 now)
                e->type->ops.completed_request(rq, now);
 }
 
-static inline void blk_mq_sched_started_request(struct request *rq)
-{
-       struct request_queue *q = rq->q;
-       struct elevator_queue *e = q->elevator;
-
-       if (e && e->type->ops.started_request)
-               e->type->ops.started_request(rq);
-}
-
 static inline void blk_mq_sched_requeue_request(struct request *rq)
 {
        struct request_queue *q = rq->q;
index b038ec680e843e14aa2f3a7b3d967bd802efd4db..0835f4d8d42e7e34c043acc040d8f5406b2e2268 100644 (file)
@@ -669,8 +669,6 @@ void blk_mq_start_request(struct request *rq)
 {
        struct request_queue *q = rq->q;
 
-       blk_mq_sched_started_request(rq);
-
        trace_block_rq_issue(q, rq);
 
        if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {
@@ -2664,8 +2662,6 @@ void blk_mq_release(struct request_queue *q)
        struct blk_mq_hw_ctx *hctx, *next;
        int i;
 
-       cancel_delayed_work_sync(&q->requeue_work);
-
        queue_for_each_hw_ctx(q, hctx, i)
                WARN_ON_ONCE(hctx && list_empty(&hctx->hctx_list));
 
index 659ccb8b693fa63cedfc53536589f5afcf3b1afc..3954c0dc14433d21c4baf7f9b007c2710fa67d64 100644 (file)
@@ -202,6 +202,7 @@ static int rq_qos_wake_function(struct wait_queue_entry *curr,
                return -1;
 
        data->got_token = true;
+       smp_wmb();
        list_del_init(&curr->entry);
        wake_up_process(data->task);
        return 1;
@@ -244,7 +245,9 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
                return;
 
        prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE);
+       has_sleeper = !wq_has_single_sleeper(&rqw->wait);
        do {
+               /* The memory barrier in set_task_state saves us here. */
                if (data.got_token)
                        break;
                if (!has_sleeper && acquire_inflight_cb(rqw, private_data)) {
@@ -255,12 +258,14 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
                         * which means we now have two. Put our local token
                         * and wake anyone else potentially waiting for one.
                         */
+                       smp_rmb();
                        if (data.got_token)
                                cleanup_cb(rqw, private_data);
                        break;
                }
                io_schedule();
-               has_sleeper = false;
+               has_sleeper = true;
+               set_current_state(TASK_UNINTERRUPTIBLE);
        } while (1);
        finish_wait(&rqw->wait, &data.wq);
 }
index 2ae348c101a05f004a069d04726445436e68acef..2c1831207a8f74de455679551f79d8862450eed0 100644 (file)
@@ -752,7 +752,8 @@ void blk_queue_virt_boundary(struct request_queue *q, unsigned long mask)
         * page (which might not be idential to the Linux PAGE_SIZE).  Because
         * of that they are not limited by our notion of "segment size".
         */
-       q->limits.max_segment_size = UINT_MAX;
+       if (mask)
+               q->limits.max_segment_size = UINT_MAX;
 }
 EXPORT_SYMBOL(blk_queue_virt_boundary);
 
index 977c659dcd1846f193ee525b36cd1c6ccecb2684..9bfa3ea4ed63038606067f1bb9d2f0c957a90279 100644 (file)
@@ -892,6 +892,9 @@ static void __blk_release_queue(struct work_struct *work)
 
        blk_free_queue_stats(q->stats);
 
+       if (queue_is_mq(q))
+               cancel_delayed_work_sync(&q->requeue_work);
+
        blk_exit_queue(q);
 
        blk_queue_free_zone_bitmaps(q);
index 97887e59f3b2a34dfde5272bb0d3226e63bad15a..54f1f0d381f4d28c7b4d07d4044e4f0f7d2ddb05 100644 (file)
@@ -1969,7 +1969,7 @@ static const struct attribute *disk_events_attrs[] = {
  * The default polling interval can be specified by the kernel
  * parameter block.events_dfl_poll_msecs which defaults to 0
  * (disable).  This can also be modified runtime by writing to
- * /sys/module/block/events_dfl_poll_msecs.
+ * /sys/module/block/parameters/events_dfl_poll_msecs.
  */
 static int disk_events_set_dfl_poll_msecs(const char *val,
                                          const struct kernel_param *kp)
index d4551e33fa716cbfe0ee94eff1794db0cdba69cd..8569b79e8b581e894b129871a5fac2bc35994c62 100644 (file)
@@ -611,8 +611,8 @@ static int iort_dev_find_its_id(struct device *dev, u32 req_id,
 
        /* Move to ITS specific data */
        its = (struct acpi_iort_its_group *)node->node_data;
-       if (idx > its->its_count) {
-               dev_err(dev, "requested ITS ID index [%d] is greater than available [%d]\n",
+       if (idx >= its->its_count) {
+               dev_err(dev, "requested ITS ID index [%d] overruns ITS entries [%d]\n",
                        idx, its->its_count);
                return -ENXIO;
        }
index 28cffaaf9d82ad9bc392ae0288e2ece506d5bcd7..f616b16c1f0be267aa5c116b14a35b095a5ac5d5 100644 (file)
@@ -232,13 +232,15 @@ int acpi_device_set_power(struct acpi_device *device, int state)
                if (device->power.flags.power_resources)
                        result = acpi_power_transition(device, target_state);
        } else {
+               int cur_state = device->power.state;
+
                if (device->power.flags.power_resources) {
                        result = acpi_power_transition(device, ACPI_STATE_D0);
                        if (result)
                                goto end;
                }
 
-               if (device->power.state == ACPI_STATE_D0) {
+               if (cur_state == ACPI_STATE_D0) {
                        int psc;
 
                        /* Nothing to do here if _PSC is not present. */
index c02fa27dd3f340ab0851a12651f7dc4fb8a60f1c..1413324982f0d7628068711e61e598093b88d320 100644 (file)
@@ -1282,7 +1282,7 @@ static ssize_t hw_error_scrub_store(struct device *dev,
        if (rc)
                return rc;
 
-       device_lock(dev);
+       nfit_device_lock(dev);
        nd_desc = dev_get_drvdata(dev);
        if (nd_desc) {
                struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
@@ -1299,7 +1299,7 @@ static ssize_t hw_error_scrub_store(struct device *dev,
                        break;
                }
        }
-       device_unlock(dev);
+       nfit_device_unlock(dev);
        if (rc)
                return rc;
        return size;
@@ -1319,7 +1319,7 @@ static ssize_t scrub_show(struct device *dev,
        ssize_t rc = -ENXIO;
        bool busy;
 
-       device_lock(dev);
+       nfit_device_lock(dev);
        nd_desc = dev_get_drvdata(dev);
        if (!nd_desc) {
                device_unlock(dev);
@@ -1339,7 +1339,7 @@ static ssize_t scrub_show(struct device *dev,
        }
 
        mutex_unlock(&acpi_desc->init_mutex);
-       device_unlock(dev);
+       nfit_device_unlock(dev);
        return rc;
 }
 
@@ -1356,14 +1356,14 @@ static ssize_t scrub_store(struct device *dev,
        if (val != 1)
                return -EINVAL;
 
-       device_lock(dev);
+       nfit_device_lock(dev);
        nd_desc = dev_get_drvdata(dev);
        if (nd_desc) {
                struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
 
                rc = acpi_nfit_ars_rescan(acpi_desc, ARS_REQ_LONG);
        }
-       device_unlock(dev);
+       nfit_device_unlock(dev);
        if (rc)
                return rc;
        return size;
@@ -1749,9 +1749,9 @@ static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data)
        struct acpi_device *adev = data;
        struct device *dev = &adev->dev;
 
-       device_lock(dev->parent);
+       nfit_device_lock(dev->parent);
        __acpi_nvdimm_notify(dev, event);
-       device_unlock(dev->parent);
+       nfit_device_unlock(dev->parent);
 }
 
 static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
@@ -3457,8 +3457,8 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
        struct device *dev = acpi_desc->dev;
 
        /* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
-       device_lock(dev);
-       device_unlock(dev);
+       nfit_device_lock(dev);
+       nfit_device_unlock(dev);
 
        /* Bounce the init_mutex to complete initial registration */
        mutex_lock(&acpi_desc->init_mutex);
@@ -3602,8 +3602,8 @@ void acpi_nfit_shutdown(void *data)
         * acpi_nfit_ars_rescan() submissions have had a chance to
         * either submit or see ->cancel set.
         */
-       device_lock(bus_dev);
-       device_unlock(bus_dev);
+       nfit_device_lock(bus_dev);
+       nfit_device_unlock(bus_dev);
 
        flush_workqueue(nfit_wq);
 }
@@ -3746,9 +3746,9 @@ EXPORT_SYMBOL_GPL(__acpi_nfit_notify);
 
 static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
 {
-       device_lock(&adev->dev);
+       nfit_device_lock(&adev->dev);
        __acpi_nfit_notify(&adev->dev, adev->handle, event);
-       device_unlock(&adev->dev);
+       nfit_device_unlock(&adev->dev);
 }
 
 static const struct acpi_device_id acpi_nfit_ids[] = {
index 6ee2b02af73ef80ec92658d50e5f241877993161..24241941181ce2cda1d864d2e2b5eb51b1d871a7 100644 (file)
@@ -312,6 +312,30 @@ static inline struct acpi_nfit_desc *to_acpi_desc(
        return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
 }
 
+#ifdef CONFIG_PROVE_LOCKING
+static inline void nfit_device_lock(struct device *dev)
+{
+       device_lock(dev);
+       mutex_lock(&dev->lockdep_mutex);
+}
+
+static inline void nfit_device_unlock(struct device *dev)
+{
+       mutex_unlock(&dev->lockdep_mutex);
+       device_unlock(dev);
+}
+#else
+static inline void nfit_device_lock(struct device *dev)
+{
+       device_lock(dev);
+}
+
+static inline void nfit_device_unlock(struct device *dev)
+{
+       device_unlock(dev);
+}
+#endif
+
 const guid_t *to_nfit_uuid(enum nfit_uuids id);
 int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz);
 void acpi_nfit_shutdown(void *data);
index 0e28270b0fd81046b2b2a434b0dd65edb4b282a6..aad6be5c0af0a5f4da721eed1fd8b77cd25f3b94 100644 (file)
@@ -2204,6 +2204,12 @@ int __init acpi_scan_init(void)
        acpi_gpe_apply_masked_gpes();
        acpi_update_all_gpes();
 
+       /*
+        * Although we call __add_memory() that is documented to require the
+        * device_hotplug_lock, it is not necessary here because this is an
+        * early code when userspace or any other code path cannot trigger
+        * hotplug/hotunplug operations.
+        */
        mutex_lock(&acpi_scan_lock);
        /*
         * Enumerate devices in the ACPI namespace.
index 38a59a630cd4cb98badec27818949d75a206813e..dc1c83eafc225fdf00f0f3d9606652e3a9f3fb28 100644 (file)
@@ -2988,7 +2988,7 @@ static void binder_transaction(struct binder_proc *proc,
                        else
                                return_error = BR_DEAD_REPLY;
                        mutex_unlock(&context->context_mgr_node_lock);
-                       if (target_node && target_proc == proc) {
+                       if (target_node && target_proc->pid == proc->pid) {
                                binder_user_error("%d:%d got transaction to context manager from process owning it\n",
                                                  proc->pid, thread->pid);
                                return_error = BR_FAILED_REPLY;
@@ -3239,7 +3239,8 @@ static void binder_transaction(struct binder_proc *proc,
        buffer_offset = off_start_offset;
        off_end_offset = off_start_offset + tr->offsets_size;
        sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
-       sg_buf_end_offset = sg_buf_offset + extra_buffers_size;
+       sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
+               ALIGN(secctx_sz, sizeof(u64));
        off_min = 0;
        for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
             buffer_offset += sizeof(binder_size_t)) {
index 72312ad2e142d41202d9378889a1cd015795c745..9e9583a6bba99295601cc92399c94e85f623cef3 100644 (file)
@@ -338,6 +338,9 @@ static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port,
                hpriv->phys[port] = NULL;
                rc = 0;
                break;
+       case -EPROBE_DEFER:
+               /* Do not complain yet */
+               break;
 
        default:
                dev_err(dev,
@@ -408,7 +411,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
        hpriv->mmio = devm_ioremap_resource(dev,
                              platform_get_resource(pdev, IORESOURCE_MEM, 0));
        if (IS_ERR(hpriv->mmio)) {
-               dev_err(dev, "no mmio space\n");
                rc = PTR_ERR(hpriv->mmio);
                goto err_out;
        }
index 391ac0503dc075e7de0957c56aa7a30f966927e4..76d0f9de767bcec3d19b59a390cf95d9954c4025 100644 (file)
@@ -1786,6 +1786,21 @@ nothing_to_do:
        return 1;
 }
 
+static bool ata_check_nblocks(struct scsi_cmnd *scmd, u32 n_blocks)
+{
+       struct request *rq = scmd->request;
+       u32 req_blocks;
+
+       if (!blk_rq_is_passthrough(rq))
+               return true;
+
+       req_blocks = blk_rq_bytes(rq) / scmd->device->sector_size;
+       if (n_blocks > req_blocks)
+               return false;
+
+       return true;
+}
+
 /**
  *     ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
  *     @qc: Storage for translated ATA taskfile
@@ -1830,6 +1845,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                scsi_10_lba_len(cdb, &block, &n_block);
                if (cdb[1] & (1 << 3))
                        tf_flags |= ATA_TFLAG_FUA;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        case READ_6:
        case WRITE_6:
@@ -1844,6 +1861,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                 */
                if (!n_block)
                        n_block = 256;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        case READ_16:
        case WRITE_16:
@@ -1854,6 +1873,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                scsi_16_lba_len(cdb, &block, &n_block);
                if (cdb[1] & (1 << 3))
                        tf_flags |= ATA_TFLAG_FUA;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        default:
                DPRINTK("no-byte command\n");
index 10aa2788214279b1682135e77fc22ac0007e6190..4f115adb4ee83b3836f1d596e1350ce3785011d6 100644 (file)
@@ -658,6 +658,10 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
        unsigned int offset;
        unsigned char *buf;
 
+       if (!qc->cursg) {
+               qc->curbytes = qc->nbytes;
+               return;
+       }
        if (qc->curbytes == qc->nbytes - qc->sect_size)
                ap->hsm_task_state = HSM_ST_LAST;
 
@@ -683,6 +687,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
 
        if (qc->cursg_ofs == qc->cursg->length) {
                qc->cursg = sg_next(qc->cursg);
+               if (!qc->cursg)
+                       ap->hsm_task_state = HSM_ST_LAST;
                qc->cursg_ofs = 0;
        }
 }
index 173e6f2dd9af0f12afdc1fee7e372cfa4291e0aa..eefda51f97d351bda5d8437e2d83aaeae16b30f6 100644 (file)
@@ -56,7 +56,7 @@ static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev)
        unsigned int ret;
        struct rm_feature_desc *desc;
        struct ata_taskfile tf;
-       static const char cdb[] = {  GPCMD_GET_CONFIGURATION,
+       static const char cdb[ATAPI_CDB_LEN] = {  GPCMD_GET_CONFIGURATION,
                        2,      /* only 1 feature descriptor requested */
                        0, 3,   /* 3, removable medium feature */
                        0, 0, 0,/* reserved */
index 7c37f2ff09e4169f30b42fbb12798abc19de228e..deae466395de1a656d5cba27720fb8f345e6c332 100644 (file)
@@ -158,7 +158,6 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
 static int rb532_pata_driver_remove(struct platform_device *pdev)
 {
        struct ata_host *ah = platform_get_drvdata(pdev);
-       struct rb532_cf_info *info = ah->private_data;
 
        ata_host_detach(ah);
 
index 2e2efa577437e82ecdeb20d9d41b6ce63635bf16..8c37294f1d1ee4c07dacaec843a0190b0320d5fc 100644 (file)
@@ -200,7 +200,7 @@ config ATM_NICSTAR_USE_SUNI
          make the card work).
 
 config ATM_NICSTAR_USE_IDT77105
-       bool "Use IDT77015 PHY driver (25Mbps)"
+       bool "Use IDT77105 PHY driver (25Mbps)"
        depends on ATM_NICSTAR
        help
          Support for the PHYsical layer chip in ForeRunner LE25 cards. In
index 302cf0ba16008740d8f0ecd231b6f27c73f0f97e..8c7a996d1f16cfd5d2b86a73effe5562ce1732b0 100644 (file)
@@ -63,6 +63,7 @@
 #include <asm/byteorder.h>  
 #include <linux/vmalloc.h>
 #include <linux/jiffies.h>
+#include <linux/nospec.h>
 #include "iphase.h"              
 #include "suni.h"                
 #define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
@@ -2760,8 +2761,11 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
    }
    if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT; 
    board = ia_cmds.status;
-   if ((board < 0) || (board > iadev_count))
-         board = 0;    
+
+       if ((board < 0) || (board > iadev_count))
+               board = 0;
+       board = array_index_nospec(board, iadev_count + 1);
+
    iadev = ia_dev[board];
    switch (ia_cmds.cmd) {
    case MEMDUMP:
index dd61fdd400f05a0a9d5438241a52a7e6436e9e8f..68489d1f00bb33a275100e280bd68341aa31c8d1 100644 (file)
@@ -448,6 +448,11 @@ config PANEL_BOOT_MESSAGE
 choice
        prompt "Backlight initial state"
        default CHARLCD_BL_FLASH
+       ---help---
+         Select the initial backlight state on boot or module load.
+
+         Previously, there was no option for this: the backlight flashed
+         briefly on init. Now you can also turn it off/on.
 
        config CHARLCD_BL_OFF
                bool "Off"
index 92745efefb540e5d723f5bbaa3aefd11735b0f29..bef6b85778b6e2e04056fac1de5f1e9e56f834c4 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <generated/utsrelease.h>
 
-#include <misc/charlcd.h>
+#include "charlcd.h"
 
 #define LCD_MINOR              156
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
new file mode 100644 (file)
index 0000000..00911ad
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Character LCD driver for Linux
+ *
+ * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
+ * Copyright (C) 2016-2017 Glider bvba
+ */
+
+#ifndef _CHARLCD_H
+#define _CHARLCD_H
+
+struct charlcd {
+       const struct charlcd_ops *ops;
+       const unsigned char *char_conv; /* Optional */
+
+       int ifwidth;                    /* 4-bit or 8-bit (default) */
+       int height;
+       int width;
+       int bwidth;                     /* Default set by charlcd_alloc() */
+       int hwidth;                     /* Default set by charlcd_alloc() */
+
+       void *drvdata;                  /* Set by charlcd_alloc() */
+};
+
+struct charlcd_ops {
+       /* Required */
+       void (*write_cmd)(struct charlcd *lcd, int cmd);
+       void (*write_data)(struct charlcd *lcd, int data);
+
+       /* Optional */
+       void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
+       void (*clear_fast)(struct charlcd *lcd);
+       void (*backlight)(struct charlcd *lcd, int on);
+};
+
+struct charlcd *charlcd_alloc(unsigned int drvdata_size);
+void charlcd_free(struct charlcd *lcd);
+
+int charlcd_register(struct charlcd *lcd);
+int charlcd_unregister(struct charlcd *lcd);
+
+void charlcd_poke(struct charlcd *lcd);
+
+#endif /* CHARLCD_H */
index ab15b64707ad22ef429a7ee6911d72ec9a284bd5..bcbe1309232760235239d94479f23e076a76cd9f 100644 (file)
@@ -14,8 +14,7 @@
 #include <linux/property.h>
 #include <linux/slab.h>
 
-#include <misc/charlcd.h>
-
+#include "charlcd.h"
 
 enum hd44780_pin {
        /* Order does matter due to writing to GPIO array subsets! */
index 9c0bb771751d8d986b7f53d1724f1077f9412a1f..a2fcde582e2a1614d21f0edf21faee4870668b5a 100644 (file)
@@ -74,7 +74,7 @@ struct ht16k33_priv {
        struct ht16k33_fbdev fbdev;
 };
 
-static struct fb_fix_screeninfo ht16k33_fb_fix = {
+static const struct fb_fix_screeninfo ht16k33_fb_fix = {
        .id             = DRIVER_NAME,
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_MONO10,
@@ -85,7 +85,7 @@ static struct fb_fix_screeninfo ht16k33_fb_fix = {
        .accel          = FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo ht16k33_fb_var = {
+static const struct fb_var_screeninfo ht16k33_fb_var = {
        .xres = HT16K33_MATRIX_LED_MAX_ROWS,
        .yres = HT16K33_MATRIX_LED_MAX_COLS,
        .xres_virtual = HT16K33_MATRIX_LED_MAX_ROWS,
index e06de63497cf8f00edde8d2d7bcffa5b25cc8e81..85965953683e4cf78e58081c1f8eb17107a74df1 100644 (file)
@@ -55,7 +55,7 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <misc/charlcd.h>
+#include "charlcd.h"
 
 #define KEYPAD_MINOR           185
 
@@ -1617,6 +1617,8 @@ static void panel_attach(struct parport *port)
        return;
 
 err_lcd_unreg:
+       if (scan_timer.function)
+               del_timer_sync(&scan_timer);
        if (lcd.enabled)
                charlcd_unregister(lcd.charlcd);
 err_unreg_device:
index da84a73f2ba63b6ecfa6d84483770ceb32db0e93..1669d41fcddccde2cfbb35f1ccc7be37ef0b3dc0 100644 (file)
@@ -1663,6 +1663,9 @@ void device_initialize(struct device *dev)
        kobject_init(&dev->kobj, &device_ktype);
        INIT_LIST_HEAD(&dev->dma_pools);
        mutex_init(&dev->mutex);
+#ifdef CONFIG_PROVE_LOCKING
+       mutex_init(&dev->lockdep_mutex);
+#endif
        lockdep_set_novalidate_class(&dev->mutex);
        spin_lock_init(&dev->devres_lock);
        INIT_LIST_HEAD(&dev->devres_head);
@@ -1820,12 +1823,63 @@ static inline struct kobject *get_glue_dir(struct device *dev)
  */
 static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
 {
+       unsigned int ref;
+
        /* see if we live in a "glue" directory */
        if (!live_in_glue_dir(glue_dir, dev))
                return;
 
        mutex_lock(&gdp_mutex);
-       if (!kobject_has_children(glue_dir))
+       /**
+        * There is a race condition between removing glue directory
+        * and adding a new device under the glue directory.
+        *
+        * CPU1:                                         CPU2:
+        *
+        * device_add()
+        *   get_device_parent()
+        *     class_dir_create_and_add()
+        *       kobject_add_internal()
+        *         create_dir()    // create glue_dir
+        *
+        *                                               device_add()
+        *                                                 get_device_parent()
+        *                                                   kobject_get() // get glue_dir
+        *
+        * device_del()
+        *   cleanup_glue_dir()
+        *     kobject_del(glue_dir)
+        *
+        *                                               kobject_add()
+        *                                                 kobject_add_internal()
+        *                                                   create_dir() // in glue_dir
+        *                                                     sysfs_create_dir_ns()
+        *                                                       kernfs_create_dir_ns(sd)
+        *
+        *       sysfs_remove_dir() // glue_dir->sd=NULL
+        *       sysfs_put()        // free glue_dir->sd
+        *
+        *                                                         // sd is freed
+        *                                                         kernfs_new_node(sd)
+        *                                                           kernfs_get(glue_dir)
+        *                                                           kernfs_add_one()
+        *                                                           kernfs_put()
+        *
+        * Before CPU1 remove last child device under glue dir, if CPU2 add
+        * a new device under glue dir, the glue_dir kobject reference count
+        * will be increase to 2 in kobject_get(k). And CPU2 has been called
+        * kernfs_create_dir_ns(). Meanwhile, CPU1 call sysfs_remove_dir()
+        * and sysfs_put(). This result in glue_dir->sd is freed.
+        *
+        * Then the CPU2 will see a stale "empty" but still potentially used
+        * glue dir around in kernfs_new_node().
+        *
+        * In order to avoid this happening, we also should make sure that
+        * kernfs_node for glue_dir is released in CPU1 only when refcount
+        * for glue_dir kobj is 1.
+        */
+       ref = kref_read(&glue_dir->kref);
+       if (!kobject_has_children(glue_dir) && !--ref)
                kobject_del(glue_dir);
        kobject_put(glue_dir);
        mutex_unlock(&gdp_mutex);
@@ -2211,6 +2265,24 @@ void put_device(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(put_device);
 
+bool kill_device(struct device *dev)
+{
+       /*
+        * Require the device lock and set the "dead" flag to guarantee that
+        * the update behavior is consistent with the other bitfields near
+        * it and that we cannot have an asynchronous probe routine trying
+        * to run while we are tearing out the bus/class/sysfs from
+        * underneath the device.
+        */
+       lockdep_assert_held(&dev->mutex);
+
+       if (dev->p->dead)
+               return false;
+       dev->p->dead = true;
+       return true;
+}
+EXPORT_SYMBOL_GPL(kill_device);
+
 /**
  * device_del - delete device from system.
  * @dev: device.
@@ -2230,15 +2302,8 @@ void device_del(struct device *dev)
        struct kobject *glue_dir = NULL;
        struct class_interface *class_intf;
 
-       /*
-        * Hold the device lock and set the "dead" flag to guarantee that
-        * the update behavior is consistent with the other bitfields near
-        * it and that we cannot have an asynchronous probe routine trying
-        * to run while we are tearing out the bus/class/sysfs from
-        * underneath the device.
-        */
        device_lock(dev);
-       dev->p->dead = true;
+       kill_device(dev);
        device_unlock(dev);
 
        /* Notify clients of device removal.  This call must come
index 7048a41973edabc15cf04c11a44063fc0f2b984e..7ecd590e67fe1f11829d6aa6bd3fd78b21f04497 100644 (file)
@@ -141,8 +141,8 @@ int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed);
 int fw_map_paged_buf(struct fw_priv *fw_priv);
 #else
 static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {}
-int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
-int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
+static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
+static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
 #endif
 
 #endif /* __FIRMWARE_LOADER_H */
index 506a0175a5a781cf297cc0153038dc4aa9b48d86..ec974ba9c0c4ca93a3b1cfcaf541c6e4a4a3bd9c 100644 (file)
@@ -157,8 +157,13 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
         * the device will only expose one IRQ, and this fallback
         * allows a common code path across either kind of resource.
         */
-       if (num == 0 && has_acpi_companion(&dev->dev))
-               return acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num);
+       if (num == 0 && has_acpi_companion(&dev->dev)) {
+               int ret = acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num);
+
+               /* Our callers expect -ENXIO for missing IRQs. */
+               if (ret >= 0 || ret == -EPROBE_DEFER)
+                       return ret;
+       }
 
        return -ENXIO;
 #endif
index a4984136c19d50d61ec5ab23bcaa2916bdc91d55..0fd6f97ee523fdec13623b859d76dc1dd3d0e355 100644 (file)
@@ -44,7 +44,7 @@ config REGMAP_IRQ
 
 config REGMAP_SOUNDWIRE
        tristate
-       depends on SOUNDWIRE_BUS
+       depends on SOUNDWIRE
 
 config REGMAP_SCCB
        tristate
index 5b49f1b33ebec4cff30ec71347c97f119041b351..e2ea2356da0610c6872724e0295e4f8335ded013 100644 (file)
@@ -323,10 +323,14 @@ flush(const char __user *str, size_t cnt, int exiting)
        }
 
        flush_scheduled_work();
-       /* pass one: without sleeping, do aoedev_downdev */
+       /* pass one: do aoedev_downdev, which might sleep */
+restart1:
        spin_lock_irqsave(&devlist_lock, flags);
        for (d = devlist; d; d = d->next) {
                spin_lock(&d->lock);
+               if (d->flags & DEVFL_TKILL)
+                       goto cont;
+
                if (exiting) {
                        /* unconditionally take each device down */
                } else if (specified) {
@@ -338,8 +342,11 @@ flush(const char __user *str, size_t cnt, int exiting)
                || d->ref)
                        goto cont;
 
+               spin_unlock(&d->lock);
+               spin_unlock_irqrestore(&devlist_lock, flags);
                aoedev_downdev(d);
                d->flags |= DEVFL_TKILL;
+               goto restart1;
 cont:
                spin_unlock(&d->lock);
        }
@@ -348,7 +355,7 @@ cont:
        /* pass two: call freedev, which might sleep,
         * for aoedevs marked with DEVFL_TKILL
         */
-restart:
+restart2:
        spin_lock_irqsave(&devlist_lock, flags);
        for (d = devlist; d; d = d->next) {
                spin_lock(&d->lock);
@@ -357,7 +364,7 @@ restart:
                        spin_unlock(&d->lock);
                        spin_unlock_irqrestore(&devlist_lock, flags);
                        freedev(d);
-                       goto restart;
+                       goto restart2;
                }
                spin_unlock(&d->lock);
        }
index 85f20e371f2fadd32b9820d9b7cbd912aeba2a71..bd7d3bb8b890b187bf94d19e78562d0868a3ee85 100644 (file)
@@ -1726,6 +1726,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
                /* MSch: invalidate default_params */
                default_params[drive].blocks  = 0;
                set_capacity(floppy->disk, MAX_DISK_SIZE * 2);
+               /* Fall through */
        case FDFMTEND:
        case FDFLUSH:
                /* invalidate the buffer track to force a reread */
index 9bd4ddd12b25c542ae9fad6fae963f66414b496c..5b248763a672414e925f217216fc21c9a2a257fb 100644 (file)
@@ -322,6 +322,8 @@ static int drbd_thread_setup(void *arg)
                 thi->name[0],
                 resource->name);
 
+       allow_kernel_signal(DRBD_SIGKILL);
+       allow_kernel_signal(SIGXCPU);
 restart:
        retval = thi->function(thi);
 
index 90ebfcae0ce6e70dafed014f489a4e20e0d8876b..2b3103c308573a5398237bd90d78c6957108ce08 100644 (file)
@@ -5417,7 +5417,7 @@ static int drbd_do_auth(struct drbd_connection *connection)
        unsigned int key_len;
        char secret[SHARED_SECRET_MAX]; /* 64 byte */
        unsigned int resp_size;
-       SHASH_DESC_ON_STACK(desc, connection->cram_hmac_tfm);
+       struct shash_desc *desc;
        struct packet_info pi;
        struct net_conf *nc;
        int err, rv;
@@ -5430,6 +5430,13 @@ static int drbd_do_auth(struct drbd_connection *connection)
        memcpy(secret, nc->shared_secret, key_len);
        rcu_read_unlock();
 
+       desc = kmalloc(sizeof(struct shash_desc) +
+                      crypto_shash_descsize(connection->cram_hmac_tfm),
+                      GFP_KERNEL);
+       if (!desc) {
+               rv = -1;
+               goto fail;
+       }
        desc->tfm = connection->cram_hmac_tfm;
 
        rv = crypto_shash_setkey(connection->cram_hmac_tfm, (u8 *)secret, key_len);
@@ -5571,7 +5578,10 @@ static int drbd_do_auth(struct drbd_connection *connection)
        kfree(peers_ch);
        kfree(response);
        kfree(right_response);
-       shash_desc_zero(desc);
+       if (desc) {
+               shash_desc_zero(desc);
+               kfree(desc);
+       }
 
        return rv;
 }
index 44c9985f352abd0cfb4ddda003302e09f76ce4bd..ab7ca5989097ac70372f77f4fb60964a98c98177 100644 (file)
@@ -885,7 +885,7 @@ static void loop_unprepare_queue(struct loop_device *lo)
 
 static int loop_kthread_worker_fn(void *worker_ptr)
 {
-       current->flags |= PF_LESS_THROTTLE;
+       current->flags |= PF_LESS_THROTTLE | PF_MEMALLOC_NOIO;
        return kthread_worker_fn(worker_ptr);
 }
 
@@ -924,6 +924,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
        struct file     *file;
        struct inode    *inode;
        struct address_space *mapping;
+       struct block_device *claimed_bdev = NULL;
        int             lo_flags = 0;
        int             error;
        loff_t          size;
@@ -942,10 +943,11 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
         * here to avoid changing device under exclusive owner.
         */
        if (!(mode & FMODE_EXCL)) {
-               bdgrab(bdev);
-               error = blkdev_get(bdev, mode | FMODE_EXCL, loop_set_fd);
-               if (error)
+               claimed_bdev = bd_start_claiming(bdev, loop_set_fd);
+               if (IS_ERR(claimed_bdev)) {
+                       error = PTR_ERR(claimed_bdev);
                        goto out_putf;
+               }
        }
 
        error = mutex_lock_killable(&loop_ctl_mutex);
@@ -1015,15 +1017,15 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
        mutex_unlock(&loop_ctl_mutex);
        if (partscan)
                loop_reread_partitions(lo, bdev);
-       if (!(mode & FMODE_EXCL))
-               blkdev_put(bdev, mode | FMODE_EXCL);
+       if (claimed_bdev)
+               bd_abort_claiming(bdev, claimed_bdev, loop_set_fd);
        return 0;
 
 out_unlock:
        mutex_unlock(&loop_ctl_mutex);
 out_bdev:
-       if (!(mode & FMODE_EXCL))
-               blkdev_put(bdev, mode | FMODE_EXCL);
+       if (claimed_bdev)
+               bd_abort_claiming(bdev, claimed_bdev, loop_set_fd);
 out_putf:
        fput(file);
 out:
index 9bcde2325893183167dcaed84f299af777d62a39..e21d2ded732b735c13f7ebbd02533ed081afe0ca 100644 (file)
@@ -1231,7 +1231,7 @@ static void nbd_clear_sock_ioctl(struct nbd_device *nbd,
                                 struct block_device *bdev)
 {
        sock_shutdown(nbd);
-       kill_bdev(bdev);
+       __invalidate_device(bdev, true);
        nbd_bdev_reset(bdev);
        if (test_and_clear_bit(NBD_HAS_CONFIG_REF,
                               &nbd->config->runtime_flags))
index 3327192bb71f73c9e4f4500203f39d8c1de01a0a..c8fb886aebd4e9ea569203c446cf537c756026d0 100644 (file)
@@ -3038,6 +3038,17 @@ again:
                }
                return true;
        case RBD_OBJ_READ_PARENT:
+               /*
+                * The parent image is read only up to the overlap -- zero-fill
+                * from the overlap to the end of the request.
+                */
+               if (!*result) {
+                       u32 obj_overlap = rbd_obj_img_extents_bytes(obj_req);
+
+                       if (obj_overlap < obj_req->ex.oe_len)
+                               rbd_obj_zero_range(obj_req, obj_overlap,
+                                           obj_req->ex.oe_len - obj_overlap);
+               }
                return true;
        default:
                BUG();
index 3ac6a5d18071729a7747a72835223f02234e240f..b90dbcd99c03e9c4e1ae0bc5f22180b80c5903e1 100644 (file)
@@ -965,6 +965,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
                }
        }
 
+       err = -ENOMEM;
        for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) {
                req = kzalloc(sizeof(*req), GFP_KERNEL);
                if (!req)
@@ -987,7 +988,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
        err = xen_blkif_map(ring, ring_ref, nr_grefs, evtchn);
        if (err) {
                xenbus_dev_fatal(dev, err, "mapping ring-ref port %u", evtchn);
-               return err;
+               goto fail;
        }
 
        return 0;
@@ -1007,8 +1008,7 @@ fail:
                }
                kfree(req);
        }
-       return -ENOMEM;
-
+       return err;
 }
 
 static int connect_ring(struct backend_info *be)
index a0e84538cec88bfb7b80ee0dae4cef69282b589f..1fa58c059cbf5c6e115ccf5c3970b1165afe89b2 100644 (file)
@@ -337,7 +337,7 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 
        usb_free_urb(urb);
 
-       return 0;
+       return err;
 }
 
 static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
index 8b33128dccee1a0d26965b889190ca37e8d8372d..0875470a7806f8658c45b2b4a15f6e2b029bf0c2 100644 (file)
@@ -99,6 +99,27 @@ static int qca_send_reset(struct hci_dev *hdev)
        return 0;
 }
 
+int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+{
+       struct sk_buff *skb;
+       int err;
+
+       bt_dev_dbg(hdev, "QCA pre shutdown cmd");
+
+       skb = __hci_cmd_sync(hdev, QCA_PRE_SHUTDOWN_CMD, 0,
+                               NULL, HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               err = PTR_ERR(skb);
+               bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err);
+               return err;
+       }
+
+       kfree_skb(skb);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
+
 static void qca_tlv_check_data(struct rome_config *config,
                                const struct firmware *fw)
 {
@@ -119,6 +140,7 @@ static void qca_tlv_check_data(struct rome_config *config,
        BT_DBG("Length\t\t : %d bytes", length);
 
        config->dnld_mode = ROME_SKIP_EVT_NONE;
+       config->dnld_type = ROME_SKIP_EVT_NONE;
 
        switch (config->type) {
        case TLV_TYPE_PATCH:
@@ -268,7 +290,7 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev)
 
        evt = skb_put(skb, sizeof(*evt));
        evt->ncmd = 1;
-       evt->opcode = QCA_HCI_CC_OPCODE;
+       evt->opcode = cpu_to_le16(QCA_HCI_CC_OPCODE);
 
        skb_put_u8(skb, QCA_HCI_CC_SUCCESS);
 
@@ -323,7 +345,7 @@ static int qca_download_firmware(struct hci_dev *hdev,
         */
        if (config->dnld_type == ROME_SKIP_EVT_VSE_CC ||
            config->dnld_type == ROME_SKIP_EVT_VSE)
-               return qca_inject_cmd_complete_event(hdev);
+               ret = qca_inject_cmd_complete_event(hdev);
 
 out:
        release_firmware(fw);
@@ -388,6 +410,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                return err;
        }
 
+       /* Give the controller some time to get ready to receive the NVM */
+       msleep(10);
+
        /* Download NVM configuration */
        config.type = TLV_TYPE_NVM;
        if (firmware_name)
index 6a291a7a5d9658c1987cf8c01ad34c47e3d4bfc9..69c5315a65fd2630346591e5df2d3faf51690099 100644 (file)
@@ -13,6 +13,7 @@
 #define EDL_PATCH_TLV_REQ_CMD          (0x1E)
 #define EDL_NVM_ACCESS_SET_REQ_CMD     (0x01)
 #define MAX_SIZE_PER_TLV_SEGMENT       (243)
+#define QCA_PRE_SHUTDOWN_CMD           (0xFC08)
 
 #define EDL_CMD_REQ_RES_EVT            (0x00)
 #define EDL_PATCH_VER_RES_EVT          (0x19)
@@ -135,6 +136,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                   const char *firmware_name);
 int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
 int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+int qca_send_pre_shutdown_cmd(struct hci_dev *hdev);
 static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
 {
        return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998;
@@ -167,4 +169,9 @@ static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
 {
        return false;
 }
+
+static inline int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+{
+       return -EOPNOTSUPP;
+}
 #endif
index 3876fee6ad13fa617858d9b1da34ba5b43da13c9..ba41490543040a723bbdb868626225be0612846d 100644 (file)
@@ -384,6 +384,9 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x13d3, 0x3526), .driver_info = BTUSB_REALTEK },
        { USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
 
+       /* Additional Realtek 8822CE Bluetooth devices */
+       { USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK },
+
        /* Silicon Wave based devices */
        { USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
 
@@ -1170,10 +1173,6 @@ static int btusb_open(struct hci_dev *hdev)
        }
 
        data->intf->needs_remote_wakeup = 1;
-       /* device specific wakeup source enabled and required for USB
-        * remote wakeup while host is suspended
-        */
-       device_wakeup_enable(&data->udev->dev);
 
        if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
                goto done;
@@ -1238,7 +1237,6 @@ static int btusb_close(struct hci_dev *hdev)
                goto failed;
 
        data->intf->needs_remote_wakeup = 0;
-       device_wakeup_disable(&data->udev->dev);
        usb_autopm_put_interface(data->intf);
 
 failed:
@@ -2762,8 +2760,10 @@ static int btusb_mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
        fw_size = fw->size;
 
        /* The size of patch header is 30 bytes, should be skip */
-       if (fw_size < 30)
+       if (fw_size < 30) {
+               err = -EINVAL;
                goto err_release_fw;
+       }
 
        fw_size -= 30;
        fw_ptr += 30;
index a55be205b91a3ebfc843849c345d3b8a91745015..dbfe34664633a1c4783d359ad9b0eb5971c15430 100644 (file)
@@ -98,6 +98,9 @@ static int ath_open(struct hci_uart *hu)
 
        BT_DBG("hu %p", hu);
 
+       if (!hci_uart_has_flow_control(hu))
+               return -EOPNOTSUPP;
+
        ath = kzalloc(sizeof(*ath), GFP_KERNEL);
        if (!ath)
                return -ENOMEM;
index 8905ad2edde743742f9706fccfd7350d5fb2709e..ae2624fce913471bf4c8b4a25f90fcffc0a8b965 100644 (file)
@@ -406,6 +406,9 @@ static int bcm_open(struct hci_uart *hu)
 
        bt_dev_dbg(hu->hdev, "hu %p", hu);
 
+       if (!hci_uart_has_flow_control(hu))
+               return -EOPNOTSUPP;
+
        bcm = kzalloc(sizeof(*bcm), GFP_KERNEL);
        if (!bcm)
                return -ENOMEM;
index 207bae5e0d4631b7b398d8b6d59dc912c4004eed..31f25153087d760a4ed872da5b830ee9ff29c496 100644 (file)
@@ -391,6 +391,9 @@ static int intel_open(struct hci_uart *hu)
 
        BT_DBG("hu %p", hu);
 
+       if (!hci_uart_has_flow_control(hu))
+               return -EOPNOTSUPP;
+
        intel = kzalloc(sizeof(*intel), GFP_KERNEL);
        if (!intel)
                return -ENOMEM;
index 8950e07889fef64c75103d68e27688a54b995c85..85a30fb9177bbe719666d9e00f63e219f3ef3f49 100644 (file)
@@ -292,6 +292,19 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
        return 0;
 }
 
+/* Check the underlying device or tty has flow control support */
+bool hci_uart_has_flow_control(struct hci_uart *hu)
+{
+       /* serdev nodes check if the needed operations are present */
+       if (hu->serdev)
+               return true;
+
+       if (hu->tty->driver->ops->tiocmget && hu->tty->driver->ops->tiocmset)
+               return true;
+
+       return false;
+}
+
 /* Flow control or un-flow control the device */
 void hci_uart_set_flow_control(struct hci_uart *hu, bool enable)
 {
index f98e5cc343b21c22f7c054da0b315d9995cf818f..fbc3f7c3a5c710c0493a66111b7a7dedb7d664fd 100644 (file)
@@ -59,6 +59,9 @@ static int mrvl_open(struct hci_uart *hu)
 
        BT_DBG("hu %p", hu);
 
+       if (!hci_uart_has_flow_control(hu))
+               return -EOPNOTSUPP;
+
        mrvl = kzalloc(sizeof(*mrvl), GFP_KERNEL);
        if (!mrvl)
                return -ENOMEM;
index 9a5c9c1f9484822a69357c40533649c72027f7da..31dec435767be3757adcfeadad1ce2cfbcad620a 100644 (file)
@@ -309,13 +309,14 @@ static void qca_wq_awake_device(struct work_struct *work)
                                            ws_awake_device);
        struct hci_uart *hu = qca->hu;
        unsigned long retrans_delay;
+       unsigned long flags;
 
        BT_DBG("hu %p wq awake device", hu);
 
        /* Vote for serial clock */
        serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
 
-       spin_lock(&qca->hci_ibs_lock);
+       spin_lock_irqsave(&qca->hci_ibs_lock, flags);
 
        /* Send wake indication to device */
        if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
@@ -327,7 +328,7 @@ static void qca_wq_awake_device(struct work_struct *work)
        retrans_delay = msecs_to_jiffies(qca->wake_retrans);
        mod_timer(&qca->wake_retrans_timer, jiffies + retrans_delay);
 
-       spin_unlock(&qca->hci_ibs_lock);
+       spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
 
        /* Actually send the packets */
        hci_uart_tx_wakeup(hu);
@@ -338,12 +339,13 @@ static void qca_wq_awake_rx(struct work_struct *work)
        struct qca_data *qca = container_of(work, struct qca_data,
                                            ws_awake_rx);
        struct hci_uart *hu = qca->hu;
+       unsigned long flags;
 
        BT_DBG("hu %p wq awake rx", hu);
 
        serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
 
-       spin_lock(&qca->hci_ibs_lock);
+       spin_lock_irqsave(&qca->hci_ibs_lock, flags);
        qca->rx_ibs_state = HCI_IBS_RX_AWAKE;
 
        /* Always acknowledge device wake up,
@@ -354,7 +356,7 @@ static void qca_wq_awake_rx(struct work_struct *work)
 
        qca->ibs_sent_wacks++;
 
-       spin_unlock(&qca->hci_ibs_lock);
+       spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
 
        /* Actually send the packets */
        hci_uart_tx_wakeup(hu);
@@ -473,6 +475,9 @@ static int qca_open(struct hci_uart *hu)
 
        BT_DBG("hu %p qca_open", hu);
 
+       if (!hci_uart_has_flow_control(hu))
+               return -EOPNOTSUPP;
+
        qca = kzalloc(sizeof(struct qca_data), GFP_KERNEL);
        if (!qca)
                return -ENOMEM;
@@ -702,7 +707,7 @@ static void device_want_to_sleep(struct hci_uart *hu)
        unsigned long flags;
        struct qca_data *qca = hu->priv;
 
-       BT_DBG("hu %p want to sleep", hu);
+       BT_DBG("hu %p want to sleep in %d state", hu, qca->rx_ibs_state);
 
        spin_lock_irqsave(&qca->hci_ibs_lock, flags);
 
@@ -717,7 +722,7 @@ static void device_want_to_sleep(struct hci_uart *hu)
                break;
 
        case HCI_IBS_RX_ASLEEP:
-               /* Fall through */
+               break;
 
        default:
                /* Any other state is illegal */
@@ -909,7 +914,7 @@ static int qca_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
                if (hdr->evt == HCI_EV_VENDOR)
                        complete(&qca->drop_ev_comp);
 
-               kfree(skb);
+               kfree_skb(skb);
 
                return 0;
        }
@@ -1383,6 +1388,9 @@ static int qca_power_off(struct hci_dev *hdev)
 {
        struct hci_uart *hu = hci_get_drvdata(hdev);
 
+       /* Perform pre shutdown command */
+       qca_send_pre_shutdown_cmd(hdev);
+
        qca_power_shutdown(hu);
        return 0;
 }
index f11af3912ce6c16fd92720e8dccd53d5f3933589..6ab631101019c4198d24266936c179c262501c03 100644 (file)
@@ -104,6 +104,7 @@ int hci_uart_wait_until_sent(struct hci_uart *hu);
 int hci_uart_init_ready(struct hci_uart *hu);
 void hci_uart_init_work(struct work_struct *work);
 void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed);
+bool hci_uart_has_flow_control(struct hci_uart *hu);
 void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
 void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
                         unsigned int oper_speed);
index 19d7b6ff2f1793b23d1e80507d733b4de3f8d9b8..20c957185af203ff6e5dbc0e466198188ed3bfb1 100644 (file)
@@ -456,6 +456,17 @@ struct hisi_lpc_acpi_cell {
        size_t pdata_size;
 };
 
+static void hisi_lpc_acpi_remove(struct device *hostdev)
+{
+       struct acpi_device *adev = ACPI_COMPANION(hostdev);
+       struct acpi_device *child;
+
+       device_for_each_child(hostdev, NULL, hisi_lpc_acpi_remove_subdev);
+
+       list_for_each_entry(child, &adev->children, node)
+               acpi_device_clear_enumerated(child);
+}
+
 /*
  * hisi_lpc_acpi_probe - probe children for ACPI FW
  * @hostdev: LPC host device pointer
@@ -555,8 +566,7 @@ static int hisi_lpc_acpi_probe(struct device *hostdev)
        return 0;
 
 fail:
-       device_for_each_child(hostdev, NULL,
-                             hisi_lpc_acpi_remove_subdev);
+       hisi_lpc_acpi_remove(hostdev);
        return ret;
 }
 
@@ -569,6 +579,10 @@ static int hisi_lpc_acpi_probe(struct device *dev)
 {
        return -ENODEV;
 }
+
+static void hisi_lpc_acpi_remove(struct device *hostdev)
+{
+}
 #endif // CONFIG_ACPI
 
 /*
@@ -606,24 +620,27 @@ static int hisi_lpc_probe(struct platform_device *pdev)
        range->fwnode = dev->fwnode;
        range->flags = LOGIC_PIO_INDIRECT;
        range->size = PIO_INDIRECT_SIZE;
+       range->hostdata = lpcdev;
+       range->ops = &hisi_lpc_ops;
+       lpcdev->io_host = range;
 
        ret = logic_pio_register_range(range);
        if (ret) {
                dev_err(dev, "register IO range failed (%d)!\n", ret);
                return ret;
        }
-       lpcdev->io_host = range;
 
        /* register the LPC host PIO resources */
        if (acpi_device)
                ret = hisi_lpc_acpi_probe(dev);
        else
                ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
-       if (ret)
+       if (ret) {
+               logic_pio_unregister_range(range);
                return ret;
+       }
 
-       lpcdev->io_host->hostdata = lpcdev;
-       lpcdev->io_host->ops = &hisi_lpc_ops;
+       dev_set_drvdata(dev, lpcdev);
 
        io_end = lpcdev->io_host->io_start + lpcdev->io_host->size;
        dev_info(dev, "registered range [%pa - %pa]\n",
@@ -632,6 +649,23 @@ static int hisi_lpc_probe(struct platform_device *pdev)
        return ret;
 }
 
+static int hisi_lpc_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct acpi_device *acpi_device = ACPI_COMPANION(dev);
+       struct hisi_lpc_dev *lpcdev = dev_get_drvdata(dev);
+       struct logic_pio_hwaddr *range = lpcdev->io_host;
+
+       if (acpi_device)
+               hisi_lpc_acpi_remove(dev);
+       else
+               of_platform_depopulate(dev);
+
+       logic_pio_unregister_range(range);
+
+       return 0;
+}
+
 static const struct of_device_id hisi_lpc_of_match[] = {
        { .compatible = "hisilicon,hip06-lpc", },
        { .compatible = "hisilicon,hip07-lpc", },
@@ -645,5 +679,6 @@ static struct platform_driver hisi_lpc_driver = {
                .acpi_match_table = ACPI_PTR(hisi_lpc_acpi_match),
        },
        .probe = hisi_lpc_probe,
+       .remove = hisi_lpc_remove,
 };
 builtin_platform_driver(hisi_lpc_driver);
index e6deabd8305d789a9942988f26b6aa584cae2e46..2db474ab4c6bea105a5f355f9036d3f7027b3143 100644 (file)
@@ -949,7 +949,7 @@ static int sysc_best_idle_mode(u32 idlemodes, u32 *best_mode)
                *best_mode = SYSC_IDLE_SMART_WKUP;
        else if (idlemodes & BIT(SYSC_IDLE_SMART))
                *best_mode = SYSC_IDLE_SMART;
-       else if (idlemodes & SYSC_IDLE_FORCE)
+       else if (idlemodes & BIT(SYSC_IDLE_FORCE))
                *best_mode = SYSC_IDLE_FORCE;
        else
                return -EINVAL;
@@ -1267,7 +1267,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
        SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0),
        SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902,
                   0xffff00f0, 0),
-       SYSC_QUIRK("dcan", 0, 0, -1, -1, 0xffffffff, 0xffffffff, 0),
+       SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0xa3170504, 0xffffffff, 0),
+       SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0x4edb1902, 0xffffffff, 0),
        SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0),
        SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
        SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
@@ -1692,10 +1693,7 @@ static int sysc_init_sysc_mask(struct sysc *ddata)
        if (error)
                return 0;
 
-       if (val)
-               ddata->cfg.sysc_val = val & ddata->cap->sysc_mask;
-       else
-               ddata->cfg.sysc_val = ddata->cap->sysc_mask;
+       ddata->cfg.sysc_val = val & ddata->cap->sysc_mask;
 
        return 0;
 }
@@ -2385,27 +2383,27 @@ static int sysc_probe(struct platform_device *pdev)
 
        error = sysc_init_dts_quirks(ddata);
        if (error)
-               goto unprepare;
+               return error;
 
        error = sysc_map_and_check_registers(ddata);
        if (error)
-               goto unprepare;
+               return error;
 
        error = sysc_init_sysc_mask(ddata);
        if (error)
-               goto unprepare;
+               return error;
 
        error = sysc_init_idlemodes(ddata);
        if (error)
-               goto unprepare;
+               return error;
 
        error = sysc_init_syss_mask(ddata);
        if (error)
-               goto unprepare;
+               return error;
 
        error = sysc_init_pdata(ddata);
        if (error)
-               goto unprepare;
+               return error;
 
        sysc_init_early_quirks(ddata);
 
@@ -2415,7 +2413,7 @@ static int sysc_probe(struct platform_device *pdev)
 
        error = sysc_init_resets(ddata);
        if (error)
-               return error;
+               goto unprepare;
 
        error = sysc_init_module(ddata);
        if (error)
index 5c39f20378b88eb695b676c1c121992c46d37454..9ac6671bb5141f3daa335a72a6beeaff69158e53 100644 (file)
@@ -567,8 +567,7 @@ static inline unsigned long hpet_time_div(struct hpets *hpets,
        unsigned long long m;
 
        m = hpets->hp_tick_freq + (dis >> 1);
-       do_div(m, dis);
-       return (unsigned long)m;
+       return div64_ul(m, dis);
 }
 
 static int
index 57204335c5f556a47f79a6748d72b4a92e2a57ca..285e0b8f9a9744b88e4f6358dbef11c8439e6f7e 100644 (file)
@@ -76,7 +76,7 @@ static ssize_t ipmb_read(struct file *file, char __user *buf, size_t count,
        struct ipmb_dev *ipmb_dev = to_ipmb_dev(file);
        struct ipmb_request_elem *queue_elem;
        struct ipmb_msg msg;
-       ssize_t ret;
+       ssize_t ret = 0;
 
        memset(&msg, 0, sizeof(msg));
 
index d47ad10a35fe3362156fbdb15038eb4fda661a97..4838c6a9f0f2c702e932066fba62d7a336a87f36 100644 (file)
@@ -77,6 +77,18 @@ static int tpm_go_idle(struct tpm_chip *chip)
        return chip->ops->go_idle(chip);
 }
 
+static void tpm_clk_enable(struct tpm_chip *chip)
+{
+       if (chip->ops->clk_enable)
+               chip->ops->clk_enable(chip, true);
+}
+
+static void tpm_clk_disable(struct tpm_chip *chip)
+{
+       if (chip->ops->clk_enable)
+               chip->ops->clk_enable(chip, false);
+}
+
 /**
  * tpm_chip_start() - power on the TPM
  * @chip:      a TPM chip to use
@@ -89,13 +101,12 @@ int tpm_chip_start(struct tpm_chip *chip)
 {
        int ret;
 
-       if (chip->ops->clk_enable)
-               chip->ops->clk_enable(chip, true);
+       tpm_clk_enable(chip);
 
        if (chip->locality == -1) {
                ret = tpm_request_locality(chip);
                if (ret) {
-                       chip->ops->clk_enable(chip, false);
+                       tpm_clk_disable(chip);
                        return ret;
                }
        }
@@ -103,8 +114,7 @@ int tpm_chip_start(struct tpm_chip *chip)
        ret = tpm_cmd_ready(chip);
        if (ret) {
                tpm_relinquish_locality(chip);
-               if (chip->ops->clk_enable)
-                       chip->ops->clk_enable(chip, false);
+               tpm_clk_disable(chip);
                return ret;
        }
 
@@ -124,8 +134,7 @@ void tpm_chip_stop(struct tpm_chip *chip)
 {
        tpm_go_idle(chip);
        tpm_relinquish_locality(chip);
-       if (chip->ops->clk_enable)
-               chip->ops->clk_enable(chip, false);
+       tpm_clk_disable(chip);
 }
 EXPORT_SYMBOL_GPL(tpm_chip_stop);
 
@@ -545,6 +554,20 @@ static int tpm_add_hwrng(struct tpm_chip *chip)
        return hwrng_register(&chip->hwrng);
 }
 
+static int tpm_get_pcr_allocation(struct tpm_chip *chip)
+{
+       int rc;
+
+       rc = (chip->flags & TPM_CHIP_FLAG_TPM2) ?
+            tpm2_get_pcr_allocation(chip) :
+            tpm1_get_pcr_allocation(chip);
+
+       if (rc > 0)
+               return -ENODEV;
+
+       return rc;
+}
+
 /*
  * tpm_chip_register() - create a character device for the TPM chip
  * @chip: TPM chip to use.
@@ -564,6 +587,12 @@ int tpm_chip_register(struct tpm_chip *chip)
        if (rc)
                return rc;
        rc = tpm_auto_startup(chip);
+       if (rc) {
+               tpm_chip_stop(chip);
+               return rc;
+       }
+
+       rc = tpm_get_pcr_allocation(chip);
        tpm_chip_stop(chip);
        if (rc)
                return rc;
index e503ffc3aa39c7bf187cdd1a08fc5e74d3c7170c..a7fea3e0ca86a992b4c02dc9097eb25b06046230 100644 (file)
@@ -394,6 +394,7 @@ int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf);
 ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
                    const char *desc, size_t min_cap_length);
 int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
+int tpm1_get_pcr_allocation(struct tpm_chip *chip);
 unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
 int tpm_pm_suspend(struct device *dev);
 int tpm_pm_resume(struct device *dev);
@@ -449,6 +450,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
                        u32 *value, const char *desc);
 
+ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
 int tpm2_auto_startup(struct tpm_chip *chip);
 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
index faacbe1ffa1a9016798cb8ab00c5a1ca4879471b..149e953ca3699a97485e3cc8c809c9915f7432be 100644 (file)
@@ -699,18 +699,6 @@ int tpm1_auto_startup(struct tpm_chip *chip)
                goto out;
        }
 
-       chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
-                                       GFP_KERNEL);
-       if (!chip->allocated_banks) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
-       chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
-       chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
-       chip->nr_allocated_banks = 1;
-
        return rc;
 out:
        if (rc > 0)
@@ -779,3 +767,27 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
        return rc;
 }
 
+/**
+ * tpm1_get_pcr_allocation() - initialize the allocated bank
+ * @chip: TPM chip to use.
+ *
+ * The function initializes the SHA1 allocated bank to extend PCR
+ *
+ * Return:
+ * * 0 on success,
+ * * < 0 on error.
+ */
+int tpm1_get_pcr_allocation(struct tpm_chip *chip)
+{
+       chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
+                                       GFP_KERNEL);
+       if (!chip->allocated_banks)
+               return -ENOMEM;
+
+       chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
+       chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
+       chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
+       chip->nr_allocated_banks = 1;
+
+       return 0;
+}
index d103545e40550bd6b1f71048400db8b217b2cd29..ba9acae83bff12d4c10d107e458ae065074d0c20 100644 (file)
@@ -840,7 +840,7 @@ struct tpm2_pcr_selection {
        u8  pcr_select[3];
 } __packed;
 
-static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
+ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
 {
        struct tpm2_pcr_selection pcr_selection;
        struct tpm_buf buf;
@@ -1040,10 +1040,6 @@ int tpm2_auto_startup(struct tpm_chip *chip)
                        goto out;
        }
 
-       rc = tpm2_get_pcr_allocation(chip);
-       if (rc)
-               goto out;
-
        rc = tpm2_get_cc_attrs_tbl(chip);
 
 out:
index 44db83a6d01c265afef52df71b416d126871c8d3..44a46dcc0518b6516764f9a78832a7cbc427f047 100644 (file)
@@ -141,6 +141,8 @@ static int clk_generated_determine_rate(struct clk_hw *hw,
                        continue;
 
                div = DIV_ROUND_CLOSEST(parent_rate, req->rate);
+               if (div > GENERATED_MAX_DIV + 1)
+                       div = GENERATED_MAX_DIV + 1;
 
                clk_generated_best_diff(req, parent, parent_rate, div,
                                        &best_diff, &best_rate);
index c0990703ce5403c1092bda6d982c56dffd70e6a0..1c46babeb09330e8e2a98060ad310fabba65aa2d 100644 (file)
@@ -324,6 +324,25 @@ static struct clk_core *clk_core_lookup(const char *name)
        return NULL;
 }
 
+#ifdef CONFIG_OF
+static int of_parse_clkspec(const struct device_node *np, int index,
+                           const char *name, struct of_phandle_args *out_args);
+static struct clk_hw *
+of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec);
+#else
+static inline int of_parse_clkspec(const struct device_node *np, int index,
+                                  const char *name,
+                                  struct of_phandle_args *out_args)
+{
+       return -ENOENT;
+}
+static inline struct clk_hw *
+of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec)
+{
+       return ERR_PTR(-ENOENT);
+}
+#endif
+
 /**
  * clk_core_get - Find the clk_core parent of a clk
  * @core: clk to find parent of
@@ -355,8 +374,9 @@ static struct clk_core *clk_core_lookup(const char *name)
  *      };
  *
  * Returns: -ENOENT when the provider can't be found or the clk doesn't
- * exist in the provider. -EINVAL when the name can't be found. NULL when the
- * provider knows about the clk but it isn't provided on this system.
+ * exist in the provider or the name can't be found in the DT node or
+ * in a clkdev lookup. NULL when the provider knows about the clk but it
+ * isn't provided on this system.
  * A valid clk_core pointer when the clk can be found in the provider.
  */
 static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
@@ -367,17 +387,19 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
        struct device *dev = core->dev;
        const char *dev_id = dev ? dev_name(dev) : NULL;
        struct device_node *np = core->of_node;
+       struct of_phandle_args clkspec;
 
-       if (np && (name || index >= 0))
-               hw = of_clk_get_hw(np, index, name);
-
-       /*
-        * If the DT search above couldn't find the provider or the provider
-        * didn't know about this clk, fallback to looking up via clkdev based
-        * clk_lookups
-        */
-       if (PTR_ERR(hw) == -ENOENT && name)
+       if (np && (name || index >= 0) &&
+           !of_parse_clkspec(np, index, name, &clkspec)) {
+               hw = of_clk_get_hw_from_clkspec(&clkspec);
+               of_node_put(clkspec.np);
+       } else if (name) {
+               /*
+                * If the DT search above couldn't find the provider fallback to
+                * looking up via clkdev based clk_lookups.
+                */
                hw = clk_find_hw(dev_id, name);
+       }
 
        if (IS_ERR(hw))
                return ERR_CAST(hw);
@@ -401,7 +423,7 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
                        parent = ERR_PTR(-EPROBE_DEFER);
        } else {
                parent = clk_core_get(core, index);
-               if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT)
+               if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT && entry->name)
                        parent = clk_core_lookup(entry->name);
        }
 
@@ -1632,7 +1654,8 @@ static int clk_fetch_parent_index(struct clk_core *core,
                        break;
 
                /* Fallback to comparing globally unique names */
-               if (!strcmp(parent->name, core->parents[i].name))
+               if (core->parents[i].name &&
+                   !strcmp(parent->name, core->parents[i].name))
                        break;
        }
 
index 1aa5f40592514db3e015c67e176d43c44ce22a69..73b7e238eee75e020373b98e3727277676920c21 100644 (file)
@@ -25,9 +25,11 @@ static const struct mtk_fixed_clk top_fixed_clks[] = {
        FIXED_CLK(CLK_TOP_UNIVP_192M, "univpll_192m", "univpll", 192000000),
 };
 
+static const struct mtk_fixed_factor top_early_divs[] = {
+       FACTOR(CLK_TOP_CLK13M, "clk13m", "clk26m", 1, 2),
+};
+
 static const struct mtk_fixed_factor top_divs[] = {
-       FACTOR(CLK_TOP_CLK13M, "clk13m", "clk26m", 1,
-               2),
        FACTOR(CLK_TOP_F26M_CK_D2, "csw_f26m_ck_d2", "clk26m", 1,
                2),
        FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1,
@@ -1148,37 +1150,57 @@ static int clk_mt8183_apmixed_probe(struct platform_device *pdev)
        return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 }
 
+static struct clk_onecell_data *top_clk_data;
+
+static void clk_mt8183_top_init_early(struct device_node *node)
+{
+       int i;
+
+       top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+       for (i = 0; i < CLK_TOP_NR_CLK; i++)
+               top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+
+       mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs),
+                       top_clk_data);
+
+       of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data);
+}
+
+CLK_OF_DECLARE_DRIVER(mt8183_topckgen, "mediatek,mt8183-topckgen",
+                       clk_mt8183_top_init_early);
+
 static int clk_mt8183_top_probe(struct platform_device *pdev)
 {
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        void __iomem *base;
-       struct clk_onecell_data *clk_data;
        struct device_node *node = pdev->dev.of_node;
 
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
 
-       clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
-
        mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
-               clk_data);
+               top_clk_data);
+
+       mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs),
+               top_clk_data);
 
-       mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+       mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data);
 
        mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes),
-               node, &mt8183_clk_lock, clk_data);
+               node, &mt8183_clk_lock, top_clk_data);
 
        mtk_clk_register_composites(top_aud_muxes, ARRAY_SIZE(top_aud_muxes),
-               base, &mt8183_clk_lock, clk_data);
+               base, &mt8183_clk_lock, top_clk_data);
 
        mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs),
-               base, &mt8183_clk_lock, clk_data);
+               base, &mt8183_clk_lock, top_clk_data);
 
        mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
-               clk_data);
+               top_clk_data);
 
-       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       return of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data);
 }
 
 static int clk_mt8183_infra_probe(struct platform_device *pdev)
index 52bbb9ce3807db3164b0a1b6fc0eba9b903e8156..d4075b13067429cded1088e6423b77bb78b5309b 100644 (file)
@@ -572,17 +572,11 @@ static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
        unsigned int reg = id / 32;
        unsigned int bit = id % 32;
        u32 bitmask = BIT(bit);
-       unsigned long flags;
-       u32 value;
 
        dev_dbg(priv->dev, "reset %u%02u\n", reg, bit);
 
        /* Reset module */
-       spin_lock_irqsave(&priv->rmw_lock, flags);
-       value = readl(priv->base + SRCR(reg));
-       value |= bitmask;
-       writel(value, priv->base + SRCR(reg));
-       spin_unlock_irqrestore(&priv->rmw_lock, flags);
+       writel(bitmask, priv->base + SRCR(reg));
 
        /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
        udelay(35);
@@ -599,16 +593,10 @@ static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
        unsigned int reg = id / 32;
        unsigned int bit = id % 32;
        u32 bitmask = BIT(bit);
-       unsigned long flags;
-       u32 value;
 
        dev_dbg(priv->dev, "assert %u%02u\n", reg, bit);
 
-       spin_lock_irqsave(&priv->rmw_lock, flags);
-       value = readl(priv->base + SRCR(reg));
-       value |= bitmask;
-       writel(value, priv->base + SRCR(reg));
-       spin_unlock_irqrestore(&priv->rmw_lock, flags);
+       writel(bitmask, priv->base + SRCR(reg));
        return 0;
 }
 
index 91db7894125df5bcf6cc1b5c014d4307a9520c25..65c82d922b05cbb0e22bd9438627d8fde7120542 100644 (file)
@@ -14,7 +14,7 @@
 #include "clk-exynos5-subcmu.h"
 
 static struct samsung_clk_provider *ctx;
-static const struct exynos5_subcmu_info *cmu;
+static const struct exynos5_subcmu_info **cmu;
 static int nr_cmus;
 
 static void exynos5_subcmu_clk_save(void __iomem *base,
@@ -56,17 +56,17 @@ static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx,
  * when OF-core populates all device-tree nodes.
  */
 void exynos5_subcmus_init(struct samsung_clk_provider *_ctx, int _nr_cmus,
-                         const struct exynos5_subcmu_info *_cmu)
+                         const struct exynos5_subcmu_info **_cmu)
 {
        ctx = _ctx;
        cmu = _cmu;
        nr_cmus = _nr_cmus;
 
        for (; _nr_cmus--; _cmu++) {
-               exynos5_subcmu_defer_gate(ctx, _cmu->gate_clks,
-                                         _cmu->nr_gate_clks);
-               exynos5_subcmu_clk_save(ctx->reg_base, _cmu->suspend_regs,
-                                       _cmu->nr_suspend_regs);
+               exynos5_subcmu_defer_gate(ctx, (*_cmu)->gate_clks,
+                                         (*_cmu)->nr_gate_clks);
+               exynos5_subcmu_clk_save(ctx->reg_base, (*_cmu)->suspend_regs,
+                                       (*_cmu)->nr_suspend_regs);
        }
 }
 
@@ -163,9 +163,9 @@ static int __init exynos5_clk_probe(struct platform_device *pdev)
                if (of_property_read_string(np, "label", &name) < 0)
                        continue;
                for (i = 0; i < nr_cmus; i++)
-                       if (strcmp(cmu[i].pd_name, name) == 0)
+                       if (strcmp(cmu[i]->pd_name, name) == 0)
                                exynos5_clk_register_subcmu(&pdev->dev,
-                                                           &cmu[i], np);
+                                                           cmu[i], np);
        }
        return 0;
 }
index 755ee8aaa3de5670f41ae60b1b691436fa5f457b..9ae5356f25aa4170fa5a91834a7fa926246e71f4 100644 (file)
@@ -21,6 +21,6 @@ struct exynos5_subcmu_info {
 };
 
 void exynos5_subcmus_init(struct samsung_clk_provider *ctx, int nr_cmus,
-                         const struct exynos5_subcmu_info *cmu);
+                         const struct exynos5_subcmu_info **cmu);
 
 #endif
index f2b8968817682458d13c0eb1452179219ec242e9..931c70a4da196871cb75a7026908a30c1f5c286c 100644 (file)
@@ -681,6 +681,10 @@ static const struct exynos5_subcmu_info exynos5250_disp_subcmu = {
        .pd_name        = "DISP1",
 };
 
+static const struct exynos5_subcmu_info *exynos5250_subcmus[] = {
+       &exynos5250_disp_subcmu,
+};
+
 static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
        /* PLL_36XX_RATE(rate, m, p, s, k) */
@@ -843,7 +847,8 @@ static void __init exynos5250_clk_init(struct device_node *np)
 
        samsung_clk_sleep_init(reg_base, exynos5250_clk_regs,
                               ARRAY_SIZE(exynos5250_clk_regs));
-       exynos5_subcmus_init(ctx, 1, &exynos5250_disp_subcmu);
+       exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5250_subcmus),
+                            exynos5250_subcmus);
 
        samsung_clk_of_add_provider(np, ctx);
 
index 01bca5a498b2a1e330287e465401aa7f330a37ae..7670cc596c74245205babf39e339c8e0b5e087f6 100644 (file)
@@ -534,8 +534,6 @@ static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
                                GATE_BUS_TOP, 24, 0, 0),
        GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
                                GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
-       GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
-                       SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
 };
 
 static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
@@ -577,8 +575,13 @@ static const struct samsung_div_clock exynos5420_div_clks[] __initconst = {
 
 static const struct samsung_gate_clock exynos5420_gate_clks[] __initconst = {
        GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0),
+       /* Maudio Block */
        GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk",
                        SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
+               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
+               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
@@ -890,9 +893,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
        /* GSCL Block */
        DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2),
 
-       /* MSCL Block */
-       DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
-
        /* PSGEN */
        DIV(0, "dout_gen_blk", "mout_user_aclk266", DIV2_RATIO0, 8, 1),
        DIV(0, "dout_jpg_blk", "aclk166", DIV2_RATIO0, 20, 1),
@@ -1017,12 +1017,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1",
                        GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0),
 
-       /* Maudio Block */
-       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
-               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
-       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
-               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
-
        /* FSYS Block */
        GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0),
        GATE(CLK_PDMA0, "pdma0", "aclk200_fsys", GATE_BUS_FSYS0, 1, 0, 0),
@@ -1162,17 +1156,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl",
                        GATE_IP_GSCL1, 17, 0, 0),
 
-       /* MSCL Block */
-       GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
-       GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
-       GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
-       GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
-                       GATE_IP_MSCL, 8, 0, 0),
-       GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
-                       GATE_IP_MSCL, 9, 0, 0),
-       GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
-                       GATE_IP_MSCL, 10, 0, 0),
-
        /* ISP */
        GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp",
                        GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0),
@@ -1281,32 +1264,103 @@ static struct exynos5_subcmu_reg_dump exynos5x_mfc_suspend_regs[] = {
        { DIV4_RATIO, 0, 0x3 },                 /* DIV dout_mfc_blk */
 };
 
-static const struct exynos5_subcmu_info exynos5x_subcmus[] = {
-       {
-               .div_clks       = exynos5x_disp_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_disp_div_clks),
-               .gate_clks      = exynos5x_disp_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_disp_gate_clks),
-               .suspend_regs   = exynos5x_disp_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
-               .pd_name        = "DISP",
-       }, {
-               .div_clks       = exynos5x_gsc_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_gsc_div_clks),
-               .gate_clks      = exynos5x_gsc_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_gsc_gate_clks),
-               .suspend_regs   = exynos5x_gsc_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
-               .pd_name        = "GSC",
-       }, {
-               .div_clks       = exynos5x_mfc_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_mfc_div_clks),
-               .gate_clks      = exynos5x_mfc_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_mfc_gate_clks),
-               .suspend_regs   = exynos5x_mfc_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
-               .pd_name        = "MFC",
-       },
+static const struct samsung_gate_clock exynos5x_mscl_gate_clks[] __initconst = {
+       /* MSCL Block */
+       GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
+       GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
+       GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
+       GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
+                       GATE_IP_MSCL, 8, 0, 0),
+       GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
+                       GATE_IP_MSCL, 9, 0, 0),
+       GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
+                       GATE_IP_MSCL, 10, 0, 0),
+};
+
+static const struct samsung_div_clock exynos5x_mscl_div_clks[] __initconst = {
+       DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_mscl_suspend_regs[] = {
+       { GATE_IP_MSCL, 0xffffffff, 0xffffffff }, /* MSCL gates */
+       { SRC_TOP3, 0, BIT(4) },                /* MUX mout_user_aclk400_mscl */
+       { DIV2_RATIO0, 0, 0x30000000 },         /* DIV dout_mscl_blk */
+};
+
+static const struct samsung_gate_clock exynos5800_mau_gate_clks[] __initconst = {
+       GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
+                       SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
+               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
+               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5800_mau_suspend_regs[] = {
+       { SRC_TOP9, 0, BIT(8) },        /* MUX mout_user_mau_epll */
+};
+
+static const struct exynos5_subcmu_info exynos5x_disp_subcmu = {
+       .div_clks       = exynos5x_disp_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_disp_div_clks),
+       .gate_clks      = exynos5x_disp_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_disp_gate_clks),
+       .suspend_regs   = exynos5x_disp_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
+       .pd_name        = "DISP",
+};
+
+static const struct exynos5_subcmu_info exynos5x_gsc_subcmu = {
+       .div_clks       = exynos5x_gsc_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_gsc_div_clks),
+       .gate_clks      = exynos5x_gsc_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_gsc_gate_clks),
+       .suspend_regs   = exynos5x_gsc_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
+       .pd_name        = "GSC",
+};
+
+static const struct exynos5_subcmu_info exynos5x_mfc_subcmu = {
+       .div_clks       = exynos5x_mfc_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_mfc_div_clks),
+       .gate_clks      = exynos5x_mfc_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_mfc_gate_clks),
+       .suspend_regs   = exynos5x_mfc_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
+       .pd_name        = "MFC",
+};
+
+static const struct exynos5_subcmu_info exynos5x_mscl_subcmu = {
+       .div_clks       = exynos5x_mscl_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_mscl_div_clks),
+       .gate_clks      = exynos5x_mscl_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_mscl_gate_clks),
+       .suspend_regs   = exynos5x_mscl_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_mscl_suspend_regs),
+       .pd_name        = "MSC",
+};
+
+static const struct exynos5_subcmu_info exynos5800_mau_subcmu = {
+       .gate_clks      = exynos5800_mau_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5800_mau_gate_clks),
+       .suspend_regs   = exynos5800_mau_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5800_mau_suspend_regs),
+       .pd_name        = "MAU",
+};
+
+static const struct exynos5_subcmu_info *exynos5x_subcmus[] = {
+       &exynos5x_disp_subcmu,
+       &exynos5x_gsc_subcmu,
+       &exynos5x_mfc_subcmu,
+       &exynos5x_mscl_subcmu,
+};
+
+static const struct exynos5_subcmu_info *exynos5800_subcmus[] = {
+       &exynos5x_disp_subcmu,
+       &exynos5x_gsc_subcmu,
+       &exynos5x_mfc_subcmu,
+       &exynos5x_mscl_subcmu,
+       &exynos5800_mau_subcmu,
 };
 
 static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
@@ -1539,11 +1593,17 @@ static void __init exynos5x_clk_init(struct device_node *np,
        samsung_clk_extended_sleep_init(reg_base,
                exynos5x_clk_regs, ARRAY_SIZE(exynos5x_clk_regs),
                exynos5420_set_clksrc, ARRAY_SIZE(exynos5420_set_clksrc));
-       if (soc == EXYNOS5800)
+
+       if (soc == EXYNOS5800) {
                samsung_clk_sleep_init(reg_base, exynos5800_clk_regs,
                                       ARRAY_SIZE(exynos5800_clk_regs));
-       exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
-                            exynos5x_subcmus);
+
+               exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5800_subcmus),
+                                    exynos5800_subcmus);
+       } else {
+               exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
+                                    exynos5x_subcmus);
+       }
 
        samsung_clk_of_add_provider(np, ctx);
 }
index 5c50e723ecae7e945c85da36eacf514ffc71d81c..1a191eeeebbab915705bca2284c4cdbeba22bbd2 100644 (file)
@@ -38,7 +38,7 @@ static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
        if (socfpgaclk->fixed_div) {
                div = socfpgaclk->fixed_div;
        } else {
-               if (!socfpgaclk->bypass_reg)
+               if (socfpgaclk->hw.reg)
                        div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
        }
 
index 91d3d721c801e13ba1f44e1c26139922dcc73a00..3c219af2510016ed76f3069743abd23a6c0072f9 100644 (file)
@@ -3,6 +3,7 @@ config SPRD_COMMON_CLK
        tristate "Clock support for Spreadtrum SoCs"
        depends on ARCH_SPRD || COMPILE_TEST
        default ARCH_SPRD
+       select REGMAP_MMIO
 
 if SPRD_COMMON_CLK
 
index 5e6038fbf115d10bc82cc77548b709c3145e4a43..09e031176bc6bae860133bb478d7fb5428b25469 100644 (file)
@@ -55,7 +55,7 @@ static u64 riscv_sched_clock(void)
        return get_cycles64();
 }
 
-static DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = {
+static struct clocksource riscv_clocksource = {
        .name           = "riscv_clocksource",
        .rating         = 300,
        .mask           = CLOCKSOURCE_MASK(64),
@@ -92,7 +92,6 @@ void riscv_timer_interrupt(void)
 static int __init riscv_timer_init_dt(struct device_node *n)
 {
        int cpuid, hartid, error;
-       struct clocksource *cs;
 
        hartid = riscv_of_processor_hartid(n);
        if (hartid < 0) {
@@ -112,8 +111,7 @@ static int __init riscv_timer_init_dt(struct device_node *n)
 
        pr_info("%s: Registering clocksource cpuid [%d] hartid [%d]\n",
               __func__, cpuid, hartid);
-       cs = per_cpu_ptr(&riscv_clocksource, cpuid);
-       error = clocksource_register_hz(cs, riscv_timebase);
+       error = clocksource_register_hz(&riscv_clocksource, riscv_timebase);
        if (error) {
                pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
                       error, cpuid);
index 23553ed6b548063df3a39139994b0eaf722cbd8d..2d22d6bf52f25a074728d1650541f2c39b1f3383 100644 (file)
@@ -248,16 +248,12 @@ static int __maybe_unused cn_proc_show(struct seq_file *m, void *v)
        return 0;
 }
 
-static struct cn_dev cdev = {
-       .input   = cn_rx_skb,
-};
-
 static int cn_init(void)
 {
        struct cn_dev *dev = &cdev;
        struct netlink_kernel_cfg cfg = {
                .groups = CN_NETLINK_USERS + 0xf,
-               .input  = dev->input,
+               .input  = cn_rx_skb,
        };
 
        dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR, &cfg);
index 8dda62367816f331420eedd58a7c686f0d68a04f..c28ebf2810f11508a1c36cb1660bdd949ef3aeff 100644 (file)
@@ -2528,7 +2528,7 @@ static int cpufreq_boost_set_sw(int state)
                }
 
                ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);
-               if (ret)
+               if (ret < 0)
                        break;
        }
 
index 93f39a1d4c3de064f93acd8b0757f4d655458f93..c66f566a854cb6775242df8a2078ee217269e260 100644 (file)
@@ -131,10 +131,18 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
        int err = -ENODEV;
 
        cpu = of_get_cpu_node(policy->cpu, NULL);
+       if (!cpu)
+               goto out;
 
+       max_freqp = of_get_property(cpu, "clock-frequency", NULL);
        of_node_put(cpu);
-       if (!cpu)
+       if (!max_freqp) {
+               err = -EINVAL;
                goto out;
+       }
+
+       /* we need the freq in kHz */
+       max_freq = *max_freqp / 1000;
 
        dn = of_find_compatible_node(NULL, NULL, "1682m-sdc");
        if (!dn)
@@ -171,16 +179,6 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
        }
 
        pr_debug("init cpufreq on CPU %d\n", policy->cpu);
-
-       max_freqp = of_get_property(cpu, "clock-frequency", NULL);
-       if (!max_freqp) {
-               err = -EINVAL;
-               goto out_unmap_sdcpwr;
-       }
-
-       /* we need the freq in kHz */
-       max_freq = *max_freqp / 1000;
-
        pr_debug("max clock-frequency is at %u kHz\n", max_freq);
        pr_debug("initializing frequency table\n");
 
@@ -199,9 +197,6 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
        cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency());
        return 0;
 
-out_unmap_sdcpwr:
-       iounmap(sdcpwr_mapbase);
-
 out_unmap_sdcasr:
        iounmap(sdcasr_mapbase);
 out:
index f9fec2ddf56aef0e3ec72039395bc6044403f8f9..94c1ad7eeddf7ca84d11f685b90756c2edefcf2f 100644 (file)
@@ -58,6 +58,19 @@ static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
 static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
                                   unsigned int authsize)
 {
+       switch (authsize) {
+       case 16:
+       case 15:
+       case 14:
+       case 13:
+       case 12:
+       case 8:
+       case 4:
+               break;
+       default:
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -104,6 +117,7 @@ static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
        memset(&rctx->cmd, 0, sizeof(rctx->cmd));
        INIT_LIST_HEAD(&rctx->cmd.entry);
        rctx->cmd.engine = CCP_ENGINE_AES;
+       rctx->cmd.u.aes.authsize = crypto_aead_authsize(tfm);
        rctx->cmd.u.aes.type = ctx->u.aes.type;
        rctx->cmd.u.aes.mode = ctx->u.aes.mode;
        rctx->cmd.u.aes.action = encrypt;
index f79eede71c62d8e1d50cb7640f7ea64023b1b590..edefa669153f49c4df1591431c24d4180d3f4b7c 100644 (file)
@@ -540,6 +540,10 @@ int ccp_dev_suspend(struct sp_device *sp, pm_message_t state)
        unsigned long flags;
        unsigned int i;
 
+       /* If there's no device there's nothing to do */
+       if (!ccp)
+               return 0;
+
        spin_lock_irqsave(&ccp->cmd_lock, flags);
 
        ccp->suspending = 1;
@@ -564,6 +568,10 @@ int ccp_dev_resume(struct sp_device *sp)
        unsigned long flags;
        unsigned int i;
 
+       /* If there's no device there's nothing to do */
+       if (!ccp)
+               return 0;
+
        spin_lock_irqsave(&ccp->cmd_lock, flags);
 
        ccp->suspending = 0;
index c69ed4bae2eb1045dfab71f0f884954756cde4f1..9bc3c62157d7dc500b3b00c3d4d74bd37d5fd531 100644 (file)
@@ -622,6 +622,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
 
        unsigned long long *final;
        unsigned int dm_offset;
+       unsigned int authsize;
        unsigned int jobid;
        unsigned int ilen;
        bool in_place = true; /* Default value */
@@ -643,6 +644,21 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
        if (!aes->key) /* Gotta have a key SGL */
                return -EINVAL;
 
+       /* Zero defaults to 16 bytes, the maximum size */
+       authsize = aes->authsize ? aes->authsize : AES_BLOCK_SIZE;
+       switch (authsize) {
+       case 16:
+       case 15:
+       case 14:
+       case 13:
+       case 12:
+       case 8:
+       case 4:
+               break;
+       default:
+               return -EINVAL;
+       }
+
        /* First, decompose the source buffer into AAD & PT,
         * and the destination buffer into AAD, CT & tag, or
         * the input into CT & tag.
@@ -657,7 +673,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
                p_tag = scatterwalk_ffwd(sg_tag, p_outp, ilen);
        } else {
                /* Input length for decryption includes tag */
-               ilen = aes->src_len - AES_BLOCK_SIZE;
+               ilen = aes->src_len - authsize;
                p_tag = scatterwalk_ffwd(sg_tag, p_inp, ilen);
        }
 
@@ -766,8 +782,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
                while (src.sg_wa.bytes_left) {
                        ccp_prepare_data(&src, &dst, &op, AES_BLOCK_SIZE, true);
                        if (!src.sg_wa.bytes_left) {
-                               unsigned int nbytes = aes->src_len
-                                                     % AES_BLOCK_SIZE;
+                               unsigned int nbytes = ilen % AES_BLOCK_SIZE;
 
                                if (nbytes) {
                                        op.eom = 1;
@@ -839,19 +854,19 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
 
        if (aes->action == CCP_AES_ACTION_ENCRYPT) {
                /* Put the ciphered tag after the ciphertext. */
-               ccp_get_dm_area(&final_wa, 0, p_tag, 0, AES_BLOCK_SIZE);
+               ccp_get_dm_area(&final_wa, 0, p_tag, 0, authsize);
        } else {
                /* Does this ciphered tag match the input? */
-               ret = ccp_init_dm_workarea(&tag, cmd_q, AES_BLOCK_SIZE,
+               ret = ccp_init_dm_workarea(&tag, cmd_q, authsize,
                                           DMA_BIDIRECTIONAL);
                if (ret)
                        goto e_tag;
-               ret = ccp_set_dm_area(&tag, 0, p_tag, 0, AES_BLOCK_SIZE);
+               ret = ccp_set_dm_area(&tag, 0, p_tag, 0, authsize);
                if (ret)
                        goto e_tag;
 
                ret = crypto_memneq(tag.address, final_wa.address,
-                                   AES_BLOCK_SIZE) ? -EBADMSG : 0;
+                                   authsize) ? -EBADMSG : 0;
                ccp_dm_free(&tag);
        }
 
@@ -859,11 +874,11 @@ e_tag:
        ccp_dm_free(&final_wa);
 
 e_dst:
-       if (aes->src_len && !in_place)
+       if (ilen > 0 && !in_place)
                ccp_free_data(&dst, cmd_q);
 
 e_src:
-       if (aes->src_len)
+       if (ilen > 0)
                ccp_free_data(&src, cmd_q);
 
 e_aad:
index ece83a363e1130008b06f0a4b3feea72b163e7d6..f22f6fa612b379efb674383e8470c3e526d9f5e9 100644 (file)
@@ -314,14 +314,17 @@ void cryp_save_device_context(struct cryp_device_data *device_data,
        case CRYP_KEY_SIZE_256:
                ctx->key_4_l = readl_relaxed(&src_reg->key_4_l);
                ctx->key_4_r = readl_relaxed(&src_reg->key_4_r);
+               /* Fall through */
 
        case CRYP_KEY_SIZE_192:
                ctx->key_3_l = readl_relaxed(&src_reg->key_3_l);
                ctx->key_3_r = readl_relaxed(&src_reg->key_3_r);
+               /* Fall through */
 
        case CRYP_KEY_SIZE_128:
                ctx->key_2_l = readl_relaxed(&src_reg->key_2_l);
                ctx->key_2_r = readl_relaxed(&src_reg->key_2_r);
+               /* Fall through */
 
        default:
                ctx->key_1_l = readl_relaxed(&src_reg->key_1_l);
@@ -361,14 +364,17 @@ void cryp_restore_device_context(struct cryp_device_data *device_data,
        case CRYP_KEY_SIZE_256:
                writel_relaxed(ctx->key_4_l, &reg->key_4_l);
                writel_relaxed(ctx->key_4_r, &reg->key_4_r);
+               /* Fall through */
 
        case CRYP_KEY_SIZE_192:
                writel_relaxed(ctx->key_3_l, &reg->key_3_l);
                writel_relaxed(ctx->key_3_r, &reg->key_3_r);
+               /* Fall through */
 
        case CRYP_KEY_SIZE_128:
                writel_relaxed(ctx->key_2_l, &reg->key_2_l);
                writel_relaxed(ctx->key_2_r, &reg->key_2_r);
+               /* Fall through */
 
        default:
                writel_relaxed(ctx->key_1_l, &reg->key_1_l);
index b6cc90cbc9dc244734fd763a9ed34829419c994a..4e5f9f6e901baec4f3c87f9fd3ed0f7b5bb5874b 100644 (file)
@@ -50,7 +50,7 @@ struct dw_edma_burst {
 
 struct dw_edma_region {
        phys_addr_t                     paddr;
-       dma_addr_t                      vaddr;
+       void                            __iomem *vaddr;
        size_t                          sz;
 };
 
index 4c96e1c948f2be68489b264b69f488523f520995..dc85f55e1bb8ce3c3d9410d181c7362f9801ed7e 100644 (file)
@@ -130,19 +130,19 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
        chip->id = pdev->devfn;
        chip->irq = pdev->irq;
 
-       dw->rg_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->rg_bar];
+       dw->rg_region.vaddr = pcim_iomap_table(pdev)[pdata->rg_bar];
        dw->rg_region.vaddr += pdata->rg_off;
        dw->rg_region.paddr = pdev->resource[pdata->rg_bar].start;
        dw->rg_region.paddr += pdata->rg_off;
        dw->rg_region.sz = pdata->rg_sz;
 
-       dw->ll_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->ll_bar];
+       dw->ll_region.vaddr = pcim_iomap_table(pdev)[pdata->ll_bar];
        dw->ll_region.vaddr += pdata->ll_off;
        dw->ll_region.paddr = pdev->resource[pdata->ll_bar].start;
        dw->ll_region.paddr += pdata->ll_off;
        dw->ll_region.sz = pdata->ll_sz;
 
-       dw->dt_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->dt_bar];
+       dw->dt_region.vaddr = pcim_iomap_table(pdev)[pdata->dt_bar];
        dw->dt_region.vaddr += pdata->dt_off;
        dw->dt_region.paddr = pdev->resource[pdata->dt_bar].start;
        dw->dt_region.paddr += pdata->dt_off;
@@ -158,17 +158,17 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
        pci_dbg(pdev, "Mode:\t%s\n",
                dw->mode == EDMA_MODE_LEGACY ? "Legacy" : "Unroll");
 
-       pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+       pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
                pdata->rg_bar, pdata->rg_off, pdata->rg_sz,
-               &dw->rg_region.vaddr, &dw->rg_region.paddr);
+               dw->rg_region.vaddr, &dw->rg_region.paddr);
 
-       pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+       pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
                pdata->ll_bar, pdata->ll_off, pdata->ll_sz,
-               &dw->ll_region.vaddr, &dw->ll_region.paddr);
+               dw->ll_region.vaddr, &dw->ll_region.paddr);
 
-       pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+       pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
                pdata->dt_bar, pdata->dt_off, pdata->dt_sz,
-               &dw->dt_region.vaddr, &dw->dt_region.paddr);
+               dw->dt_region.vaddr, &dw->dt_region.paddr);
 
        pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
 
index 8a3180ed49a60940492d5c32f31518618e8ff97a..692de47b16701dc7b9f75aefa657618a352149d5 100644 (file)
@@ -25,7 +25,7 @@ enum dw_edma_control {
 
 static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
 {
-       return (struct dw_edma_v0_regs __iomem *)dw->rg_region.vaddr;
+       return dw->rg_region.vaddr;
 }
 
 #define SET(dw, name, value)                           \
@@ -192,13 +192,12 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
 static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
 {
        struct dw_edma_burst *child;
-       struct dw_edma_v0_lli *lli;
-       struct dw_edma_v0_llp *llp;
+       struct dw_edma_v0_lli __iomem *lli;
+       struct dw_edma_v0_llp __iomem *llp;
        u32 control = 0, i = 0;
-       u64 sar, dar, addr;
        int j;
 
-       lli = (struct dw_edma_v0_lli *)chunk->ll_region.vaddr;
+       lli = chunk->ll_region.vaddr;
 
        if (chunk->cb)
                control = DW_EDMA_V0_CB;
@@ -214,17 +213,15 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
                /* Transfer size */
                SET_LL(&lli[i].transfer_size, child->sz);
                /* SAR - low, high */
-               sar = cpu_to_le64(child->sar);
-               SET_LL(&lli[i].sar_low, lower_32_bits(sar));
-               SET_LL(&lli[i].sar_high, upper_32_bits(sar));
+               SET_LL(&lli[i].sar_low, lower_32_bits(child->sar));
+               SET_LL(&lli[i].sar_high, upper_32_bits(child->sar));
                /* DAR - low, high */
-               dar = cpu_to_le64(child->dar);
-               SET_LL(&lli[i].dar_low, lower_32_bits(dar));
-               SET_LL(&lli[i].dar_high, upper_32_bits(dar));
+               SET_LL(&lli[i].dar_low, lower_32_bits(child->dar));
+               SET_LL(&lli[i].dar_high, upper_32_bits(child->dar));
                i++;
        }
 
-       llp = (struct dw_edma_v0_llp *)&lli[i];
+       llp = (void __iomem *)&lli[i];
        control = DW_EDMA_V0_LLP | DW_EDMA_V0_TCB;
        if (!chunk->cb)
                control |= DW_EDMA_V0_CB;
@@ -232,9 +229,8 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
        /* Channel control */
        SET_LL(&llp->control, control);
        /* Linked list  - low, high */
-       addr = cpu_to_le64(chunk->ll_region.paddr);
-       SET_LL(&llp->llp_low, lower_32_bits(addr));
-       SET_LL(&llp->llp_high, upper_32_bits(addr));
+       SET_LL(&llp->llp_low, lower_32_bits(chunk->ll_region.paddr));
+       SET_LL(&llp->llp_high, upper_32_bits(chunk->ll_region.paddr));
 }
 
 void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
@@ -242,7 +238,6 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
        struct dw_edma_chan *chan = chunk->chan;
        struct dw_edma *dw = chan->chip->dw;
        u32 tmp;
-       u64 llp;
 
        dw_edma_v0_core_write_chunk(chunk);
 
@@ -262,9 +257,10 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
                SET_CH(dw, chan->dir, chan->id, ch_control1,
                       (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
                /* Linked list - low, high */
-               llp = cpu_to_le64(chunk->ll_region.paddr);
-               SET_CH(dw, chan->dir, chan->id, llp_low, lower_32_bits(llp));
-               SET_CH(dw, chan->dir, chan->id, llp_high, upper_32_bits(llp));
+               SET_CH(dw, chan->dir, chan->id, llp_low,
+                      lower_32_bits(chunk->ll_region.paddr));
+               SET_CH(dw, chan->dir, chan->id, llp_high,
+                      upper_32_bits(chunk->ll_region.paddr));
        }
        /* Doorbell */
        SET_RW(dw, chan->dir, doorbell,
index 3226f528cc11395409ae503f45ce9816ead6d8bc..42739508c0d854c669ea3f40baf2c0e8e61a59c9 100644 (file)
@@ -14,7 +14,7 @@
 #include "dw-edma-core.h"
 
 #define REGS_ADDR(name) \
-       ((dma_addr_t *)&regs->name)
+       ((void __force *)&regs->name)
 #define REGISTER(name) \
        { #name, REGS_ADDR(name) }
 
 
 static struct dentry                           *base_dir;
 static struct dw_edma                          *dw;
-static struct dw_edma_v0_regs                  *regs;
+static struct dw_edma_v0_regs                  __iomem *regs;
 
 static struct {
-       void                                    *start;
-       void                                    *end;
+       void                                    __iomem *start;
+       void                                    __iomem *end;
 } lim[2][EDMA_V0_MAX_NR_CH];
 
 struct debugfs_entries {
-       char                                    name[24];
+       const char                              *name;
        dma_addr_t                              *reg;
 };
 
 static int dw_edma_debugfs_u32_get(void *data, u64 *val)
 {
+       void __iomem *reg = (void __force __iomem *)data;
        if (dw->mode == EDMA_MODE_LEGACY &&
-           data >= (void *)&regs->type.legacy.ch) {
-               void *ptr = (void *)&regs->type.legacy.ch;
+           reg >= (void __iomem *)&regs->type.legacy.ch) {
+               void __iomem *ptr = &regs->type.legacy.ch;
                u32 viewport_sel = 0;
                unsigned long flags;
                u16 ch;
 
                for (ch = 0; ch < dw->wr_ch_cnt; ch++)
-                       if (lim[0][ch].start >= data && data < lim[0][ch].end) {
-                               ptr += (data - lim[0][ch].start);
+                       if (lim[0][ch].start >= reg && reg < lim[0][ch].end) {
+                               ptr += (reg - lim[0][ch].start);
                                goto legacy_sel_wr;
                        }
 
                for (ch = 0; ch < dw->rd_ch_cnt; ch++)
-                       if (lim[1][ch].start >= data && data < lim[1][ch].end) {
-                               ptr += (data - lim[1][ch].start);
+                       if (lim[1][ch].start >= reg && reg < lim[1][ch].end) {
+                               ptr += (reg - lim[1][ch].start);
                                goto legacy_sel_rd;
                        }
 
@@ -86,7 +87,7 @@ legacy_sel_wr:
 
                raw_spin_unlock_irqrestore(&dw->lock, flags);
        } else {
-               *val = readl(data);
+               *val = readl(reg);
        }
 
        return 0;
@@ -105,7 +106,7 @@ static void dw_edma_debugfs_create_x32(const struct debugfs_entries entries[],
        }
 }
 
-static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs *regs,
+static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
                                    struct dentry *dir)
 {
        int nr_entries;
@@ -288,7 +289,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
        if (!dw)
                return;
 
-       regs = (struct dw_edma_v0_regs *)dw->rg_region.vaddr;
+       regs = dw->rg_region.vaddr;
        if (!regs)
                return;
 
index 23e0a356f16754083a981158a8a6bf2508e97e57..ad72b3f42ffa06d413b7d2f5a73a5faa00458a71 100644 (file)
@@ -1163,6 +1163,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
        switch (chan->feature & FSL_DMA_IP_MASK) {
        case FSL_DMA_IP_85XX:
                chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
+               /* Fall through */
        case FSL_DMA_IP_83XX:
                chan->toggle_ext_start = fsl_chan_toggle_ext_start;
                chan->set_src_loop_size = fsl_chan_set_src_loop_size;
index 9c41a4e425759fcca6235e80c4ff42bf9fcb6c4b..1072c450c37ab89d7c78ea0f521927fcb13410ae 100644 (file)
@@ -192,6 +192,7 @@ struct rcar_dmac_chan {
  * @iomem: remapped I/O memory base
  * @n_channels: number of available channels
  * @channels: array of DMAC channels
+ * @channels_mask: bitfield of which DMA channels are managed by this driver
  * @modules: bitmask of client modules in use
  */
 struct rcar_dmac {
@@ -202,6 +203,7 @@ struct rcar_dmac {
 
        unsigned int n_channels;
        struct rcar_dmac_chan *channels;
+       unsigned int channels_mask;
 
        DECLARE_BITMAP(modules, 256);
 };
@@ -438,7 +440,7 @@ static int rcar_dmac_init(struct rcar_dmac *dmac)
        u16 dmaor;
 
        /* Clear all channels and enable the DMAC globally. */
-       rcar_dmac_write(dmac, RCAR_DMACHCLR, GENMASK(dmac->n_channels - 1, 0));
+       rcar_dmac_write(dmac, RCAR_DMACHCLR, dmac->channels_mask);
        rcar_dmac_write(dmac, RCAR_DMAOR,
                        RCAR_DMAOR_PRI_FIXED | RCAR_DMAOR_DME);
 
@@ -814,6 +816,9 @@ static void rcar_dmac_stop_all_chan(struct rcar_dmac *dmac)
        for (i = 0; i < dmac->n_channels; ++i) {
                struct rcar_dmac_chan *chan = &dmac->channels[i];
 
+               if (!(dmac->channels_mask & BIT(i)))
+                       continue;
+
                /* Stop and reinitialize the channel. */
                spin_lock_irq(&chan->lock);
                rcar_dmac_chan_halt(chan);
@@ -1776,6 +1781,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
        return 0;
 }
 
+#define RCAR_DMAC_MAX_CHANNELS 32
+
 static int rcar_dmac_parse_of(struct device *dev, struct rcar_dmac *dmac)
 {
        struct device_node *np = dev->of_node;
@@ -1787,12 +1794,16 @@ static int rcar_dmac_parse_of(struct device *dev, struct rcar_dmac *dmac)
                return ret;
        }
 
-       if (dmac->n_channels <= 0 || dmac->n_channels >= 100) {
+       /* The hardware and driver don't support more than 32 bits in CHCLR */
+       if (dmac->n_channels <= 0 ||
+           dmac->n_channels >= RCAR_DMAC_MAX_CHANNELS) {
                dev_err(dev, "invalid number of channels %u\n",
                        dmac->n_channels);
                return -EINVAL;
        }
 
+       dmac->channels_mask = GENMASK(dmac->n_channels - 1, 0);
+
        return 0;
 }
 
@@ -1802,7 +1813,6 @@ static int rcar_dmac_probe(struct platform_device *pdev)
                DMA_SLAVE_BUSWIDTH_2_BYTES | DMA_SLAVE_BUSWIDTH_4_BYTES |
                DMA_SLAVE_BUSWIDTH_8_BYTES | DMA_SLAVE_BUSWIDTH_16_BYTES |
                DMA_SLAVE_BUSWIDTH_32_BYTES | DMA_SLAVE_BUSWIDTH_64_BYTES;
-       unsigned int channels_offset = 0;
        struct dma_device *engine;
        struct rcar_dmac *dmac;
        struct resource *mem;
@@ -1831,10 +1841,8 @@ static int rcar_dmac_probe(struct platform_device *pdev)
         * level we can't disable it selectively, so ignore channel 0 for now if
         * the device is part of an IOMMU group.
         */
-       if (device_iommu_mapped(&pdev->dev)) {
-               dmac->n_channels--;
-               channels_offset = 1;
-       }
+       if (device_iommu_mapped(&pdev->dev))
+               dmac->channels_mask &= ~BIT(0);
 
        dmac->channels = devm_kcalloc(&pdev->dev, dmac->n_channels,
                                      sizeof(*dmac->channels), GFP_KERNEL);
@@ -1892,8 +1900,10 @@ static int rcar_dmac_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&engine->channels);
 
        for (i = 0; i < dmac->n_channels; ++i) {
-               ret = rcar_dmac_chan_probe(dmac, &dmac->channels[i],
-                                          i + channels_offset);
+               if (!(dmac->channels_mask & BIT(i)))
+                       continue;
+
+               ret = rcar_dmac_chan_probe(dmac, &dmac->channels[i], i);
                if (ret < 0)
                        goto error;
        }
index baac476c86224f2615fe7e2f8010d68b6e1dfdb9..525dc7338fe3b86842f4d2aa3ffd9857d34ec5f6 100644 (file)
@@ -908,6 +908,7 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        struct sprd_dma_chn *schan = to_sprd_dma_chan(chan);
        struct dma_slave_config *slave_cfg = &schan->slave_cfg;
        dma_addr_t src = 0, dst = 0;
+       dma_addr_t start_src = 0, start_dst = 0;
        struct sprd_dma_desc *sdesc;
        struct scatterlist *sg;
        u32 len = 0;
@@ -954,6 +955,11 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        dst = sg_dma_address(sg);
                }
 
+               if (!i) {
+                       start_src = src;
+                       start_dst = dst;
+               }
+
                /*
                 * The link-list mode needs at least 2 link-list
                 * configurations. If there is only one sg, it doesn't
@@ -970,8 +976,8 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                }
        }
 
-       ret = sprd_dma_fill_desc(chan, &sdesc->chn_hw, 0, 0, src, dst, len,
-                                dir, flags, slave_cfg);
+       ret = sprd_dma_fill_desc(chan, &sdesc->chn_hw, 0, 0, start_src,
+                                start_dst, len, dir, flags, slave_cfg);
        if (ret) {
                kfree(sdesc);
                return NULL;
index 89d710899010d3d804a2acc3d92d07f287366d4c..de8bfd9a76e9ebc87d678002de85096b85d80810 100644 (file)
@@ -142,7 +142,7 @@ enum d40_events {
  * when the DMA hw is powered off.
  * TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works.
  */
-static u32 d40_backup_regs[] = {
+static __maybe_unused u32 d40_backup_regs[] = {
        D40_DREG_LCPA,
        D40_DREG_LCLA,
        D40_DREG_PRMSE,
@@ -211,7 +211,7 @@ static u32 d40_backup_regs_v4b[] = {
 
 #define BACKUP_REGS_SZ_V4B ARRAY_SIZE(d40_backup_regs_v4b)
 
-static u32 d40_backup_regs_chan[] = {
+static __maybe_unused u32 d40_backup_regs_chan[] = {
        D40_CHAN_REG_SSCFG,
        D40_CHAN_REG_SSELT,
        D40_CHAN_REG_SSPTR,
index d6e919d3936a295e75271329035f02ad7239e076..1311de74bfdde5f817937fd2a929a1e02ce00c0f 100644 (file)
@@ -1366,7 +1366,7 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid)
 
        chan = &dmadev->chan[id];
        if (!chan) {
-               dev_err(chan2dev(chan), "MDMA channel not initialized\n");
+               dev_dbg(mdma2dev(dmadev), "MDMA channel not initialized\n");
                goto exit;
        }
 
index 2805853e963fcf6f9076e8360ebd519585efa94e..b33cf6e8ab8ef85b67a885fafa8161ee1c989d68 100644 (file)
@@ -712,7 +712,7 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
        return chan;
 }
 
-static int tegra_adma_runtime_suspend(struct device *dev)
+static int __maybe_unused tegra_adma_runtime_suspend(struct device *dev)
 {
        struct tegra_adma *tdma = dev_get_drvdata(dev);
        struct tegra_adma_chan_regs *ch_reg;
@@ -744,7 +744,7 @@ clk_disable:
        return 0;
 }
 
-static int tegra_adma_runtime_resume(struct device *dev)
+static int __maybe_unused tegra_adma_runtime_resume(struct device *dev)
 {
        struct tegra_adma *tdma = dev_get_drvdata(dev);
        struct tegra_adma_chan_regs *ch_reg;
index ad2f0a4cd6a4d1e413ef619eb95ef88c0266cd59..f255056696eecc9aa1f7535bf15eebcba9782850 100644 (file)
@@ -391,8 +391,10 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
 
                ret = of_property_read_u32_array(node, pname, (u32 *)rsv_events,
                                                 nelm * 2);
-               if (ret)
+               if (ret) {
+                       kfree(rsv_events);
                        return ret;
+               }
 
                for (i = 0; i < nelm; i++) {
                        ti_dra7_xbar_reserve(rsv_events[i][0], rsv_events[i][1],
index ba2489d4ea246604ade12f48bf1e077e1ccd30e6..d07c0d5de7a256388e1806afa4264e91f2f51e2d 100644 (file)
@@ -1234,7 +1234,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_interleaved(
        if (src_icg) {
                d->ccr |= CCR_SRC_AMODE_DBLIDX;
                d->ei = 1;
-               d->fi = src_icg;
+               d->fi = src_icg + 1;
        } else if (xt->src_inc) {
                d->ccr |= CCR_SRC_AMODE_POSTINC;
                d->fi = 0;
@@ -1249,7 +1249,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_interleaved(
        if (dst_icg) {
                d->ccr |= CCR_DST_AMODE_DBLIDX;
                sg->ei = 1;
-               sg->fi = dst_icg;
+               sg->fi = dst_icg + 1;
        } else if (xt->dst_inc) {
                d->ccr |= CCR_DST_AMODE_POSTINC;
                sg->fi = 0;
@@ -1540,8 +1540,10 @@ static int omap_dma_probe(struct platform_device *pdev)
 
                rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq,
                                      IRQF_SHARED, "omap-dma-engine", od);
-               if (rc)
+               if (rc) {
+                       omap_dma_free(od);
                        return rc;
+               }
        }
 
        if (omap_dma_glbl_read(od, CAPS_0) & CAPS_0_SUPPORT_LL123)
index 3dc1cbf849db38eb65a598538c2fefcfd5060beb..b785e936244f530eafc35ed1b804822eaf99ef6a 100644 (file)
@@ -957,7 +957,7 @@ static void set_broadcast_channel(struct fw_device *device, int generation)
                                device->bc_implemented = BC_IMPLEMENTED;
                                break;
                        }
-                       /* else fall through to case address error */
+                       /* else, fall through - to case address error */
                case RCODE_ADDRESS_ERROR:
                        device->bc_implemented = BC_UNIMPLEMENTED;
                }
index 42566b7be8f51f00085432992994def48b7d4585..df8a56a979b996c0c1a48e19c7ef84739b7e2611 100644 (file)
@@ -284,7 +284,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
                        if ((data[0] & bit) == (data[1] & bit))
                                continue;
 
-                       /* 1394-1995 IRM, fall through to retry. */
+                       /* fall through - It's a 1394-1995 IRM, retry. */
                default:
                        if (retry) {
                                retry--;
index 46bd22dde5359ee939ada5565c0327be7ea5d023..94a13fca82673b4036052378b398a239a0c57ace 100644 (file)
@@ -54,6 +54,7 @@ static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count)
                switch (port_type) {
                case SELFID_PORT_CHILD:
                        (*child_port_count)++;
+                       /* fall through */
                case SELFID_PORT_PARENT:
                case SELFID_PORT_NCONN:
                        (*total_port_count)++;
index 53446e39a32c7699c8fc793388587343f4b59fe8..ba8d3d0ef32c7fc0dfb11f393a76d01be0f83c7e 100644 (file)
@@ -157,7 +157,7 @@ config DMI_SCAN_MACHINE_NON_EFI_FALLBACK
 
 config ISCSI_IBFT_FIND
        bool "iSCSI Boot Firmware Table Attributes"
-       depends on X86 && ACPI
+       depends on X86 && ISCSI_IBFT
        default n
        help
          This option enables the kernel to find the region of memory
@@ -168,7 +168,8 @@ config ISCSI_IBFT_FIND
 config ISCSI_IBFT
        tristate "iSCSI Boot Firmware Table Attributes module"
        select ISCSI_BOOT_SYSFS
-       depends on ISCSI_IBFT_FIND && SCSI && SCSI_LOWLEVEL
+       select ISCSI_IBFT_FIND if X86
+       depends on ACPI && SCSI && SCSI_LOWLEVEL
        default n
        help
          This option enables support for detection and exposing of iSCSI
index 1db780c0f07be671073e8d7a063dbc58aa6e2698..3caae7f2cf56772936b6f77484ef1f7e1a2b42c2 100644 (file)
@@ -927,17 +927,33 @@ fail:
        return status;
 }
 
+#define GET_EFI_CONFIG_TABLE(bits)                                     \
+static void *get_efi_config_table##bits(efi_system_table_t *_sys_table,        \
+                                       efi_guid_t guid)                \
+{                                                                      \
+       efi_system_table_##bits##_t *sys_table;                         \
+       efi_config_table_##bits##_t *tables;                            \
+       int i;                                                          \
+                                                                       \
+       sys_table = (typeof(sys_table))_sys_table;                      \
+       tables = (typeof(tables))(unsigned long)sys_table->tables;      \
+                                                                       \
+       for (i = 0; i < sys_table->nr_tables; i++) {                    \
+               if (efi_guidcmp(tables[i].guid, guid) != 0)             \
+                       continue;                                       \
+                                                                       \
+               return (void *)(unsigned long)tables[i].table;          \
+       }                                                               \
+                                                                       \
+       return NULL;                                                    \
+}
+GET_EFI_CONFIG_TABLE(32)
+GET_EFI_CONFIG_TABLE(64)
+
 void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
 {
-       efi_config_table_t *tables = (efi_config_table_t *)sys_table->tables;
-       int i;
-
-       for (i = 0; i < sys_table->nr_tables; i++) {
-               if (efi_guidcmp(tables[i].guid, guid) != 0)
-                       continue;
-
-               return (void *)tables[i].table;
-       }
-
-       return NULL;
+       if (efi_is_64bit())
+               return get_efi_config_table64(sys_table, guid);
+       else
+               return get_efi_config_table32(sys_table, guid);
 }
index ab3aa398383384fb21d65c7320594ebee89cf99f..7e12cbdf957cc7668bd100878585d29af5a71e7d 100644 (file)
@@ -84,6 +84,10 @@ MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(IBFT_ISCSI_VERSION);
 
+#ifndef CONFIG_ISCSI_IBFT_FIND
+struct acpi_table_ibft *ibft_addr;
+#endif
+
 struct ibft_hdr {
        u8 id;
        u8 version;
index 474f304ec109361c59bbd76eb7cf31c8f53a5e40..cdd4f73b48690e9c4a66e397ca7737e7a3a1a8f5 100644 (file)
@@ -40,6 +40,7 @@ config ALTERA_PR_IP_CORE_PLAT
 config FPGA_MGR_ALTERA_PS_SPI
        tristate "Altera FPGA Passive Serial over SPI"
        depends on SPI
+       select BITREVERSE
        help
          FPGA manager driver support for Altera Arria/Cyclone/Stratix
          using the passive serial interface over SPI.
index a13f224303c699a8bc05165084e2b5ec1eb9f72f..0221dee8dd4c6b3e90f159ec024f09e4ee847390 100644 (file)
@@ -210,7 +210,7 @@ static int altera_ps_write_complete(struct fpga_manager *mgr,
                return -EIO;
        }
 
-       if (!IS_ERR(conf->confd)) {
+       if (conf->confd) {
                if (!gpiod_get_raw_value_cansleep(conf->confd)) {
                        dev_err(&mgr->dev, "CONF_DONE is inactive!\n");
                        return -EIO;
@@ -289,10 +289,13 @@ static int altera_ps_probe(struct spi_device *spi)
                return PTR_ERR(conf->status);
        }
 
-       conf->confd = devm_gpiod_get(&spi->dev, "confd", GPIOD_IN);
+       conf->confd = devm_gpiod_get_optional(&spi->dev, "confd", GPIOD_IN);
        if (IS_ERR(conf->confd)) {
-               dev_warn(&spi->dev, "Not using confd gpio: %ld\n",
-                        PTR_ERR(conf->confd));
+               dev_err(&spi->dev, "Failed to get confd gpio: %ld\n",
+                       PTR_ERR(conf->confd));
+               return PTR_ERR(conf->confd);
+       } else if (!conf->confd) {
+               dev_warn(&spi->dev, "Not using confd gpio");
        }
 
        /* Register manager with unique name */
index 343153d47e5b640fe992bde7d31a601d78491d80..004dc03ccf09c190497a9f597f76e70b708f646c 100644 (file)
@@ -38,8 +38,7 @@
 #define SCOM_STATUS_PIB_RESP_MASK      0x00007000
 #define SCOM_STATUS_PIB_RESP_SHIFT     12
 
-#define SCOM_STATUS_ANY_ERR            (SCOM_STATUS_ERR_SUMMARY | \
-                                        SCOM_STATUS_PROTECTION | \
+#define SCOM_STATUS_ANY_ERR            (SCOM_STATUS_PROTECTION | \
                                         SCOM_STATUS_PARITY |     \
                                         SCOM_STATUS_PIB_ABORT | \
                                         SCOM_STATUS_PIB_RESP_MASK)
@@ -251,11 +250,6 @@ static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
        /* Return -EBUSY on PIB abort to force a retry */
        if (status & SCOM_STATUS_PIB_ABORT)
                return -EBUSY;
-       if (status & SCOM_STATUS_ERR_SUMMARY) {
-               fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
-                                sizeof(uint32_t));
-               return -EIO;
-       }
        return 0;
 }
 
index f1a9c0544e3f7f5fc63c8f87298c5630c3254e4b..213aedc97dc2e7d37c04194b889d95acb7763df5 100644 (file)
@@ -309,6 +309,7 @@ static const struct file_operations gpio_mockup_debugfs_ops = {
        .read = gpio_mockup_debugfs_read,
        .write = gpio_mockup_debugfs_write,
        .llseek = no_llseek,
+       .release = single_release,
 };
 
 static void gpio_mockup_debugfs_setup(struct device *dev,
index 378b206d2dc9495dc32c3ffc6fdf06e35262a31e..48fea4c68e8d08df15ada9d917fdf295e19aeb5a 100644 (file)
@@ -604,10 +604,9 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
        u8 new_irqs;
        int level, i;
        u8 invert_irq_mask[MAX_BANK];
-       int reg_direction[MAX_BANK];
+       u8 reg_direction[MAX_BANK];
 
-       regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction,
-                        NBANK(chip));
+       pca953x_read_regs(chip, chip->regs->direction, reg_direction);
 
        if (chip->driver_data & PCA_PCAL) {
                /* Enable latch on interrupt-enabled inputs */
@@ -679,7 +678,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
        bool pending_seen = false;
        bool trigger_seen = false;
        u8 trigger[MAX_BANK];
-       int reg_direction[MAX_BANK];
+       u8 reg_direction[MAX_BANK];
        int ret, i;
 
        if (chip->driver_data & PCA_PCAL) {
@@ -710,8 +709,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
                return false;
 
        /* Remove output pins from the equation */
-       regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction,
-                        NBANK(chip));
+       pca953x_read_regs(chip, chip->regs->direction, reg_direction);
        for (i = 0; i < NBANK(chip); i++)
                cur_stat[i] &= reg_direction[i];
 
@@ -768,7 +766,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 {
        struct i2c_client *client = chip->client;
        struct irq_chip *irq_chip = &chip->irq_chip;
-       int reg_direction[MAX_BANK];
+       u8 reg_direction[MAX_BANK];
        int ret, i;
 
        if (!client->irq)
@@ -789,8 +787,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
         * interrupt.  We have to rely on the previous read for
         * this purpose.
         */
-       regmap_bulk_read(chip->regmap, chip->regs->direction, reg_direction,
-                        NBANK(chip));
+       pca953x_read_regs(chip, chip->regs->direction, reg_direction);
        for (i = 0; i < NBANK(chip); i++)
                chip->irq_stat[i] &= reg_direction[i];
        mutex_init(&chip->irq_lock);
index 39f2f9035c11df2b7c0d7446745a0c83cf7e0cc2..bda28eb82c3fadc70feed81beff1c540fe93d322 100644 (file)
@@ -7,6 +7,7 @@
  *          Mika Westerberg <mika.westerberg@linux.intel.com>
  */
 
+#include <linux/dmi.h>
 #include <linux/errno.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/driver.h>
 
 #include "gpiolib.h"
 
+static int run_edge_events_on_boot = -1;
+module_param(run_edge_events_on_boot, int, 0444);
+MODULE_PARM_DESC(run_edge_events_on_boot,
+                "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
+
 /**
  * struct acpi_gpio_event - ACPI GPIO event handler data
  *
@@ -170,10 +176,13 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
        event->irq_requested = true;
 
        /* Make sure we trigger the initial state of edge-triggered IRQs */
-       value = gpiod_get_raw_value_cansleep(event->desc);
-       if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
-           ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
-               event->handler(event->irq, event);
+       if (run_edge_events_on_boot &&
+           (event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
+               value = gpiod_get_raw_value_cansleep(event->desc);
+               if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
+                   ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
+                       event->handler(event->irq, event);
+       }
 }
 
 static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
@@ -1283,3 +1292,28 @@ static int acpi_gpio_handle_deferred_request_irqs(void)
 }
 /* We must use _sync so that this runs after the first deferred_probe run */
 late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
+
+static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
+               }
+       },
+       {} /* Terminating entry */
+};
+
+static int acpi_gpio_setup_params(void)
+{
+       if (run_edge_events_on_boot < 0) {
+               if (dmi_check_system(run_edge_events_on_boot_blacklist))
+                       run_edge_events_on_boot = 0;
+               else
+                       run_edge_events_on_boot = 1;
+       }
+
+       return 0;
+}
+
+/* Directly after dmi_setup() which runs as core_initcall() */
+postcore_initcall(acpi_gpio_setup_params);
index 567fb98c0892740a8921a18542514fdb84b57fc0..9b44c49a922783d4f06e09248d8211ff50c61c48 100644 (file)
@@ -343,36 +343,27 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
 
                desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
                                                &of_flags);
-               /*
-                * -EPROBE_DEFER in our case means that we found a
-                * valid GPIO property, but no controller has been
-                * registered so far.
-                *
-                * This means we don't need to look any further for
-                * alternate name conventions, and we should really
-                * preserve the return code for our user to be able to
-                * retry probing later.
-                */
-               if (IS_ERR(desc) && PTR_ERR(desc) == -EPROBE_DEFER)
-                       return desc;
 
-               if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
+               if (!IS_ERR(desc) || PTR_ERR(desc) != -ENOENT)
                        break;
        }
 
-       /* Special handling for SPI GPIOs if used */
-       if (IS_ERR(desc))
+       if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+               /* Special handling for SPI GPIOs if used */
                desc = of_find_spi_gpio(dev, con_id, &of_flags);
-       if (IS_ERR(desc)) {
+       }
+
+       if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
                /* This quirk looks up flags and all */
                desc = of_find_spi_cs_gpio(dev, con_id, idx, flags);
                if (!IS_ERR(desc))
                        return desc;
        }
 
-       /* Special handling for regulator GPIOs if used */
-       if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
+       if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+               /* Special handling for regulator GPIOs if used */
                desc = of_find_regulator_gpio(dev, con_id, &of_flags);
+       }
 
        if (IS_ERR(desc))
                return desc;
index 3ee99d070608240914f64839c7ab36336caabe21..d9074191edef4da533d27673660e6f357df32fe7 100644 (file)
@@ -535,6 +535,14 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
        if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS)
                return -EINVAL;
 
+       /*
+        * Do not allow both INPUT & OUTPUT flags to be set as they are
+        * contradictory.
+        */
+       if ((lflags & GPIOHANDLE_REQUEST_INPUT) &&
+           (lflags & GPIOHANDLE_REQUEST_OUTPUT))
+               return -EINVAL;
+
        /*
         * Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If
         * the hardware actually supports enabling both at the same time the
@@ -926,7 +934,9 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
        }
 
        /* This is just wrong: we don't look for events on output lines */
-       if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
+       if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) ||
+           (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
+           (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)) {
                ret = -EINVAL;
                goto out_free_label;
        }
@@ -940,10 +950,6 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
 
        if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
                set_bit(FLAG_ACTIVE_LOW, &desc->flags);
-       if (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN)
-               set_bit(FLAG_OPEN_DRAIN, &desc->flags);
-       if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
-               set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 
        ret = gpiod_direction_input(desc);
        if (ret)
@@ -956,9 +962,11 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
        }
 
        if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
-               irqflags |= IRQF_TRIGGER_RISING;
+               irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+                       IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
        if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE)
-               irqflags |= IRQF_TRIGGER_FALLING;
+               irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+                       IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
        irqflags |= IRQF_ONESHOT;
 
        INIT_KFIFO(le->events);
@@ -1089,9 +1097,11 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
                        lineinfo.flags |= GPIOLINE_FLAG_ACTIVE_LOW;
                if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
-                       lineinfo.flags |= GPIOLINE_FLAG_OPEN_DRAIN;
+                       lineinfo.flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
+                                          GPIOLINE_FLAG_IS_OUT);
                if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
-                       lineinfo.flags |= GPIOLINE_FLAG_OPEN_SOURCE;
+                       lineinfo.flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
+                                          GPIOLINE_FLAG_IS_OUT);
 
                if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
                        return -EFAULT;
@@ -1369,21 +1379,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
        if (status)
                goto err_remove_from_list;
 
-       status = gpiochip_irqchip_init_valid_mask(chip);
-       if (status)
-               goto err_remove_from_list;
-
        status = gpiochip_alloc_valid_mask(chip);
        if (status)
-               goto err_remove_irqchip_mask;
-
-       status = gpiochip_add_irqchip(chip, lock_key, request_key);
-       if (status)
-               goto err_free_gpiochip_mask;
+               goto err_remove_from_list;
 
        status = of_gpiochip_add(chip);
        if (status)
-               goto err_remove_chip;
+               goto err_free_gpiochip_mask;
 
        status = gpiochip_init_valid_mask(chip);
        if (status)
@@ -1392,18 +1394,31 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
        for (i = 0; i < chip->ngpio; i++) {
                struct gpio_desc *desc = &gdev->descs[i];
 
-               if (chip->get_direction && gpiochip_line_is_valid(chip, i))
-                       desc->flags = !chip->get_direction(chip, i) ?
-                                       (1 << FLAG_IS_OUT) : 0;
-               else
-                       desc->flags = !chip->direction_input ?
-                                       (1 << FLAG_IS_OUT) : 0;
+               if (chip->get_direction && gpiochip_line_is_valid(chip, i)) {
+                       if (!chip->get_direction(chip, i))
+                               set_bit(FLAG_IS_OUT, &desc->flags);
+                       else
+                               clear_bit(FLAG_IS_OUT, &desc->flags);
+               } else {
+                       if (!chip->direction_input)
+                               set_bit(FLAG_IS_OUT, &desc->flags);
+                       else
+                               clear_bit(FLAG_IS_OUT, &desc->flags);
+               }
        }
 
        acpi_gpiochip_add(chip);
 
        machine_gpiochip_add(chip);
 
+       status = gpiochip_irqchip_init_valid_mask(chip);
+       if (status)
+               goto err_remove_acpi_chip;
+
+       status = gpiochip_add_irqchip(chip, lock_key, request_key);
+       if (status)
+               goto err_remove_irqchip_mask;
+
        /*
         * By first adding the chardev, and then adding the device,
         * we get a device node entry in sysfs under
@@ -1415,21 +1430,21 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
        if (gpiolib_initialized) {
                status = gpiochip_setup_dev(gdev);
                if (status)
-                       goto err_remove_acpi_chip;
+                       goto err_remove_irqchip;
        }
        return 0;
 
+err_remove_irqchip:
+       gpiochip_irqchip_remove(chip);
+err_remove_irqchip_mask:
+       gpiochip_irqchip_free_valid_mask(chip);
 err_remove_acpi_chip:
        acpi_gpiochip_remove(chip);
 err_remove_of_chip:
        gpiochip_free_hogs(chip);
        of_gpiochip_remove(chip);
-err_remove_chip:
-       gpiochip_irqchip_remove(chip);
 err_free_gpiochip_mask:
        gpiochip_free_valid_mask(chip);
-err_remove_irqchip_mask:
-       gpiochip_irqchip_free_valid_mask(chip);
 err_remove_from_list:
        spin_lock_irqsave(&gpio_lock, flags);
        list_del(&gdev->list);
index 1d80222587ad2a8553c24ddeed23db1abadac907..3c88420e3497a44a1d8320f171701a18ee408641 100644 (file)
@@ -394,7 +394,7 @@ config DRM_R128
 config DRM_I810
        tristate "Intel I810"
        # !PREEMPT because of missing ioctl locking
-       depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
+       depends on DRM && AGP && AGP_INTEL && (!PREEMPTION || BROKEN)
        help
          Choose this option if you have an Intel I810 graphics card.  If M is
          selected, the module will be called i810.  AGP support is required
index 1d3ee9c42f7eda2f811be1d16ba9e554c498bf57..6a5c96e519b15983bc3fb1ff1037727245245511 100644 (file)
@@ -1140,7 +1140,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
                        adev->asic_type != CHIP_FIJI &&
                        adev->asic_type != CHIP_POLARIS10 &&
                        adev->asic_type != CHIP_POLARIS11 &&
-                       adev->asic_type != CHIP_POLARIS12) ?
+                       adev->asic_type != CHIP_POLARIS12 &&
+                       adev->asic_type != CHIP_VEGAM) ?
                        VI_BO_SIZE_ALIGN : 1;
 
        mapping_flags = AMDGPU_VM_PAGE_READABLE;
index 9b384a94d2f34b608108f5b971d0475781787ffa..3e35a8f2c5e553e4c714deff5e838ac1510a2f59 100644 (file)
@@ -574,6 +574,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
        { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
+       { 0x1002, 0x699f, 0x1028, 0x0814, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0, 0, 0, 0, 0 },
index e069de8b54e619fbd9a630e34ad9f757731d27ab..8b26c970a3cb1f364c1595c8a394daf44420d74d 100644 (file)
@@ -1044,29 +1044,27 @@ static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p,
                        return r;
                }
 
-               fence = amdgpu_ctx_get_fence(ctx, entity,
-                                            deps[i].handle);
+               fence = amdgpu_ctx_get_fence(ctx, entity, deps[i].handle);
+               amdgpu_ctx_put(ctx);
+
+               if (IS_ERR(fence))
+                       return PTR_ERR(fence);
+               else if (!fence)
+                       continue;
 
                if (chunk->chunk_id == AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES) {
-                       struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
+                       struct drm_sched_fence *s_fence;
                        struct dma_fence *old = fence;
 
+                       s_fence = to_drm_sched_fence(fence);
                        fence = dma_fence_get(&s_fence->scheduled);
                        dma_fence_put(old);
                }
 
-               if (IS_ERR(fence)) {
-                       r = PTR_ERR(fence);
-                       amdgpu_ctx_put(ctx);
+               r = amdgpu_sync_fence(p->adev, &p->job->sync, fence, true);
+               dma_fence_put(fence);
+               if (r)
                        return r;
-               } else if (fence) {
-                       r = amdgpu_sync_fence(p->adev, &p->job->sync, fence,
-                                       true);
-                       dma_fence_put(fence);
-                       amdgpu_ctx_put(ctx);
-                       if (r)
-                               return r;
-               }
        }
        return 0;
 }
@@ -1145,6 +1143,9 @@ static int amdgpu_cs_process_syncobj_out_dep(struct amdgpu_cs_parser *p,
        num_deps = chunk->length_dw * 4 /
                sizeof(struct drm_amdgpu_cs_chunk_sem);
 
+       if (p->post_deps)
+               return -EINVAL;
+
        p->post_deps = kmalloc_array(num_deps, sizeof(*p->post_deps),
                                     GFP_KERNEL);
        p->num_post_deps = 0;
@@ -1168,8 +1169,7 @@ static int amdgpu_cs_process_syncobj_out_dep(struct amdgpu_cs_parser *p,
 
 
 static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p,
-                                                     struct amdgpu_cs_chunk
-                                                     *chunk)
+                                                     struct amdgpu_cs_chunk *chunk)
 {
        struct drm_amdgpu_cs_chunk_syncobj *syncobj_deps;
        unsigned num_deps;
@@ -1179,6 +1179,9 @@ static int amdgpu_cs_process_syncobj_timeline_out_dep(struct amdgpu_cs_parser *p
        num_deps = chunk->length_dw * 4 /
                sizeof(struct drm_amdgpu_cs_chunk_syncobj);
 
+       if (p->post_deps)
+               return -EINVAL;
+
        p->post_deps = kmalloc_array(num_deps, sizeof(*p->post_deps),
                                     GFP_KERNEL);
        p->num_post_deps = 0;
index f539a2a927747add782a608796775299128bd184..7398b4850649bd64c45061c10df4f6faec68d31e 100644 (file)
@@ -534,21 +534,24 @@ int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx,
                               struct drm_sched_entity *entity)
 {
        struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
-       unsigned idx = centity->sequence & (amdgpu_sched_jobs - 1);
-       struct dma_fence *other = centity->fences[idx];
+       struct dma_fence *other;
+       unsigned idx;
+       long r;
 
-       if (other) {
-               signed long r;
-               r = dma_fence_wait(other, true);
-               if (r < 0) {
-                       if (r != -ERESTARTSYS)
-                               DRM_ERROR("Error (%ld) waiting for fence!\n", r);
+       spin_lock(&ctx->ring_lock);
+       idx = centity->sequence & (amdgpu_sched_jobs - 1);
+       other = dma_fence_get(centity->fences[idx]);
+       spin_unlock(&ctx->ring_lock);
 
-                       return r;
-               }
-       }
+       if (!other)
+               return 0;
 
-       return 0;
+       r = dma_fence_wait(other, true);
+       if (r < 0 && r != -ERESTARTSYS)
+               DRM_ERROR("Error (%ld) waiting for fence!\n", r);
+
+       dma_fence_put(other);
+       return r;
 }
 
 void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr)
index 6d54decef7f8156d0a20883151dab0af1c90d6de..5652cc72ed3a9b3adcf004a654e8be57b9cd2552 100644 (file)
@@ -707,7 +707,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
        thread = (*pos & GENMASK_ULL(59, 52)) >> 52;
        bank = (*pos & GENMASK_ULL(61, 60)) >> 60;
 
-       data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL);
+       data = kcalloc(1024, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
index f2e8b4238efd49d6efac87b9e2d06801a94aca06..5376328d3fd0af4c8f5aeae321913d01fa03cb92 100644 (file)
@@ -148,7 +148,7 @@ struct amdgpu_mgpu_info mgpu_info = {
        .mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
 };
 int amdgpu_ras_enable = -1;
-uint amdgpu_ras_mask = 0xffffffff;
+uint amdgpu_ras_mask = 0xfffffffb;
 
 /**
  * DOC: vramlimit (int)
index df8a2355483172fa6bc45303d93439036f681f2c..f6ac1e9548f276d4279d2830a15e7ca45428973f 100644 (file)
@@ -32,7 +32,6 @@ struct amdgpu_gds {
        uint32_t gws_size;
        uint32_t oa_size;
        uint32_t gds_compute_max_wave_id;
-       uint32_t vgt_gs_max_wave_id;
 };
 
 struct amdgpu_gds_reg_offset {
index 8b7efd0a70280a486160ccce13ec736adaccc33c..2b546567853b45ee155fcc9faa9592b46d38066c 100644 (file)
@@ -159,12 +159,16 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev,
        struct amdgpu_device *adev = ddev->dev_private;
        enum amd_pm_state_type pm;
 
-       if (is_support_sw_smu(adev) && adev->smu.ppt_funcs->get_current_power_state)
-               pm = amdgpu_smu_get_current_power_state(adev);
-       else if (adev->powerplay.pp_funcs->get_current_power_state)
+       if (is_support_sw_smu(adev)) {
+               if (adev->smu.ppt_funcs->get_current_power_state)
+                       pm = amdgpu_smu_get_current_power_state(adev);
+               else
+                       pm = adev->pm.dpm.user_state;
+       } else if (adev->powerplay.pp_funcs->get_current_power_state) {
                pm = amdgpu_dpm_get_current_power_state(adev);
-       else
+       } else {
                pm = adev->pm.dpm.user_state;
+       }
 
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        (pm == POWER_STATE_TYPE_BATTERY) ? "battery" :
@@ -191,7 +195,11 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev,
                goto fail;
        }
 
-       if (adev->powerplay.pp_funcs->dispatch_tasks) {
+       if (is_support_sw_smu(adev)) {
+               mutex_lock(&adev->pm.mutex);
+               adev->pm.dpm.user_state = state;
+               mutex_unlock(&adev->pm.mutex);
+       } else if (adev->powerplay.pp_funcs->dispatch_tasks) {
                amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state);
        } else {
                mutex_lock(&adev->pm.mutex);
@@ -1734,7 +1742,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev,
                return -EINVAL;
 
        if (is_support_sw_smu(adev)) {
-               err = smu_get_current_rpm(&adev->smu, &speed);
+               err = smu_get_fan_speed_rpm(&adev->smu, &speed);
                if (err)
                        return err;
        } else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) {
@@ -1794,7 +1802,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev,
                return -EINVAL;
 
        if (is_support_sw_smu(adev)) {
-               err = smu_get_current_rpm(&adev->smu, &rpm);
+               err = smu_get_fan_speed_rpm(&adev->smu, &rpm);
                if (err)
                        return err;
        } else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) {
@@ -3067,28 +3075,44 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
        if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK, (void *)&value64, &size))
                seq_printf(m, "SMC Feature Mask: 0x%016llx\n", value64);
 
-       /* UVD clocks */
-       if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value, &size)) {
-               if (!value) {
-                       seq_printf(m, "UVD: Disabled\n");
-               } else {
-                       seq_printf(m, "UVD: Enabled\n");
-                       if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size))
-                               seq_printf(m, "\t%u MHz (DCLK)\n", value/100);
-                       if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size))
-                               seq_printf(m, "\t%u MHz (VCLK)\n", value/100);
+       if (adev->asic_type > CHIP_VEGA20) {
+               /* VCN clocks */
+               if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCN_POWER_STATE, (void *)&value, &size)) {
+                       if (!value) {
+                               seq_printf(m, "VCN: Disabled\n");
+                       } else {
+                               seq_printf(m, "VCN: Enabled\n");
+                               if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size))
+                                       seq_printf(m, "\t%u MHz (DCLK)\n", value/100);
+                               if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size))
+                                       seq_printf(m, "\t%u MHz (VCLK)\n", value/100);
+                       }
                }
-       }
-       seq_printf(m, "\n");
+               seq_printf(m, "\n");
+       } else {
+               /* UVD clocks */
+               if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value, &size)) {
+                       if (!value) {
+                               seq_printf(m, "UVD: Disabled\n");
+                       } else {
+                               seq_printf(m, "UVD: Enabled\n");
+                               if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size))
+                                       seq_printf(m, "\t%u MHz (DCLK)\n", value/100);
+                               if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size))
+                                       seq_printf(m, "\t%u MHz (VCLK)\n", value/100);
+                       }
+               }
+               seq_printf(m, "\n");
 
-       /* VCE clocks */
-       if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value, &size)) {
-               if (!value) {
-                       seq_printf(m, "VCE: Disabled\n");
-               } else {
-                       seq_printf(m, "VCE: Enabled\n");
-                       if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value, &size))
-                               seq_printf(m, "\t%u MHz (ECCLK)\n", value/100);
+               /* VCE clocks */
+               if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value, &size)) {
+                       if (!value) {
+                               seq_printf(m, "VCE: Disabled\n");
+                       } else {
+                               seq_printf(m, "VCE: Enabled\n");
+                               if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value, &size))
+                                       seq_printf(m, "\t%u MHz (ECCLK)\n", value/100);
+                       }
                }
        }
 
index 1a4412e47810256727036fdf21ab90ebb80d090e..fac7aa2c244fa9f80776165e193313d543fb9082 100644 (file)
@@ -136,11 +136,6 @@ static int amdgpu_ras_reserve_vram(struct amdgpu_device *adev,
 static int amdgpu_ras_release_vram(struct amdgpu_device *adev,
                struct amdgpu_bo **bo_ptr);
 
-static void amdgpu_ras_self_test(struct amdgpu_device *adev)
-{
-       /* TODO */
-}
-
 static ssize_t amdgpu_ras_debugfs_read(struct file *f, char __user *buf,
                                        size_t size, loff_t *pos)
 {
@@ -689,6 +684,12 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
        if (!obj)
                return -EINVAL;
 
+       if (block_info.block_id != TA_RAS_BLOCK__UMC) {
+               DRM_INFO("%s error injection is not supported yet\n",
+                        ras_block_str(info->head.block));
+               return -EINVAL;
+       }
+
        ret = psp_ras_trigger_error(&adev->psp, &block_info);
        if (ret)
                DRM_ERROR("RAS ERROR: inject %s error failed ret %d\n",
@@ -1557,6 +1558,12 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
 
        amdgpu_ras_check_supported(adev, &con->hw_supported,
                        &con->supported);
+       if (!con->hw_supported) {
+               amdgpu_ras_set_context(adev, NULL);
+               kfree(con);
+               return 0;
+       }
+
        con->features = 0;
        INIT_LIST_HEAD(&con->head);
        /* Might need get this flag from vbios. */
@@ -1570,8 +1577,6 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
        if (amdgpu_ras_fs_init(adev))
                goto fs_out;
 
-       amdgpu_ras_self_test(adev);
-
        DRM_INFO("RAS INFO: ras initialized successfully, "
                        "hardware ability[%x] ras_mask[%x]\n",
                        con->hw_supported, con->supported);
index 99f14fcc1460550c66e0bf7dfdfedcfc8b297723..19661c645703e56809c584b61916d141d5ed32d0 100644 (file)
@@ -30,6 +30,7 @@
 #define AMDGPU_VCN_FIRMWARE_OFFSET     256
 #define AMDGPU_VCN_MAX_ENC_RINGS       3
 
+#define VCN_DEC_KMD_CMD                0x80000000
 #define VCN_DEC_CMD_FENCE              0x00000000
 #define VCN_DEC_CMD_TRAP               0x00000001
 #define VCN_DEC_CMD_WRITE_REG          0x00000004
index 1675d5837c3c8b0995585b79ba26c443d2629c54..f41287f9000da599accefb3382575d405c8a030b 100644 (file)
@@ -1441,6 +1441,15 @@ static void gfx_v10_0_init_compute_vmid(struct amdgpu_device *adev)
        }
        nv_grbm_select(adev, 0, 0, 0, 0);
        mutex_unlock(&adev->srbm_mutex);
+
+       /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+          acccess. These should be enabled by FW for target VMIDs. */
+       for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
+               WREG32_SOC15_OFFSET(GC, 0, mmGDS_VMID0_BASE, 2 * i, 0);
+               WREG32_SOC15_OFFSET(GC, 0, mmGDS_VMID0_SIZE, 2 * i, 0);
+               WREG32_SOC15_OFFSET(GC, 0, mmGDS_GWS_VMID0, i, 0);
+               WREG32_SOC15_OFFSET(GC, 0, mmGDS_OA_VMID0, i, 0);
+       }
 }
 
 static void gfx_v10_0_tcp_harvest(struct amdgpu_device *adev)
@@ -4197,15 +4206,6 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 header, control = 0;
 
-       /* Prevent a hw deadlock due to a wave ID mismatch between ME and GDS.
-        * This resets the wave ID counters. (needed by transform feedback)
-        * TODO: This might only be needed on a VMID switch when we change
-        *       the GDS OA mapping, not sure.
-        */
-       amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-       amdgpu_ring_write(ring, mmVGT_GS_MAX_WAVE_ID);
-       amdgpu_ring_write(ring, ring->adev->gds.vgt_gs_max_wave_id);
-
        if (ib->flags & AMDGPU_IB_FLAG_CE)
                header = PACKET3(PACKET3_INDIRECT_BUFFER_CNST, 2);
        else
@@ -4611,6 +4611,7 @@ gfx_v10_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
                cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
                                            TIME_STAMP_INT_ENABLE, 0);
                WREG32(cp_int_cntl_reg, cp_int_cntl);
+               break;
        case AMDGPU_IRQ_STATE_ENABLE:
                cp_int_cntl = RREG32(cp_int_cntl_reg);
                cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
@@ -4951,7 +4952,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
                5 + /* HDP_INVL */
                8 + 8 + /* FENCE x2 */
                2, /* SWITCH_BUFFER */
-       .emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_gfx */
+       .emit_ib_size = 4, /* gfx_v10_0_ring_emit_ib_gfx */
        .emit_ib = gfx_v10_0_ring_emit_ib_gfx,
        .emit_fence = gfx_v10_0_ring_emit_fence,
        .emit_pipeline_sync = gfx_v10_0_ring_emit_pipeline_sync,
@@ -5102,7 +5103,6 @@ static void gfx_v10_0_set_gds_init(struct amdgpu_device *adev)
        default:
                adev->gds.gds_size = 0x10000;
                adev->gds.gds_compute_max_wave_id = 0x4ff;
-               adev->gds.vgt_gs_max_wave_id = 0x3ff;
                break;
        }
 
index 0db9f488da7eb4a0db8672cb88ab4d16a0c5a20f..21187275dfd37e496db7de2de3f21f2518a606f9 100644 (file)
@@ -1879,6 +1879,15 @@ static void gfx_v7_0_init_compute_vmid(struct amdgpu_device *adev)
        }
        cik_srbm_select(adev, 0, 0, 0, 0);
        mutex_unlock(&adev->srbm_mutex);
+
+       /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+          acccess. These should be enabled by FW for target VMIDs. */
+       for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
+               WREG32(amdgpu_gds_reg_offset[i].mem_base, 0);
+               WREG32(amdgpu_gds_reg_offset[i].mem_size, 0);
+               WREG32(amdgpu_gds_reg_offset[i].gws, 0);
+               WREG32(amdgpu_gds_reg_offset[i].oa, 0);
+       }
 }
 
 static void gfx_v7_0_config_init(struct amdgpu_device *adev)
index 5f401b41ef7ce67cf6aefcc59010ca4d090e1db5..ee1ccdcf2d30e128751b82f9839397618bc2fb08 100644 (file)
@@ -1321,6 +1321,39 @@ static int gfx_v8_0_rlc_init(struct amdgpu_device *adev)
        return 0;
 }
 
+static int gfx_v8_0_csb_vram_pin(struct amdgpu_device *adev)
+{
+       int r;
+
+       r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+       if (unlikely(r != 0))
+               return r;
+
+       r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj,
+                       AMDGPU_GEM_DOMAIN_VRAM);
+       if (!r)
+               adev->gfx.rlc.clear_state_gpu_addr =
+                       amdgpu_bo_gpu_offset(adev->gfx.rlc.clear_state_obj);
+
+       amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+
+       return r;
+}
+
+static void gfx_v8_0_csb_vram_unpin(struct amdgpu_device *adev)
+{
+       int r;
+
+       if (!adev->gfx.rlc.clear_state_obj)
+               return;
+
+       r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
+       if (likely(r == 0)) {
+               amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
+               amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+       }
+}
+
 static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
 {
        amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
@@ -3706,6 +3739,15 @@ static void gfx_v8_0_init_compute_vmid(struct amdgpu_device *adev)
        }
        vi_srbm_select(adev, 0, 0, 0, 0);
        mutex_unlock(&adev->srbm_mutex);
+
+       /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+          acccess. These should be enabled by FW for target VMIDs. */
+       for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
+               WREG32(amdgpu_gds_reg_offset[i].mem_base, 0);
+               WREG32(amdgpu_gds_reg_offset[i].mem_size, 0);
+               WREG32(amdgpu_gds_reg_offset[i].gws, 0);
+               WREG32(amdgpu_gds_reg_offset[i].oa, 0);
+       }
 }
 
 static void gfx_v8_0_config_init(struct amdgpu_device *adev)
@@ -4776,6 +4818,10 @@ static int gfx_v8_0_hw_init(void *handle)
        gfx_v8_0_init_golden_registers(adev);
        gfx_v8_0_constants_init(adev);
 
+       r = gfx_v8_0_csb_vram_pin(adev);
+       if (r)
+               return r;
+
        r = adev->gfx.rlc.funcs->resume(adev);
        if (r)
                return r;
@@ -4892,6 +4938,9 @@ static int gfx_v8_0_hw_fini(void *handle)
        else
                pr_err("rlc is busy, skip halt rlc\n");
        amdgpu_gfx_rlc_exit_safe_mode(adev);
+
+       gfx_v8_0_csb_vram_unpin(adev);
+
        return 0;
 }
 
index f4c4eea625268045795cb0dbfc892d2be823aacc..c066e1d3f981da65d7d19f2c9615a121c1aa19f0 100644 (file)
@@ -596,14 +596,18 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
        case CHIP_VEGA20:
                break;
        case CHIP_RAVEN:
-               if (adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
-                       break;
-               if ((adev->gfx.rlc_fw_version != 106 &&
-                    adev->gfx.rlc_fw_version < 531) ||
-                   (adev->gfx.rlc_fw_version == 53815) ||
-                   (adev->gfx.rlc_feature_version < 1) ||
-                   !adev->gfx.rlc.is_rlc_v2_1)
+               if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
+                       &&((adev->gfx.rlc_fw_version != 106 &&
+                            adev->gfx.rlc_fw_version < 531) ||
+                           (adev->gfx.rlc_fw_version == 53815) ||
+                           (adev->gfx.rlc_feature_version < 1) ||
+                           !adev->gfx.rlc.is_rlc_v2_1))
                        adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
+
+               if (adev->pm.pp_feature & PP_GFXOFF_MASK)
+                       adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
+                               AMD_PG_SUPPORT_CP |
+                               AMD_PG_SUPPORT_RLC_SMU_HS;
                break;
        default:
                break;
@@ -1918,6 +1922,15 @@ static void gfx_v9_0_init_compute_vmid(struct amdgpu_device *adev)
        }
        soc15_grbm_select(adev, 0, 0, 0, 0);
        mutex_unlock(&adev->srbm_mutex);
+
+       /* Initialize all compute VMIDs to have no GDS, GWS, or OA
+          acccess. These should be enabled by FW for target VMIDs. */
+       for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
+               WREG32_SOC15_OFFSET(GC, 0, mmGDS_VMID0_BASE, 2 * i, 0);
+               WREG32_SOC15_OFFSET(GC, 0, mmGDS_VMID0_SIZE, 2 * i, 0);
+               WREG32_SOC15_OFFSET(GC, 0, mmGDS_GWS_VMID0, i, 0);
+               WREG32_SOC15_OFFSET(GC, 0, mmGDS_OA_VMID0, i, 0);
+       }
 }
 
 static void gfx_v9_0_constants_init(struct amdgpu_device *adev)
@@ -4860,7 +4873,7 @@ static void gfx_v9_0_ring_soft_recovery(struct amdgpu_ring *ring, unsigned vmid)
        value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
        value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
        value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
-       WREG32(mmSQ_CMD, value);
+       WREG32_SOC15(GC, 0, mmSQ_CMD, value);
 }
 
 static void gfx_v9_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
index 662612f89c70b5f2990a111aa740d350541a7127..9922bce3fd89e1362de3f60ed733333a0a7593c5 100644 (file)
@@ -552,7 +552,6 @@ static int nv_common_early_init(void *handle)
                        AMD_CG_SUPPORT_BIF_LS;
                adev->pg_flags = AMD_PG_SUPPORT_VCN |
                        AMD_PG_SUPPORT_VCN_DPG |
-                       AMD_PG_SUPPORT_MMHUB |
                        AMD_PG_SUPPORT_ATHUB;
                adev->external_rev_id = adev->rev_id + 0x1;
                break;
index 23265414d44867b81c36d85f1ef87e67013ca95f..04fbf05d7176b4276c5876382f7dabd6b8e4e6d6 100644 (file)
@@ -992,11 +992,6 @@ static int soc15_common_early_init(void *handle)
 
                        adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN;
                }
-
-               if (adev->pm.pp_feature & PP_GFXOFF_MASK)
-                       adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
-                               AMD_PG_SUPPORT_CP |
-                               AMD_PG_SUPPORT_RLC_SMU_HS;
                break;
        default:
                /* FIXME: not supported yet */
index 988c0adaca916e797d42b236ad39a487adf013a4..dfde886cc6bd161928835e9c79f23b176329d15a 100644 (file)
@@ -372,11 +372,8 @@ static void vcn_v2_0_mc_resume(struct amdgpu_device *adev)
                WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
                        upper_32_bits(adev->vcn.gpu_addr));
                offset = size;
-               /* No signed header for now from firmware
                WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0,
                        AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
-               */
-               WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0, 0);
        }
 
        WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE0, size);
@@ -1488,7 +1485,7 @@ static void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET, 0));
        amdgpu_ring_write(ring, 0);
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
-       amdgpu_ring_write(ring, VCN_DEC_CMD_PACKET_START << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
 }
 
 /**
@@ -1501,7 +1498,7 @@ static void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
 static void vcn_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring)
 {
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
-       amdgpu_ring_write(ring, VCN_DEC_CMD_PACKET_END << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_END << 1));
 }
 
 /**
@@ -1546,7 +1543,7 @@ static void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
        amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
-       amdgpu_ring_write(ring, VCN_DEC_CMD_FENCE << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_FENCE << 1));
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET, 0));
        amdgpu_ring_write(ring, 0);
@@ -1556,7 +1553,7 @@ static void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
 
-       amdgpu_ring_write(ring, VCN_DEC_CMD_TRAP << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_TRAP << 1));
 }
 
 /**
@@ -1600,7 +1597,7 @@ static void vcn_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring,
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
 
-       amdgpu_ring_write(ring, VCN_DEC_CMD_REG_READ_COND_WAIT << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_REG_READ_COND_WAIT << 1));
 }
 
 static void vcn_v2_0_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
@@ -1629,7 +1626,7 @@ static void vcn_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring,
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
 
-       amdgpu_ring_write(ring, VCN_DEC_CMD_WRITE_REG << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_WRITE_REG << 1));
 }
 
 /**
@@ -2082,6 +2079,36 @@ static int vcn_v2_0_process_interrupt(struct amdgpu_device *adev,
        return 0;
 }
 
+static int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring)
+{
+       struct amdgpu_device *adev = ring->adev;
+       uint32_t tmp = 0;
+       unsigned i;
+       int r;
+
+       WREG32(adev->vcn.external.scratch9, 0xCAFEDEAD);
+       r = amdgpu_ring_alloc(ring, 4);
+       if (r)
+               return r;
+       amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
+       amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
+       amdgpu_ring_write(ring, 0xDEADBEEF);
+       amdgpu_ring_commit(ring);
+       for (i = 0; i < adev->usec_timeout; i++) {
+               tmp = RREG32(adev->vcn.external.scratch9);
+               if (tmp == 0xDEADBEEF)
+                       break;
+               DRM_UDELAY(1);
+       }
+
+       if (i >= adev->usec_timeout)
+               r = -ETIMEDOUT;
+
+       return r;
+}
+
+
 static int vcn_v2_0_set_powergating_state(void *handle,
                                          enum amd_powergating_state state)
 {
@@ -2145,7 +2172,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = {
        .emit_ib = vcn_v2_0_dec_ring_emit_ib,
        .emit_fence = vcn_v2_0_dec_ring_emit_fence,
        .emit_vm_flush = vcn_v2_0_dec_ring_emit_vm_flush,
-       .test_ring = amdgpu_vcn_dec_ring_test_ring,
+       .test_ring = vcn_v2_0_dec_ring_test_ring,
        .test_ib = amdgpu_vcn_dec_ring_test_ib,
        .insert_nop = vcn_v2_0_dec_ring_insert_nop,
        .insert_start = vcn_v2_0_dec_ring_insert_start,
index 26b15cc56c31c60b624ba13eaf566cfad3525747..1d3cd5c50d5f2b06191e5bf8ff1fee7bed7a6225 100644 (file)
@@ -1567,32 +1567,6 @@ copy_from_user_failed:
        return err;
 }
 
-static int kfd_ioctl_alloc_queue_gws(struct file *filep,
-               struct kfd_process *p, void *data)
-{
-       int retval;
-       struct kfd_ioctl_alloc_queue_gws_args *args = data;
-       struct kfd_dev *dev;
-
-       if (!hws_gws_support)
-               return -ENODEV;
-
-       dev = kfd_device_by_id(args->gpu_id);
-       if (!dev) {
-               pr_debug("Could not find gpu id 0x%x\n", args->gpu_id);
-               return -ENODEV;
-       }
-       if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
-               return -ENODEV;
-
-       mutex_lock(&p->mutex);
-       retval = pqm_set_gws(&p->pqm, args->queue_id, args->num_gws ? dev->gws : NULL);
-       mutex_unlock(&p->mutex);
-
-       args->first_gws = 0;
-       return retval;
-}
-
 static int kfd_ioctl_get_dmabuf_info(struct file *filep,
                struct kfd_process *p, void *data)
 {
@@ -1795,8 +1769,6 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
        AMDKFD_IOCTL_DEF(AMDKFD_IOC_IMPORT_DMABUF,
                                kfd_ioctl_import_dmabuf, 0),
 
-       AMDKFD_IOCTL_DEF(AMDKFD_IOC_ALLOC_QUEUE_GWS,
-                       kfd_ioctl_alloc_queue_gws, 0),
 };
 
 #define AMDKFD_CORE_IOCTL_COUNT        ARRAY_SIZE(amdkfd_ioctls)
index 7923714421955a9cce8e57d9745518ecac50f55e..4e3fc284f6aca24db230a9f1dcea271d4bf0e5f5 100644 (file)
@@ -668,6 +668,7 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev,
        case CHIP_RAVEN:
                pcache_info = raven_cache_info;
                num_of_cache_types = ARRAY_SIZE(raven_cache_info);
+               break;
        case CHIP_NAVI10:
                pcache_info = navi10_cache_info;
                num_of_cache_types = ARRAY_SIZE(navi10_cache_info);
index 4f8a6ffc577579daa70dcaee52c1154012c4a199..9cd3eb2d90bd6b54cc47ec698eba07c146bd9c1b 100644 (file)
@@ -429,7 +429,6 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
 
        switch (type) {
        case KFD_MQD_TYPE_CP:
-               pr_debug("%s@%i\n", __func__, __LINE__);
        case KFD_MQD_TYPE_COMPUTE:
                pr_debug("%s@%i\n", __func__, __LINE__);
                mqd->allocate_mqd = allocate_mqd;
index 4a29f72334d0fa88d738a93f5bd3778c30a81615..45be7a2132bb3b0f548004f38ee8e542608d534d 100644 (file)
@@ -3131,13 +3131,25 @@ static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector,
                                      const struct drm_connector_state *state)
 {
-       uint32_t bpc = connector->display_info.bpc;
+       uint8_t bpc = (uint8_t)connector->display_info.bpc;
+
+       /* Assume 8 bpc by default if no bpc is specified. */
+       bpc = bpc ? bpc : 8;
 
        if (!state)
                state = connector->state;
 
        if (state) {
-               bpc = state->max_bpc;
+               /*
+                * Cap display bpc based on the user requested value.
+                *
+                * The value for state->max_bpc may not correctly updated
+                * depending on when the connector gets added to the state
+                * or if this was called outside of atomic check, so it
+                * can't be used directly.
+                */
+               bpc = min(bpc, state->max_requested_bpc);
+
                /* Round down to the nearest even number. */
                bpc = bpc - (bpc & 1);
        }
index c1a92c16535cd80dfab61db06e15243ab061c7fa..5cc3acccda2accfa5e57cc5b53e8463376f8b1b6 100644 (file)
@@ -262,12 +262,12 @@ void dce110_clk_mgr_construct(
                struct dc_context *ctx,
                struct clk_mgr_internal *clk_mgr)
 {
+       dce_clk_mgr_construct(ctx, clk_mgr);
+
        memcpy(clk_mgr->max_clks_by_state,
                dce110_max_clks_by_state,
                sizeof(dce110_max_clks_by_state));
 
-       dce_clk_mgr_construct(ctx, clk_mgr);
-
        clk_mgr->regs = &disp_clk_regs;
        clk_mgr->clk_mgr_shift = &disp_clk_shift;
        clk_mgr->clk_mgr_mask = &disp_clk_mask;
index 778392c73187d0a39703b3e8aa54fbcff7debc82..7c746ef1e32ea0a54ba37b560f8c0aad6a76c260 100644 (file)
@@ -226,12 +226,12 @@ void dce112_clk_mgr_construct(
                struct dc_context *ctx,
                struct clk_mgr_internal *clk_mgr)
 {
+       dce_clk_mgr_construct(ctx, clk_mgr);
+
        memcpy(clk_mgr->max_clks_by_state,
                dce112_max_clks_by_state,
                sizeof(dce112_max_clks_by_state));
 
-       dce_clk_mgr_construct(ctx, clk_mgr);
-
        clk_mgr->regs = &disp_clk_regs;
        clk_mgr->clk_mgr_shift = &disp_clk_shift;
        clk_mgr->clk_mgr_mask = &disp_clk_mask;
index 906310c3e2eb759e0b3cbedc8db054211b725498..5399b8cf6b75baf28177a8737e1ddb078222673f 100644 (file)
@@ -127,12 +127,12 @@ static struct clk_mgr_funcs dce120_funcs = {
 
 void dce120_clk_mgr_construct(struct dc_context *ctx, struct clk_mgr_internal *clk_mgr)
 {
+       dce_clk_mgr_construct(ctx, clk_mgr);
+
        memcpy(clk_mgr->max_clks_by_state,
                dce120_max_clks_by_state,
                sizeof(dce120_max_clks_by_state));
 
-       dce_clk_mgr_construct(ctx, clk_mgr);
-
        clk_mgr->base.dprefclk_khz = 600000;
        clk_mgr->base.funcs = &dce120_funcs;
 }
index 08a774fc7b67f11a59fcac2e340f20dd4c4a6d3e..50bfb5921de07164156692ab8cc04d163bcacb74 100644 (file)
@@ -301,6 +301,8 @@ void dcn2_update_clocks_fpga(struct clk_mgr *clk_mgr,
 void dcn2_init_clocks(struct clk_mgr *clk_mgr)
 {
        memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
+       // Assumption is that boot state always supports pstate
+       clk_mgr->clks.p_state_change_support = true;
 }
 
 void dcn2_enable_pme_wa(struct clk_mgr *clk_mgr_base)
@@ -331,6 +333,7 @@ void dcn20_clk_mgr_construct(
                struct dccg *dccg)
 {
        clk_mgr->base.ctx = ctx;
+       clk_mgr->pp_smu = pp_smu;
        clk_mgr->base.funcs = &dcn2_funcs;
        clk_mgr->regs = &clk_mgr_regs;
        clk_mgr->clk_mgr_shift = &clk_mgr_shift;
index 4ef4dc63e221e65c88a040ae799732fe2eddcc0d..cbc480a333764130878e64b880ef2073a1b440ff 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/mm.h>
 
 #include "dm_services.h"
 
@@ -502,8 +503,10 @@ void dc_stream_set_static_screen_events(struct dc *dc,
 
 static void destruct(struct dc *dc)
 {
-       dc_release_state(dc->current_state);
-       dc->current_state = NULL;
+       if (dc->current_state) {
+               dc_release_state(dc->current_state);
+               dc->current_state = NULL;
+       }
 
        destroy_links(dc);
 
@@ -1169,8 +1172,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
 
 struct dc_state *dc_create_state(struct dc *dc)
 {
-       struct dc_state *context = kzalloc(sizeof(struct dc_state),
-                                          GFP_KERNEL);
+       struct dc_state *context = kvzalloc(sizeof(struct dc_state),
+                                           GFP_KERNEL);
 
        if (!context)
                return NULL;
@@ -1190,11 +1193,11 @@ struct dc_state *dc_create_state(struct dc *dc)
 struct dc_state *dc_copy_state(struct dc_state *src_ctx)
 {
        int i, j;
-       struct dc_state *new_ctx = kmemdup(src_ctx,
-                       sizeof(struct dc_state), GFP_KERNEL);
+       struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL);
 
        if (!new_ctx)
                return NULL;
+       memcpy(new_ctx, src_ctx, sizeof(struct dc_state));
 
        for (i = 0; i < MAX_PIPES; i++) {
                        struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i];
@@ -1228,7 +1231,7 @@ static void dc_state_free(struct kref *kref)
 {
        struct dc_state *context = container_of(kref, struct dc_state, refcount);
        dc_resource_state_destruct(context);
-       kfree(context);
+       kvfree(context);
 }
 
 void dc_release_state(struct dc_state *context)
index 8dbf759eba45339e37b0265c334bf9fe7c0d6525..355b4ba127966777b6aefe833278e3e16426b2ac 100644 (file)
@@ -532,6 +532,7 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
        uint32_t read_dpcd_retry_cnt = 10;
        enum dc_status status = DC_ERROR_UNEXPECTED;
        int i;
+       union max_down_spread max_down_spread = { {0} };
 
        // Read DPCD 00101h to find out the number of lanes currently set
        for (i = 0; i < read_dpcd_retry_cnt; i++) {
@@ -553,8 +554,6 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
                msleep(8);
        }
 
-       ASSERT(status == DC_OK);
-
        // Read DPCD 00100h to find if standard link rates are set
        core_link_read_dpcd(link, DP_LINK_BW_SET,
                        &link_bw_set, sizeof(link_bw_set));
@@ -576,6 +575,12 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
                link->cur_link_settings.link_rate = link_bw_set;
                link->cur_link_settings.use_link_rate_set = false;
        }
+       // Read DPCD 00003h to find the max down spread.
+       core_link_read_dpcd(link, DP_MAX_DOWNSPREAD,
+                       &max_down_spread.raw, sizeof(max_down_spread));
+       link->cur_link_settings.link_spread =
+               max_down_spread.bits.MAX_DOWN_SPREAD ?
+               LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
 }
 
 static bool detect_dp(
@@ -717,13 +722,6 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                return false;
        }
 
-       if (link->connector_signal == SIGNAL_TYPE_EDP) {
-               /* On detect, we want to make sure current link settings are
-                * up to date, especially if link was powered on by GOP.
-                */
-               read_edp_current_link_settings_on_detect(link);
-       }
-
        prev_sink = link->local_sink;
        if (prev_sink != NULL) {
                dc_sink_retain(prev_sink);
@@ -765,6 +763,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
                }
 
                case SIGNAL_TYPE_EDP: {
+                       read_edp_current_link_settings_on_detect(link);
                        detect_edp_sink_caps(link);
                        sink_caps.transaction_type =
                                DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
@@ -2329,7 +2328,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
                        if (core_dc->current_state->res_ctx.pipe_ctx[i].stream) {
                                if (core_dc->current_state->res_ctx.
                                                pipe_ctx[i].stream->link
-                                               == link)
+                                               == link) {
                                        /* DMCU -1 for all controller id values,
                                         * therefore +1 here
                                         */
@@ -2337,6 +2336,13 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
                                                core_dc->current_state->
                                                res_ctx.pipe_ctx[i].stream_res.tg->inst +
                                                1;
+
+                                       /* Disable brightness ramping when the display is blanked
+                                        * as it can hang the DMCU
+                                        */
+                                       if (core_dc->current_state->res_ctx.pipe_ctx[i].plane_state == NULL)
+                                               frame_ramp = 0;
+                               }
                        }
                }
                abm->funcs->set_backlight_level_pwm(
@@ -2984,8 +2990,10 @@ void dc_link_set_preferred_link_settings(struct dc *dc,
 
        /* Retrain with preferred link settings only relevant for
         * DP signal type
+        * Check for non-DP signal or if passive dongle present
         */
-       if (!dc_is_dp_signal(link->connector_signal))
+       if (!dc_is_dp_signal(link->connector_signal) ||
+               link->dongle_max_pix_clk > 0)
                return;
 
        for (i = 0; i < MAX_PIPES; i++) {
index 056be4c34a98d95608ba857bf789d7cec4761645..2c7aaed907b9171eb25db19ae864f192e3315a67 100644 (file)
@@ -2230,18 +2230,25 @@ static void get_active_converter_info(
                link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
                ddc_service_set_dongle_type(link->ddc,
                                link->dpcd_caps.dongle_type);
+               link->dpcd_caps.is_branch_dev = false;
                return;
        }
 
        /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
-       link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
+       if (ds_port.fields.PORT_TYPE == DOWNSTREAM_DP) {
+               link->dpcd_caps.is_branch_dev = false;
+       }
+
+       else {
+               link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
+       }
 
        switch (ds_port.fields.PORT_TYPE) {
        case DOWNSTREAM_VGA:
                link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
                break;
-       case DOWNSTREAM_DVI_HDMI:
-               /* At this point we don't know is it DVI or HDMI,
+       case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
+               /* At this point we don't know is it DVI or HDMI or DP++,
                 * assume DVI.*/
                link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
                break;
@@ -2258,6 +2265,10 @@ static void get_active_converter_info(
                                det_caps, sizeof(det_caps));
 
                switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
+               /*Handle DP case as DONGLE_NONE*/
+               case DOWN_STREAM_DETAILED_DP:
+                       link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
+                       break;
                case DOWN_STREAM_DETAILED_VGA:
                        link->dpcd_caps.dongle_type =
                                DISPLAY_DONGLE_DP_VGA_CONVERTER;
@@ -2267,6 +2278,8 @@ static void get_active_converter_info(
                                DISPLAY_DONGLE_DP_DVI_CONVERTER;
                        break;
                case DOWN_STREAM_DETAILED_HDMI:
+               case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
+                       /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
                        link->dpcd_caps.dongle_type =
                                DISPLAY_DONGLE_DP_HDMI_CONVERTER;
 
@@ -2282,14 +2295,18 @@ static void get_active_converter_info(
 
                                link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
                                        hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
-                               link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
-                                       hdmi_caps.bits.YCrCr422_PASS_THROUGH;
-                               link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
-                                       hdmi_caps.bits.YCrCr420_PASS_THROUGH;
-                               link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
-                                       hdmi_caps.bits.YCrCr422_CONVERSION;
-                               link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
-                                       hdmi_caps.bits.YCrCr420_CONVERSION;
+                               /*YCBCR capability only for HDMI case*/
+                               if (port_caps->bits.DWN_STRM_PORTX_TYPE
+                                               == DOWN_STREAM_DETAILED_HDMI) {
+                                       link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
+                                                       hdmi_caps.bits.YCrCr422_PASS_THROUGH;
+                                       link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
+                                                       hdmi_caps.bits.YCrCr420_PASS_THROUGH;
+                                       link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
+                                                       hdmi_caps.bits.YCrCr422_CONVERSION;
+                                       link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
+                                                       hdmi_caps.bits.YCrCr420_CONVERSION;
+                               }
 
                                link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
                                        translate_dpcd_max_bpc(
index 51a78283a86da510837ce3ab3b6d3ae6bc1801bd..2ceaab4fb5debec9ae27d4c0ffd960346488a636 100644 (file)
@@ -258,7 +258,7 @@ bool resource_construct(
                 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
                 */
                update_num_audio(&straps, &num_audio, &pool->audio_support);
-               for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
+               for (i = 0; i < caps->num_audio; i++) {
                        struct audio *aud = create_funcs->create_audio(ctx, i);
 
                        if (aud == NULL) {
@@ -1669,6 +1669,12 @@ static struct audio *find_first_free_audio(
                        return pool->audios[i];
                }
        }
+
+    /* use engine id to find free audio */
+       if ((id < pool->audio_count) && (res_ctx->is_audio_acquired[id] == false)) {
+               return pool->audios[id];
+       }
+
        /*not found the matching one, first come first serve*/
        for (i = 0; i < pool->audio_count; i++) {
                if (res_ctx->is_audio_acquired[i] == false) {
@@ -1833,6 +1839,7 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
                pix_clk /= 2;
        if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
                switch (timing->display_color_depth) {
+               case COLOR_DEPTH_666:
                case COLOR_DEPTH_888:
                        normalized_pix_clk = pix_clk;
                        break;
@@ -1979,7 +1986,7 @@ enum dc_status resource_map_pool_resources(
        /* TODO: Add check if ASIC support and EDID audio */
        if (!stream->converter_disable_audio &&
            dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
-           stream->audio_info.mode_count) {
+           stream->audio_info.mode_count && stream->audio_info.flags.all) {
                pipe_ctx->stream_res.audio = find_first_free_audio(
                &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id);
 
index af7f8be230f749513826ec4d951bb69548b77e5b..352862370390e947dbbd06bd41a07d6de48ed0e7 100644 (file)
@@ -612,7 +612,8 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc,
 
        pipe_ctx->stream->dmdata_address = attr->address;
 
-       if (pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL) {
+       if (pipe_ctx->stream_res.stream_enc &&
+                       pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL) {
                if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
                        /* if using dynamic meta, don't set up generic infopackets */
                        pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
index f8903bcabe491f3faa0961e3f3bb5da0b5539942..58bd131d5b4849bc70f0bc29f4448d6d44d38daf 100644 (file)
@@ -239,6 +239,10 @@ static void dmcu_set_backlight_level(
        s2 |= (backlight_8_bit << ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
 
        REG_WRITE(BIOS_SCRATCH_2, s2);
+
+       /* waitDMCUReadyForCmd */
+       REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT,
+                       0, 1, 80000);
 }
 
 static void dce_abm_init(struct abm *abm)
index 858a58856ebd0c2cf98df0508c7f6d8376070503..fafb4b470140f8eac0dcb78fde10ca911730a2a6 100644 (file)
@@ -965,11 +965,17 @@ void hwss_edp_backlight_control(
 void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
 {
        /* notify audio driver for audio modes of monitor */
-       struct dc *core_dc = pipe_ctx->stream->ctx->dc;
+       struct dc *core_dc;
        struct pp_smu_funcs *pp_smu = NULL;
-       struct clk_mgr *clk_mgr = core_dc->clk_mgr;
+       struct clk_mgr *clk_mgr;
        unsigned int i, num_audio = 1;
 
+       if (!pipe_ctx->stream)
+               return;
+
+       core_dc = pipe_ctx->stream->ctx->dc;
+       clk_mgr = core_dc->clk_mgr;
+
        if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true)
                return;
 
@@ -999,9 +1005,15 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
 
 void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
 {
-       struct dc *dc = pipe_ctx->stream->ctx->dc;
+       struct dc *dc;
        struct pp_smu_funcs *pp_smu = NULL;
-       struct clk_mgr *clk_mgr = dc->clk_mgr;
+       struct clk_mgr *clk_mgr;
+
+       if (!pipe_ctx || !pipe_ctx->stream)
+               return;
+
+       dc = pipe_ctx->stream->ctx->dc;
+       clk_mgr = dc->clk_mgr;
 
        if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false)
                return;
@@ -1009,6 +1021,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
        pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
                        pipe_ctx->stream_res.stream_enc, true);
        if (pipe_ctx->stream_res.audio) {
+               pipe_ctx->stream_res.audio->enabled = false;
+
                if (dc->res_pool->pp_smu)
                        pp_smu = dc->res_pool->pp_smu;
 
@@ -1039,8 +1053,6 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
                /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
                 * stream->stream_engine_id);
                 */
-               if (pipe_ctx->stream_res.audio)
-                       pipe_ctx->stream_res.audio->enabled = false;
        }
 }
 
index e50a696fcb5deac0bd97acae0b257951565807c9..2118ea21d7e95082b267b387bf80a813c8ec44f3 100644 (file)
@@ -1195,16 +1195,7 @@ static void dcn10_init_hw(struct dc *dc)
         * everything down.
         */
        if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
-               for (i = 0; i < dc->res_pool->pipe_count; i++) {
-                       struct hubp *hubp = dc->res_pool->hubps[i];
-                       struct dpp *dpp = dc->res_pool->dpps[i];
-
-                       hubp->funcs->hubp_init(hubp);
-                       dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
-                       plane_atomic_power_down(dc, dpp, hubp);
-               }
-
-               apply_DEGVIDCN10_253_wa(dc);
+               dc->hwss.init_pipes(dc, dc->current_state);
        }
 
        for (i = 0; i < dc->res_pool->audio_count; i++) {
@@ -1375,10 +1366,6 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
        return result;
 }
 
-
-
-
-
 static bool
 dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
                               const struct dc_stream_state *stream)
@@ -2516,6 +2503,12 @@ static void dcn10_apply_ctx_for_surface(
                if (removed_pipe[i])
                        dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
 
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               if (removed_pipe[i]) {
+                       dc->hwss.optimize_bandwidth(dc, context);
+                       break;
+               }
+
        if (dc->hwseq->wa.DEGVIDCN10_254)
                hubbub1_wm_change_req_wa(dc->res_pool->hubbub);
 }
index 1a20461c29376d1d3fb443927f6bcff34a776621..a12530a3ab9ca16944ee260e913ca136f4649b5e 100644 (file)
@@ -508,7 +508,7 @@ static const struct resource_caps rv2_res_cap = {
                .num_audio = 3,
                .num_stream_encoder = 3,
                .num_pll = 3,
-               .num_ddc = 3,
+               .num_ddc = 4,
 };
 
 static const struct dc_plane_cap plane_cap = {
index 51a3dfe97f0eaa9541ab7060eacefa018b98043f..31aa6ee5cd5b9c32880570caf5463deb2968dabf 100644 (file)
@@ -102,14 +102,19 @@ void dccg2_init(struct dccg *dccg)
        switch (dccg_dcn->base.ctx->dc->res_pool->pipe_count) {
        case 6:
                REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[5], 1);
+               /* Fall through */
        case 5:
                REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[4], 1);
+               /* Fall through */
        case 4:
                REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[3], 1);
+               /* Fall through */
        case 3:
                REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[2], 1);
+               /* Fall through */
        case 2:
                REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[1], 1);
+               /* Fall through */
        case 1:
                REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[0], 1);
                break;
index ece6e136437ba0e19d7c6bde554e5ce2cab340fc..6e2dbd03f9bfcb5c631dc6a654558e176d779bdc 100644 (file)
@@ -337,6 +337,7 @@ static enum dcn_hubbub_page_table_block_size page_table_block_size_to_hw(unsigne
                break;
        default:
                ASSERT(false);
+               block_size = page_table_block_size;
                break;
        }
 
@@ -366,25 +367,24 @@ int hubbub2_init_dchub_sys_ctx(struct hubbub *hubbub,
        struct dcn_vmid_page_table_config phys_config;
 
        REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
-                       FB_BASE, pa_config->system_aperture.fb_base);
+                       FB_BASE, pa_config->system_aperture.fb_base >> 24);
        REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
-                       FB_TOP, pa_config->system_aperture.fb_top);
+                       FB_TOP, pa_config->system_aperture.fb_top >> 24);
        REG_SET(DCN_VM_FB_OFFSET, 0,
-                       FB_OFFSET, pa_config->system_aperture.fb_offset);
+                       FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);
        REG_SET(DCN_VM_AGP_BOT, 0,
-                       AGP_BOT, pa_config->system_aperture.agp_bot);
+                       AGP_BOT, pa_config->system_aperture.agp_bot >> 24);
        REG_SET(DCN_VM_AGP_TOP, 0,
-                       AGP_TOP, pa_config->system_aperture.agp_top);
+                       AGP_TOP, pa_config->system_aperture.agp_top >> 24);
        REG_SET(DCN_VM_AGP_BASE, 0,
-                       AGP_BASE, pa_config->system_aperture.agp_base);
+                       AGP_BASE, pa_config->system_aperture.agp_base >> 24);
 
        if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
-               phys_config.depth = 1;
-               phys_config.block_size = 4096;
                phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
                phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
                phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
-
+               phys_config.depth = 0;
+               phys_config.block_size = 0;
                // Init VMID 0 based on PA config
                dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);
        }
index 0b84a322b8a2c01af95de8aad35765338e9e5d28..d810c8940129b2852b7d19f7ee5a7b0457da844a 100644 (file)
@@ -1153,8 +1153,8 @@ void dcn20_enable_plane(
 
                apt.sys_default.quad_part = 0;
 
-               apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.start_addr;
-               apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.end_addr;
+               apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.start_addr;
+               apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.end_addr;
 
                // Program system aperture settings
                pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt);
@@ -1242,6 +1242,8 @@ void dcn20_pipe_control_lock_global(
                                CRTC_STATE_VACTIVE);
                pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
                                CRTC_STATE_VBLANK);
+               pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
+                               CRTC_STATE_VACTIVE);
                pipe->stream_res.tg->funcs->lock_doublebuffer_disable(
                                pipe->stream_res.tg);
        }
@@ -1263,6 +1265,17 @@ void dcn20_pipe_control_lock(
        if (pipe->plane_state != NULL)
                flip_immediate = pipe->plane_state->flip_immediate;
 
+       if (flip_immediate && lock) {
+               while (pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->plane_res.hubp)) {
+                       udelay(1);
+               }
+
+               if (pipe->bottom_pipe != NULL)
+                       while (pipe->bottom_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->bottom_pipe->plane_res.hubp))       {
+                               udelay(1);
+                       }
+       }
+
        /* In flip immediate and pipe splitting case, we need to use GSL
         * for synchronization. Only do setup on locking and on flip type change.
         */
@@ -1740,8 +1753,11 @@ static void dcn20_reset_back_end_for_pipe(
                else if (pipe_ctx->stream_res.audio) {
                        dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
                }
-
        }
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+       else if (pipe_ctx->stream_res.dsc)
+               dp_set_dsc_enable(pipe_ctx, false);
+#endif
 
        /* by upper caller loop, parent pipe: pipe0, will be reset last.
         * back end share by all pipes and will be disable only when disable
index 26a66ccf6e72670dd655f7671060db7cdc62d4c1..1ae973962d53b1fd4afe1efd94d3f72b3b52bcb4 100644 (file)
@@ -535,7 +535,7 @@ void dcn20_timing_generator_init(struct optc *optc1)
        optc1->min_h_blank = 32;
        optc1->min_v_blank = 3;
        optc1->min_v_blank_interlace = 5;
-       optc1->min_h_sync_width = 8;
+       optc1->min_h_sync_width = 4;//  Minimum HSYNC = 8 pixels asked By HW in the first place for no actual reason. Oculus Rift S will not light up with 8 as it's hsyncWidth is 6. Changing it to 4 to fix that issue.
        optc1->min_v_sync_width = 1;
        optc1->comb_opp_id = 0xf;
 }
index d200bc3cec714c22f6389e65bec4c56df6d4ad50..b949e202d6cb71c468daa17d3a8e80b7e018e3be 100644 (file)
@@ -2643,6 +2643,10 @@ static void update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_
 
        if (dc->bb_overrides.min_dcfclk_mhz > 0)
                min_dcfclk = dc->bb_overrides.min_dcfclk_mhz;
+       else
+               // Accounting for SOC/DCF relationship, we can go as high as
+               // 506Mhz in Vmin.  We need to code 507 since SMU will round down to 506.
+               min_dcfclk = 507;
 
        for (i = 0; i < num_states; i++) {
                int min_fclk_required_by_uclk;
index 27679ef6ebe87c77828fab859667e918ea5f946e..96c2632233151abdf9d8d37723c177cced18636e 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+#include <linux/delay.h>
+
 #include "dcn20_vmid.h"
 #include "reg_helper.h"
 
 #define FN(reg_name, field_name) \
        vmid->shifts->field_name, vmid->masks->field_name
 
+static void dcn20_wait_for_vmid_ready(struct dcn20_vmid *vmid)
+{
+       /* According the hardware spec, we need to poll for the lowest
+        * bit of PAGE_TABLE_BASE_ADDR_LO32 = 1 any time a GPUVM
+        * context is updated. We can't use REG_WAIT here since we
+        * don't have a seperate field to wait on.
+        *
+        * TODO: Confirm timeout / poll interval with hardware team
+        */
+
+       int max_times = 10000;
+       int delay_us  = 5;
+       int i;
+
+       for (i = 0; i < max_times; ++i) {
+               uint32_t entry_lo32;
+
+               REG_GET(PAGE_TABLE_BASE_ADDR_LO32,
+                       VM_CONTEXT0_PAGE_DIRECTORY_ENTRY_LO32,
+                       &entry_lo32);
+
+               if (entry_lo32 & 0x1)
+                       return;
+
+               udelay(delay_us);
+       }
+
+       /* VM setup timed out */
+       DC_LOG_WARNING("Timeout while waiting for GPUVM context update\n");
+       ASSERT(0);
+}
+
 void dcn20_vmid_setup(struct dcn20_vmid *vmid, const struct dcn_vmid_page_table_config *config)
 {
        REG_SET(PAGE_TABLE_START_ADDR_HI32, 0,
@@ -54,6 +88,9 @@ void dcn20_vmid_setup(struct dcn20_vmid *vmid, const struct dcn_vmid_page_table_
 
        REG_SET(PAGE_TABLE_BASE_ADDR_HI32, 0,
                        VM_CONTEXT0_PAGE_DIRECTORY_ENTRY_HI32, (config->page_table_base_addr >> 32) & 0xFFFFFFFF);
+       /* Note: per hardware spec PAGE_TABLE_BASE_ADDR_LO32 must be programmed last in sequence */
        REG_SET(PAGE_TABLE_BASE_ADDR_LO32, 0,
                        VM_CONTEXT0_PAGE_DIRECTORY_ENTRY_LO32, config->page_table_base_addr & 0xFFFFFFFF);
+
+       dcn20_wait_for_vmid_ready(vmid);
 }
index 67089765780bbf7d018236be8fa8f3e3cbd9a524..340ef4d41ebda03a400fdb450c40ee864dafd110 100644 (file)
@@ -377,6 +377,12 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
        vdsc_cfg->rc_bits = (hrd_delay * vdsc_cfg->bits_per_pixel) / 16;
        vdsc_cfg->initial_dec_delay = hrd_delay - vdsc_cfg->initial_xmit_delay;
 
+       /* As per DSC spec v1.2a recommendation: */
+       if (vdsc_cfg->native_420)
+               vdsc_cfg->second_line_offset_adj = 512;
+       else
+               vdsc_cfg->second_line_offset_adj = 0;
+
        return 0;
 }
 EXPORT_SYMBOL(drm_dsc_compute_rc_parameters);
index c89393c19232170bb60832128d8d993020050217..a148ffde8b12d9598366358da4f68a072e547a27 100644 (file)
@@ -212,7 +212,7 @@ struct resource_pool {
        struct clock_source *clock_sources[MAX_CLOCK_SOURCES];
        unsigned int clk_src_count;
 
-       struct audio *audios[MAX_PIPES];
+       struct audio *audios[MAX_AUDIOS];
        unsigned int audio_count;
        struct audio_support audio_support;
 
index 959f5b6546110441872889ef707ad21ebaa3b587..9502478c4a1bd1c86ce45cd400e8d22bd163af2a 100644 (file)
@@ -61,8 +61,8 @@ enum dcn_hubbub_page_table_depth {
 };
 
 enum dcn_hubbub_page_table_block_size {
-       DCN_PAGE_TABLE_BLOCK_SIZE_4KB,
-       DCN_PAGE_TABLE_BLOCK_SIZE_64KB
+       DCN_PAGE_TABLE_BLOCK_SIZE_4KB = 0,
+       DCN_PAGE_TABLE_BLOCK_SIZE_64KB = 4,
 };
 
 struct dcn_hubbub_phys_addr_config {
index 8759ec03aedec0e63047d34eab9c966c3f9fe6e7..f82365e2d03cc1aeba035eb6e25c1445756dfd64 100644 (file)
@@ -34,6 +34,7 @@
  * Data types shared between different Virtual HW blocks
  ******************************************************************************/
 
+#define MAX_AUDIOS 7
 #define MAX_PIPES 6
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
 #define MAX_DWB_PIPES  1
index 1c66166d0a949257ac262c0c236452cc431f99e9..2c90d1b46c8b233452ccaaafcc9f2cd1f2f2225e 100644 (file)
@@ -43,7 +43,7 @@ enum dpcd_revision {
 enum dpcd_downstream_port_type {
        DOWNSTREAM_DP = 0,
        DOWNSTREAM_VGA,
-       DOWNSTREAM_DVI_HDMI,
+       DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS,/* DVI, HDMI, DP++ */
        DOWNSTREAM_NONDDC /* has no EDID (TV,CV) */
 };
 
index 9f661bf96ed0344b20c47d30fb874e2c229ff289..5b1ebb7f995ae1d5023c8260d83e33c6ad313a43 100644 (file)
@@ -123,6 +123,7 @@ enum amd_pp_sensors {
        AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK,
        AMDGPU_PP_SENSOR_MIN_FAN_RPM,
        AMDGPU_PP_SENSOR_MAX_FAN_RPM,
+       AMDGPU_PP_SENSOR_VCN_POWER_STATE,
 };
 
 enum amd_pp_task {
index f1565c448de5169812d4aa5e289ae10b7b2b7508..8a3eadeebdcb611c4bd685376514802679d48601 100644 (file)
@@ -137,12 +137,37 @@ int smu_get_dpm_freq_range(struct smu_context *smu, enum smu_clk_type clk_type,
 {
        int ret = 0, clk_id = 0;
        uint32_t param = 0;
+       uint32_t clock_limit;
 
        if (!min && !max)
                return -EINVAL;
 
-       if (!smu_clk_dpm_is_enabled(smu, clk_type))
+       if (!smu_clk_dpm_is_enabled(smu, clk_type)) {
+               switch (clk_type) {
+               case SMU_MCLK:
+               case SMU_UCLK:
+                       clock_limit = smu->smu_table.boot_values.uclk;
+                       break;
+               case SMU_GFXCLK:
+               case SMU_SCLK:
+                       clock_limit = smu->smu_table.boot_values.gfxclk;
+                       break;
+               case SMU_SOCCLK:
+                       clock_limit = smu->smu_table.boot_values.socclk;
+                       break;
+               default:
+                       clock_limit = 0;
+                       break;
+               }
+
+               /* clock in Mhz unit */
+               if (min)
+                       *min = clock_limit / 100;
+               if (max)
+                       *max = clock_limit / 100;
+
                return 0;
+       }
 
        mutex_lock(&smu->mutex);
        clk_id = smu_clk_get_index(smu, clk_type);
@@ -281,7 +306,8 @@ int smu_get_power_num_states(struct smu_context *smu,
 
        /* not support power state */
        memset(state_info, 0, sizeof(struct pp_states_info));
-       state_info->nums = 0;
+       state_info->nums = 1;
+       state_info->states[0] = POWER_STATE_TYPE_DEFAULT;
 
        return 0;
 }
@@ -289,6 +315,8 @@ int smu_get_power_num_states(struct smu_context *smu,
 int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
                           void *data, uint32_t *size)
 {
+       struct smu_power_context *smu_power = &smu->smu_power;
+       struct smu_power_gate *power_gate = &smu_power->power_gate;
        int ret = 0;
 
        switch (sensor) {
@@ -312,6 +340,10 @@ int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
                *(uint32_t *)data = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT) ? 1 : 0;
                *size = 4;
                break;
+       case AMDGPU_PP_SENSOR_VCN_POWER_STATE:
+               *(uint32_t *)data = power_gate->vcn_gated ? 0 : 1;
+               *size = 4;
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -698,6 +730,12 @@ static int smu_sw_init(void *handle)
                return ret;
        }
 
+       ret = smu_register_irq_handler(smu);
+       if (ret) {
+               pr_err("Failed to register smc irq handler!\n");
+               return ret;
+       }
+
        return 0;
 }
 
@@ -707,6 +745,9 @@ static int smu_sw_fini(void *handle)
        struct smu_context *smu = &adev->smu;
        int ret;
 
+       kfree(smu->irq_source);
+       smu->irq_source = NULL;
+
        ret = smu_smc_table_sw_fini(smu);
        if (ret) {
                pr_err("Failed to sw fini smc table!\n");
@@ -1063,10 +1104,6 @@ static int smu_hw_init(void *handle)
        if (ret)
                goto failed;
 
-       ret = smu_register_irq_handler(smu);
-       if (ret)
-               goto failed;
-
        if (!smu->pm_enabled)
                adev->pm.dpm_enabled = false;
        else
@@ -1096,9 +1133,6 @@ static int smu_hw_fini(void *handle)
        kfree(table_context->overdrive_table);
        table_context->overdrive_table = NULL;
 
-       kfree(smu->irq_source);
-       smu->irq_source = NULL;
-
        ret = smu_fini_fb_allocations(smu);
        if (ret)
                return ret;
@@ -1349,13 +1383,49 @@ static int smu_enable_umd_pstate(void *handle,
        return 0;
 }
 
+static int smu_default_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
+{
+       int ret = 0;
+       uint32_t sclk_mask, mclk_mask, soc_mask;
+
+       switch (level) {
+       case AMD_DPM_FORCED_LEVEL_HIGH:
+               ret = smu_force_dpm_limit_value(smu, true);
+               break;
+       case AMD_DPM_FORCED_LEVEL_LOW:
+               ret = smu_force_dpm_limit_value(smu, false);
+               break;
+       case AMD_DPM_FORCED_LEVEL_AUTO:
+       case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
+               ret = smu_unforce_dpm_levels(smu);
+               break;
+       case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
+       case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
+       case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
+               ret = smu_get_profiling_clk_mask(smu, level,
+                                                &sclk_mask,
+                                                &mclk_mask,
+                                                &soc_mask);
+               if (ret)
+                       return ret;
+               smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask);
+               smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask);
+               smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
+               break;
+       case AMD_DPM_FORCED_LEVEL_MANUAL:
+       case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
+       default:
+               break;
+       }
+       return ret;
+}
+
 int smu_adjust_power_state_dynamic(struct smu_context *smu,
                                   enum amd_dpm_forced_level level,
                                   bool skip_display_settings)
 {
        int ret = 0;
        int index = 0;
-       uint32_t sclk_mask, mclk_mask, soc_mask;
        long workload;
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
 
@@ -1386,39 +1456,10 @@ int smu_adjust_power_state_dynamic(struct smu_context *smu,
        }
 
        if (smu_dpm_ctx->dpm_level != level) {
-               switch (level) {
-               case AMD_DPM_FORCED_LEVEL_HIGH:
-                       ret = smu_force_dpm_limit_value(smu, true);
-                       break;
-               case AMD_DPM_FORCED_LEVEL_LOW:
-                       ret = smu_force_dpm_limit_value(smu, false);
-                       break;
-
-               case AMD_DPM_FORCED_LEVEL_AUTO:
-               case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
-                       ret = smu_unforce_dpm_levels(smu);
-                       break;
-
-               case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
-               case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
-               case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
-                       ret = smu_get_profiling_clk_mask(smu, level,
-                                                        &sclk_mask,
-                                                        &mclk_mask,
-                                                        &soc_mask);
-                       if (ret)
-                               return ret;
-                       smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask);
-                       smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask);
-                       smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
-                       break;
-
-               case AMD_DPM_FORCED_LEVEL_MANUAL:
-               case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
-               default:
-                       break;
+               ret = smu_asic_set_performance_level(smu, level);
+               if (ret) {
+                       ret = smu_default_set_performance_level(smu, level);
                }
-
                if (!ret)
                        smu_dpm_ctx->dpm_level = level;
        }
index e32ae9d3373ca3e45fcea4a793be0d3951adf2a5..18e780f566fab78923a415b3f5ce77fe9d06bdfa 100644 (file)
@@ -1111,6 +1111,7 @@ static int smu10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
 static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
                          void *value, int *size)
 {
+       struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
        uint32_t sclk, mclk;
        int ret = 0;
 
@@ -1132,6 +1133,10 @@ static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
        case AMDGPU_PP_SENSOR_GPU_TEMP:
                *((uint32_t *)value) = smu10_thermal_get_temperature(hwmgr);
                break;
+       case AMDGPU_PP_SENSOR_VCN_POWER_STATE:
+               *(uint32_t *)value =  smu10_data->vcn_power_gated ? 0 : 1;
+               *size = 4;
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -1175,18 +1180,22 @@ static int smu10_powergate_sdma(struct pp_hwmgr *hwmgr, bool gate)
 
 static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, bool bgate)
 {
+       struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
+
        if (bgate) {
                amdgpu_device_ip_set_powergating_state(hwmgr->adev,
                                                AMD_IP_BLOCK_TYPE_VCN,
                                                AMD_PG_STATE_GATE);
                smum_send_msg_to_smc_with_parameter(hwmgr,
                                        PPSMC_MSG_PowerDownVcn, 0);
+               smu10_data->vcn_power_gated = true;
        } else {
                smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_PowerUpVcn, 0);
                amdgpu_device_ip_set_powergating_state(hwmgr->adev,
                                                AMD_IP_BLOCK_TYPE_VCN,
                                                AMD_PG_STATE_UNGATE);
+               smu10_data->vcn_power_gated = false;
        }
 }
 
index f27c6fbb192ed20133982db6df494893939f482a..90c4e87ac5ada9b09acc99d934df065e04a949d1 100644 (file)
@@ -2101,7 +2101,11 @@ static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr,
        if (ret)
                return ret;
 
-       *query = metrics_table.CurrSocketPower << 8;
+       /* For the 40.46 release, they changed the value name */
+       if (hwmgr->smu_version == 0x282e00)
+               *query = metrics_table.AverageSocketPower << 8;
+       else
+               *query = metrics_table.CurrSocketPower << 8;
 
        return ret;
 }
@@ -2349,12 +2353,16 @@ static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
                data->dpm_table.soc_table.dpm_state.soft_max_level =
                data->dpm_table.soc_table.dpm_levels[soft_level].value;
 
-       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to highest!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload dpm max level to highest!",
                        return ret);
@@ -2387,12 +2395,16 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
                data->dpm_table.soc_table.dpm_state.soft_max_level =
                data->dpm_table.soc_table.dpm_levels[soft_level].value;
 
-       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to highest!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload dpm max level to highest!",
                        return ret);
@@ -2403,14 +2415,54 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
 
 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
 {
+       struct vega20_hwmgr *data =
+                       (struct vega20_hwmgr *)(hwmgr->backend);
+       uint32_t soft_min_level, soft_max_level;
        int ret = 0;
 
-       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
+       /* gfxclk soft min/max settings */
+       soft_min_level =
+               vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
+       soft_max_level =
+               vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
+
+       data->dpm_table.gfx_table.dpm_state.soft_min_level =
+               data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.gfx_table.dpm_state.soft_max_level =
+               data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
+
+       /* uclk soft min/max settings */
+       soft_min_level =
+               vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
+       soft_max_level =
+               vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
+
+       data->dpm_table.mem_table.dpm_state.soft_min_level =
+               data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.mem_table.dpm_state.soft_max_level =
+               data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
+
+       /* socclk soft min/max settings */
+       soft_min_level =
+               vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
+       soft_max_level =
+               vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
+
+       data->dpm_table.soc_table.dpm_state.soft_min_level =
+               data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
+       data->dpm_table.soc_table.dpm_state.soft_max_level =
+               data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
+
+       ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload DPM Bootup Levels!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
+       ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK |
+                                                FEATURE_DPM_UCLK_MASK |
+                                                FEATURE_DPM_SOCCLK_MASK);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload DPM Max Levels!",
                        return ret);
index 1af992fb0bdedce0f4d89d0059a334a510d92a00..a78b2e295895070a8d12940f3e8847ba61fd76e0 100644 (file)
@@ -429,7 +429,6 @@ struct smu_table_context
        struct smu_table                *tables;
        uint32_t                        table_count;
        struct smu_table                memory_pool;
-       uint16_t                        software_shutdown_temp;
        uint8_t                         thermal_controller_type;
        uint16_t                        TDPODLimit;
 
@@ -452,6 +451,7 @@ struct smu_dpm_context {
 struct smu_power_gate {
        bool uvd_gated;
        bool vce_gated;
+       bool vcn_gated;
 };
 
 struct smu_power_context {
@@ -613,6 +613,7 @@ struct pptable_funcs {
        int (*tables_init)(struct smu_context *smu, struct smu_table *tables);
        int (*set_thermal_fan_table)(struct smu_context *smu);
        int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed);
+       int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed);
        int (*set_watermarks_table)(struct smu_context *smu, void *watermarks,
                                    struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges);
        int (*get_current_clk_freq_by_table)(struct smu_context *smu,
@@ -621,6 +622,7 @@ struct pptable_funcs {
        int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range);
        int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states);
        int (*set_default_od_settings)(struct smu_context *smu, bool initialize);
+       int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level);
 };
 
 struct smu_funcs
@@ -685,7 +687,6 @@ struct smu_funcs
        int (*set_watermarks_for_clock_ranges)(struct smu_context *smu,
                                               struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges);
        int (*conv_power_profile_to_pplib_workload)(int power_profile);
-       int (*get_current_rpm)(struct smu_context *smu, uint32_t *speed);
        uint32_t (*get_fan_control_mode)(struct smu_context *smu);
        int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
        int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed);
@@ -751,8 +752,6 @@ struct smu_funcs
        ((smu)->funcs->init_max_sustainable_clocks ? (smu)->funcs->init_max_sustainable_clocks((smu)) : 0)
 #define smu_set_default_od_settings(smu, initialize) \
        ((smu)->ppt_funcs->set_default_od_settings ? (smu)->ppt_funcs->set_default_od_settings((smu), (initialize)) : 0)
-#define smu_get_current_rpm(smu, speed) \
-       ((smu)->funcs->get_current_rpm ? (smu)->funcs->get_current_rpm((smu), (speed)) : 0)
 #define smu_set_fan_speed_rpm(smu, speed) \
        ((smu)->funcs->set_fan_speed_rpm ? (smu)->funcs->set_fan_speed_rpm((smu), (speed)) : 0)
 #define smu_send_smc_msg(smu, msg) \
@@ -841,6 +840,8 @@ struct smu_funcs
        ((smu)->ppt_funcs->get_fan_speed_percent ? (smu)->ppt_funcs->get_fan_speed_percent((smu), (speed)) : 0)
 #define smu_set_fan_speed_percent(smu, speed) \
        ((smu)->funcs->set_fan_speed_percent ? (smu)->funcs->set_fan_speed_percent((smu), (speed)) : 0)
+#define smu_get_fan_speed_rpm(smu, speed) \
+       ((smu)->ppt_funcs->get_fan_speed_rpm ? (smu)->ppt_funcs->get_fan_speed_rpm((smu), (speed)) : 0)
 
 #define smu_msg_get_index(smu, msg) \
        ((smu)->ppt_funcs? ((smu)->ppt_funcs->get_smu_msg_index? (smu)->ppt_funcs->get_smu_msg_index((smu), (msg)) : -EINVAL) : -EINVAL)
@@ -906,8 +907,6 @@ struct smu_funcs
        ((smu)->funcs->register_irq_handler ? (smu)->funcs->register_irq_handler(smu) : 0)
 #define smu_set_azalia_d3_pme(smu) \
        ((smu)->funcs->set_azalia_d3_pme ? (smu)->funcs->set_azalia_d3_pme((smu)) : 0)
-#define smu_get_uclk_dpm_states(smu, clocks_in_khz, num_states) \
-       ((smu)->ppt_funcs->get_uclk_dpm_states ? (smu)->ppt_funcs->get_uclk_dpm_states((smu), (clocks_in_khz), (num_states)) : 0)
 #define smu_get_max_sustainable_clocks_by_dc(smu, max_clocks) \
        ((smu)->funcs->get_max_sustainable_clocks_by_dc ? (smu)->funcs->get_max_sustainable_clocks_by_dc((smu), (max_clocks)) : 0)
 #define smu_get_uclk_dpm_states(smu, clocks_in_khz, num_states) \
@@ -918,6 +917,9 @@ struct smu_funcs
        ((smu)->funcs->baco_get_state? (smu)->funcs->baco_get_state((smu), (state)) : 0)
 #define smu_baco_reset(smu) \
        ((smu)->funcs->baco_reset? (smu)->funcs->baco_reset((smu)) : 0)
+#define smu_asic_set_performance_level(smu, level) \
+       ((smu)->ppt_funcs->set_performance_level? (smu)->ppt_funcs->set_performance_level((smu), (level)) : -EINVAL);
+
 
 extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table,
                                   uint16_t *size, uint8_t *frev, uint8_t *crev,
index 2dae0ae0829ef0de9df11e83f2e692eb54ad0868..b81c7e715dc943b00b3c0d456c17d42f5c01240e 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "pp_debug.h"
 #include <linux/firmware.h>
+#include <linux/pci.h>
 #include "amdgpu.h"
 #include "amdgpu_smu.h"
 #include "atomfirmware.h"
@@ -501,6 +502,8 @@ static int navi10_store_powerplay_table(struct smu_context *smu)
 
 static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
 {
+       struct smu_table_context *smu_table = &smu->smu_table;
+
        SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
                       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
        SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
@@ -515,9 +518,35 @@ static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
                       sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
                       AMDGPU_GEM_DOMAIN_VRAM);
 
+       smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
+       if (!smu_table->metrics_table)
+               return -ENOMEM;
+       smu_table->metrics_time = 0;
+
        return 0;
 }
 
+static int navi10_get_metrics_table(struct smu_context *smu,
+                                   SmuMetrics_t *metrics_table)
+{
+       struct smu_table_context *smu_table= &smu->smu_table;
+       int ret = 0;
+
+       if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
+               ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
+                               (void *)smu_table->metrics_table, false);
+               if (ret) {
+                       pr_info("Failed to export SMU metrics table!\n");
+                       return ret;
+               }
+               smu_table->metrics_time = jiffies;
+       }
+
+       memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+
+       return ret;
+}
+
 static int navi10_allocate_dpm_context(struct smu_context *smu)
 {
        struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
@@ -576,44 +605,38 @@ static int navi10_set_default_dpm_table(struct smu_context *smu)
 
 static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
 {
-       int ret = 0;
        struct smu_power_context *smu_power = &smu->smu_power;
        struct smu_power_gate *power_gate = &smu_power->power_gate;
+       int ret = 0;
 
-       if (enable && power_gate->uvd_gated) {
-               if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
+       if (enable) {
+               /* vcn dpm on is a prerequisite for vcn power gate messages */
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
                        ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
                        if (ret)
                                return ret;
                }
-               power_gate->uvd_gated = false;
+               power_gate->vcn_gated = false;
        } else {
-               if (!enable && !power_gate->uvd_gated) {
-                       if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) {
-                               ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
-                               if (ret)
-                                       return ret;
-                       }
-                       power_gate->uvd_gated = true;
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+                       ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
+                       if (ret)
+                               return ret;
                }
+               power_gate->vcn_gated = true;
        }
 
-       return 0;
+       return ret;
 }
 
 static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
                                       enum smu_clk_type clk_type,
                                       uint32_t *value)
 {
-       static SmuMetrics_t metrics;
        int ret = 0, clk_id = 0;
+       SmuMetrics_t metrics;
 
-       if (!value)
-               return -EINVAL;
-
-       memset(&metrics, 0, sizeof(metrics));
-
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics, false);
+       ret = navi10_get_metrics_table(smu, &metrics);
        if (ret)
                return ret;
 
@@ -626,11 +649,26 @@ static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
        return ret;
 }
 
+static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type)
+{
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
+       DpmDescriptor_t *dpm_desc = NULL;
+       uint32_t clk_index = 0;
+
+       clk_index = smu_clk_get_index(smu, clk_type);
+       dpm_desc = &pptable->DpmDescriptor[clk_index];
+
+       /* 0 - Fine grained DPM, 1 - Discrete DPM */
+       return dpm_desc->SnapToDiscrete == 0 ? true : false;
+}
+
 static int navi10_print_clk_levels(struct smu_context *smu,
                        enum smu_clk_type clk_type, char *buf)
 {
        int i, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
+       uint32_t freq_values[3] = {0};
+       uint32_t mark_index = 0;
 
        switch (clk_type) {
        case SMU_GFXCLK:
@@ -643,22 +681,42 @@ static int navi10_print_clk_levels(struct smu_context *smu,
                ret = smu_get_current_clk_freq(smu, clk_type, &cur_value);
                if (ret)
                        return size;
+
                /* 10KHz -> MHz */
                cur_value = cur_value / 100;
 
-               size += sprintf(buf, "current clk: %uMhz\n", cur_value);
-
                ret = smu_get_dpm_level_count(smu, clk_type, &count);
                if (ret)
                        return size;
 
-               for (i = 0; i < count; i++) {
-                       ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value);
+               if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {
+                       for (i = 0; i < count; i++) {
+                               ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value);
+                               if (ret)
+                                       return size;
+
+                               size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
+                                               cur_value == value ? "*" : "");
+                       }
+               } else {
+                       ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
                        if (ret)
                                return size;
+                       ret = smu_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
+                       if (ret)
+                               return size;
+
+                       freq_values[1] = cur_value;
+                       mark_index = cur_value == freq_values[0] ? 0 :
+                                    cur_value == freq_values[2] ? 2 : 1;
+                       if (mark_index != 1)
+                               freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
+
+                       for (i = 0; i < 3; i++) {
+                               size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
+                                               i == mark_index ? "*" : "");
+                       }
 
-                       size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
-                                       cur_value == value ? "*" : "");
                }
                break;
        default:
@@ -866,8 +924,9 @@ static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
        if (!value)
                return -EINVAL;
 
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics,
-                              false);
+       ret = navi10_get_metrics_table(smu, &metrics);
+       if (ret)
+               return ret;
        if (ret)
                return ret;
 
@@ -886,10 +945,7 @@ static int navi10_get_current_activity_percent(struct smu_context *smu,
        if (!value)
                return -EINVAL;
 
-       msleep(1);
-
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
-                              (void *)&metrics, false);
+       ret = navi10_get_metrics_table(smu, &metrics);
        if (ret)
                return ret;
 
@@ -919,22 +975,22 @@ static bool navi10_is_dpm_running(struct smu_context *smu)
        return !!(feature_enabled & SMC_DPM_FEATURE);
 }
 
-static int navi10_get_fan_speed(struct smu_context *smu, uint16_t *value)
+static int navi10_get_fan_speed_rpm(struct smu_context *smu,
+                                   uint32_t *speed)
 {
        SmuMetrics_t metrics;
        int ret = 0;
 
-       if (!value)
+       if (!speed)
                return -EINVAL;
 
-       memset(&metrics, 0, sizeof(metrics));
-
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
-                              (void *)&metrics, false);
+       ret = navi10_get_metrics_table(smu, &metrics);
+       if (ret)
+               return ret;
        if (ret)
                return ret;
 
-       *value = metrics.CurrFanSpeed;
+       *speed = metrics.CurrFanSpeed;
 
        return ret;
 }
@@ -944,10 +1000,10 @@ static int navi10_get_fan_speed_percent(struct smu_context *smu,
 {
        int ret = 0;
        uint32_t percent = 0;
-       uint16_t current_rpm;
+       uint32_t current_rpm;
        PPTable_t *pptable = smu->smu_table.driver_pptable;
 
-       ret = navi10_get_fan_speed(smu, &current_rpm);
+       ret = navi10_get_fan_speed_rpm(smu, &current_rpm);
        if (ret)
                return ret;
 
@@ -1278,7 +1334,7 @@ static int navi10_thermal_get_temperature(struct smu_context *smu,
        if (!value)
                return -EINVAL;
 
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics, false);
+       ret = navi10_get_metrics_table(smu, &metrics);
        if (ret)
                return ret;
 
@@ -1530,6 +1586,76 @@ static int navi10_set_ppfeature_status(struct smu_context *smu,
        return 0;
 }
 
+static int navi10_set_peak_clock_by_device(struct smu_context *smu)
+{
+       struct amdgpu_device *adev = smu->adev;
+       int ret = 0;
+       uint32_t sclk_freq = 0, uclk_freq = 0;
+       uint32_t uclk_level = 0;
+
+       switch (adev->pdev->revision) {
+       case 0xf0: /* XTX */
+       case 0xc0:
+               sclk_freq = NAVI10_PEAK_SCLK_XTX;
+               break;
+       case 0xf1: /* XT */
+       case 0xc1:
+               sclk_freq = NAVI10_PEAK_SCLK_XT;
+               break;
+       default: /* XL */
+               sclk_freq = NAVI10_PEAK_SCLK_XL;
+               break;
+       }
+
+       ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_level);
+       if (ret)
+               return ret;
+       ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, uclk_level - 1, &uclk_freq);
+       if (ret)
+               return ret;
+
+       ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
+       if (ret)
+               return ret;
+       ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+
+static int navi10_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
+{
+       int ret = 0;
+
+       switch (level) {
+       case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
+               ret = navi10_set_peak_clock_by_device(smu);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int navi10_get_thermal_temperature_range(struct smu_context *smu,
+                                               struct smu_temperature_range *range)
+{
+       struct smu_table_context *table_context = &smu->smu_table;
+       struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table;
+
+       if (!range || !powerplay_table)
+               return -EINVAL;
+
+       /* The unit is temperature */
+       range->min = 0;
+       range->max = powerplay_table->software_shutdown_temp;
+
+       return 0;
+}
+
 static const struct pptable_funcs navi10_ppt_funcs = {
        .tables_init = navi10_tables_init,
        .alloc_dpm_context = navi10_allocate_dpm_context,
@@ -1557,6 +1683,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .unforce_dpm_levels = navi10_unforce_dpm_levels,
        .is_dpm_running = navi10_is_dpm_running,
        .get_fan_speed_percent = navi10_get_fan_speed_percent,
+       .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
        .get_power_profile_mode = navi10_get_power_profile_mode,
        .set_power_profile_mode = navi10_set_power_profile_mode,
        .get_profiling_clk_mask = navi10_get_profiling_clk_mask,
@@ -1565,6 +1692,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
        .get_ppfeature_status = navi10_get_ppfeature_status,
        .set_ppfeature_status = navi10_set_ppfeature_status,
+       .set_performance_level = navi10_set_performance_level,
+       .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
 };
 
 void navi10_set_ppt_funcs(struct smu_context *smu)
index 957288e22f470c6c01b54e74eff24706db17674f..620ff17c2fef8ff54e70bbd13bcb2a9a8c52f368 100644 (file)
 #ifndef __NAVI10_PPT_H__
 #define __NAVI10_PPT_H__
 
+#define NAVI10_PEAK_SCLK_XTX           (1830)
+#define NAVI10_PEAK_SCLK_XT            (1755)
+#define NAVI10_PEAK_SCLK_XL            (1625)
+
 extern void navi10_set_ppt_funcs(struct smu_context *smu);
 
 #endif
index 95c7c4dae5236cdc61323502c414a346fdca2473..53097961bf2b7239b4076e924e7e5ba6f263cdc6 100644 (file)
@@ -326,7 +326,8 @@ static int smu_v11_0_setup_pptable(struct smu_context *smu)
        struct amdgpu_device *adev = smu->adev;
        const struct smc_firmware_header_v1_0 *hdr;
        int ret, index;
-       uint32_t size;
+       uint32_t size = 0;
+       uint16_t atom_table_size;
        uint8_t frev, crev;
        void *table;
        uint16_t version_major, version_minor;
@@ -354,10 +355,11 @@ static int smu_v11_0_setup_pptable(struct smu_context *smu)
                index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
                                                    powerplayinfo);
 
-               ret = smu_get_atom_data_table(smu, index, (uint16_t *)&size, &frev, &crev,
+               ret = smu_get_atom_data_table(smu, index, &atom_table_size, &frev, &crev,
                                              (uint8_t **)&table);
                if (ret)
                        return ret;
+               size = atom_table_size;
        }
 
        if (!smu->smu_table.power_play_table)
@@ -1124,10 +1126,8 @@ static int smu_v11_0_set_thermal_range(struct smu_context *smu,
                                       struct smu_temperature_range *range)
 {
        struct amdgpu_device *adev = smu->adev;
-       int low = SMU_THERMAL_MINIMUM_ALERT_TEMP *
-               SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
-       int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP *
-               SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       int low = SMU_THERMAL_MINIMUM_ALERT_TEMP;
+       int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP;
        uint32_t val;
 
        if (!range)
@@ -1138,6 +1138,9 @@ static int smu_v11_0_set_thermal_range(struct smu_context *smu,
        if (high > range->max)
                high = range->max;
 
+       low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, range->min);
+       high = min(SMU_THERMAL_MAXIMUM_ALERT_TEMP, range->max);
+
        if (low > high)
                return -EINVAL;
 
@@ -1146,8 +1149,8 @@ static int smu_v11_0_set_thermal_range(struct smu_context *smu,
        val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
        val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0);
        val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0);
-       val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES));
-       val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES));
+       val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff));
+       val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff));
        val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
 
        WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
@@ -1186,7 +1189,10 @@ static int smu_v11_0_start_thermal_control(struct smu_context *smu)
 
        if (!smu->pm_enabled)
                return ret;
+
        ret = smu_get_thermal_temperature_range(smu, &range);
+       if (ret)
+               return ret;
 
        if (smu->smu_table.thermal_controller_type) {
                ret = smu_v11_0_set_thermal_range(smu, &range);
@@ -1202,15 +1208,17 @@ static int smu_v11_0_start_thermal_control(struct smu_context *smu)
                        return ret;
        }
 
-       adev->pm.dpm.thermal.min_temp = range.min;
-       adev->pm.dpm.thermal.max_temp = range.max;
-       adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max;
-       adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min;
-       adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max;
-       adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max;
-       adev->pm.dpm.thermal.min_mem_temp = range.mem_min;
-       adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max;
-       adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max;
+       adev->pm.dpm.thermal.min_temp = range.min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.max_temp = range.max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.min_mem_temp = range.mem_min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.min_temp = range.min * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       adev->pm.dpm.thermal.max_temp = range.max * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 
        return ret;
 }
@@ -1371,23 +1379,6 @@ static int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
        return ret;
 }
 
-static int smu_v11_0_get_current_rpm(struct smu_context *smu,
-                                    uint32_t *current_rpm)
-{
-       int ret;
-
-       ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm);
-
-       if (ret) {
-               pr_err("Attempt to get current RPM from SMC Failed!\n");
-               return ret;
-       }
-
-       smu_read_smc_arg(smu, current_rpm);
-
-       return 0;
-}
-
 static uint32_t
 smu_v11_0_get_fan_control_mode(struct smu_context *smu)
 {
@@ -1402,7 +1393,7 @@ smu_v11_0_smc_fan_control(struct smu_context *smu, bool start)
 {
        int ret = 0;
 
-       if (smu_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT))
+       if (!smu_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT))
                return 0;
 
        ret = smu_feature_set_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT, start);
@@ -1773,7 +1764,6 @@ static const struct smu_funcs smu_v11_0_funcs = {
        .set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk,
        .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
        .set_watermarks_for_clock_ranges = smu_v11_0_set_watermarks_for_clock_ranges,
-       .get_current_rpm = smu_v11_0_get_current_rpm,
        .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
        .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
        .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
index bb9bb09cfc7a2fc779e261aae0d8366d19c4557a..6a14497257e43b8bc906f42b5d0c68fccdc93e1b 100644 (file)
@@ -450,7 +450,6 @@ static int vega20_store_powerplay_table(struct smu_context *smu)
        memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable,
               sizeof(PPTable_t));
 
-       table_context->software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
        table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
        table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
 
@@ -3015,6 +3014,23 @@ static int vega20_set_thermal_fan_table(struct smu_context *smu)
        return ret;
 }
 
+static int vega20_get_fan_speed_rpm(struct smu_context *smu,
+                                   uint32_t *speed)
+{
+       int ret;
+
+       ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm);
+
+       if (ret) {
+               pr_err("Attempt to get current RPM from SMC Failed!\n");
+               return ret;
+       }
+
+       smu_read_smc_arg(smu, speed);
+
+       return 0;
+}
+
 static int vega20_get_fan_speed_percent(struct smu_context *smu,
                                        uint32_t *speed)
 {
@@ -3022,7 +3038,7 @@ static int vega20_get_fan_speed_percent(struct smu_context *smu,
        uint32_t current_rpm = 0, percent = 0;
        PPTable_t *pptable = smu->smu_table.driver_pptable;
 
-       ret = smu_get_current_rpm(smu, &current_rpm);
+       ret = vega20_get_fan_speed_rpm(smu, &current_rpm);
        if (ret)
                return ret;
 
@@ -3034,6 +3050,7 @@ static int vega20_get_fan_speed_percent(struct smu_context *smu,
 
 static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
 {
+       uint32_t smu_version;
        int ret = 0;
        SmuMetrics_t metrics;
 
@@ -3044,7 +3061,15 @@ static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value)
        if (ret)
                return ret;
 
-       *value = metrics.CurrSocketPower << 8;
+       ret = smu_get_smc_version(smu, NULL, &smu_version);
+       if (ret)
+               return ret;
+
+       /* For the 40.46 release, they changed the value name */
+       if (smu_version == 0x282e00)
+               *value = metrics.AverageSocketPower << 8;
+       else
+               *value = metrics.CurrSocketPower << 8;
 
        return 0;
 }
@@ -3217,35 +3242,24 @@ static int vega20_set_watermarks_table(struct smu_context *smu,
        return 0;
 }
 
-static const struct smu_temperature_range vega20_thermal_policy[] =
-{
-       {-273150,  99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
-       { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
-};
-
 static int vega20_get_thermal_temperature_range(struct smu_context *smu,
                                                struct smu_temperature_range *range)
 {
-
+       struct smu_table_context *table_context = &smu->smu_table;
+       ATOM_Vega20_POWERPLAYTABLE *powerplay_table = table_context->power_play_table;
        PPTable_t *pptable = smu->smu_table.driver_pptable;
 
-       if (!range)
+       if (!range || !powerplay_table)
                return -EINVAL;
 
-       memcpy(range, &vega20_thermal_policy[0], sizeof(struct smu_temperature_range));
-
-       range->max = pptable->TedgeLimit *
-               SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
-       range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
-               SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
-       range->hotspot_crit_max = pptable->ThotspotLimit *
-               SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
-       range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
-               SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
-       range->mem_crit_max = pptable->ThbmLimit *
-               SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
-       range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM)*
-               SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       /* The unit is temperature */
+       range->min = 0;
+       range->max = powerplay_table->usSoftwareShutdownTemp;
+       range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE);
+       range->hotspot_crit_max = pptable->ThotspotLimit;
+       range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT);
+       range->mem_crit_max = pptable->ThbmLimit;
+       range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM);
 
 
        return 0;
@@ -3293,6 +3307,7 @@ static const struct pptable_funcs vega20_ppt_funcs = {
        .is_dpm_running = vega20_is_dpm_running,
        .set_thermal_fan_table = vega20_set_thermal_fan_table,
        .get_fan_speed_percent = vega20_get_fan_speed_percent,
+       .get_fan_speed_rpm = vega20_get_fan_speed_rpm,
        .set_watermarks_table = vega20_set_watermarks_table,
        .get_thermal_temperature_range = vega20_get_thermal_temperature_range
 };
index 5a118984de33d558f082855e08f2c01df0abcb3d..9d4d5075cc647ef6686afba1cac57539bd64e7a6 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/iommu.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #ifdef CONFIG_DEBUG_FS
@@ -126,7 +127,7 @@ static int komeda_parse_pipe_dt(struct komeda_dev *mdev, struct device_node *np)
        pipe->of_output_port =
                of_graph_get_port_by_id(np, KOMEDA_OF_PORT_OUTPUT);
 
-       pipe->of_node = np;
+       pipe->of_node = of_node_get(np);
 
        return 0;
 }
@@ -143,6 +144,12 @@ static int komeda_parse_dt(struct device *dev, struct komeda_dev *mdev)
                return mdev->irq;
        }
 
+       /* Get the optional framebuffer memory resource */
+       ret = of_reserved_mem_device_init(dev);
+       if (ret && ret != -ENODEV)
+               return ret;
+       ret = 0;
+
        for_each_available_child_of_node(np, child) {
                if (of_node_cmp(child->name, "pipeline") == 0) {
                        ret = komeda_parse_pipe_dt(mdev, child);
@@ -289,6 +296,8 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
 
        mdev->n_pipelines = 0;
 
+       of_reserved_mem_device_release(dev);
+
        if (funcs && funcs->cleanup)
                funcs->cleanup(mdev);
 
index cd4d9f53ddef280340898e0c35ff6abdefdcf4a1..c9a1edb9a000a0b20a98a35ba4eaad1a07119358 100644 (file)
@@ -35,6 +35,25 @@ komeda_get_format_caps(struct komeda_format_caps_table *table,
        return NULL;
 }
 
+u32 komeda_get_afbc_format_bpp(const struct drm_format_info *info, u64 modifier)
+{
+       u32 bpp;
+
+       switch (info->format) {
+       case DRM_FORMAT_YUV420_8BIT:
+               bpp = 12;
+               break;
+       case DRM_FORMAT_YUV420_10BIT:
+               bpp = 15;
+               break;
+       default:
+               bpp = info->cpp[0] * 8;
+               break;
+       }
+
+       return bpp;
+}
+
 /* Two assumptions
  * 1. RGB always has YTR
  * 2. Tiled RGB always has SC
index 3631910d33b5e4a5e83db4140921cf432265c4ef..32273cf18f7c55e53f9d7ee37c9e42eb2238ea63 100644 (file)
@@ -97,6 +97,9 @@ const struct komeda_format_caps *
 komeda_get_format_caps(struct komeda_format_caps_table *table,
                       u32 fourcc, u64 modifier);
 
+u32 komeda_get_afbc_format_bpp(const struct drm_format_info *info,
+                              u64 modifier);
+
 u32 *komeda_get_layer_fourcc_list(struct komeda_format_caps_table *table,
                                  u32 layer_type, u32 *n_fmts);
 
index 3b0a70ed6aa0fb078748f82b69e44edc4d843860..1b01a625f40e36e96aef7312dee118226767526d 100644 (file)
@@ -43,7 +43,7 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
        struct drm_framebuffer *fb = &kfb->base;
        const struct drm_format_info *info = fb->format;
        struct drm_gem_object *obj;
-       u32 alignment_w = 0, alignment_h = 0, alignment_header, n_blocks;
+       u32 alignment_w = 0, alignment_h = 0, alignment_header, n_blocks, bpp;
        u64 min_size;
 
        obj = drm_gem_object_lookup(file, mode_cmd->handles[0]);
@@ -88,8 +88,9 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
        kfb->offset_payload = ALIGN(n_blocks * AFBC_HEADER_SIZE,
                                    alignment_header);
 
+       bpp = komeda_get_afbc_format_bpp(info, fb->modifier);
        kfb->afbc_size = kfb->offset_payload + n_blocks *
-                        ALIGN(info->cpp[0] * AFBC_SUPERBLK_PIXELS,
+                        ALIGN(bpp * AFBC_SUPERBLK_PIXELS / 8,
                               AFBC_SUPERBLK_ALIGNMENT);
        min_size = kfb->afbc_size + fb->offsets[0];
        if (min_size > obj->size) {
index 419a8b0e5de8f2fe96be3d9e022e73405eb406f2..69d9e26c60c812769164996f68aa299127371053 100644 (file)
@@ -14,6 +14,7 @@
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_irq.h>
+#include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "komeda_dev.h"
@@ -146,7 +147,6 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc,
        struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc_st);
        struct komeda_plane_state *kplane_st;
        struct drm_plane_state *plane_st;
-       struct drm_framebuffer *fb;
        struct drm_plane *plane;
        struct list_head zorder_list;
        int order = 0, err;
@@ -172,7 +172,6 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc,
 
        list_for_each_entry(kplane_st, &zorder_list, zlist_node) {
                plane_st = &kplane_st->base;
-               fb = plane_st->fb;
                plane = plane_st->plane;
 
                plane_st->normalized_zpos = order++;
@@ -205,7 +204,7 @@ static int komeda_kms_check(struct drm_device *dev,
                            struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_st, *new_crtc_st;
+       struct drm_crtc_state *new_crtc_st;
        int i, err;
 
        err = drm_atomic_helper_check_modeset(dev, state);
@@ -216,7 +215,7 @@ static int komeda_kms_check(struct drm_device *dev,
         * so need to add all affected_planes (even unchanged) to
         * drm_atomic_state.
         */
-       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_st, new_crtc_st, i) {
+       for_each_new_crtc_in_state(state, crtc, new_crtc_st, i) {
                err = drm_atomic_add_affected_planes(state, crtc);
                if (err)
                        return err;
@@ -307,24 +306,33 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
                               komeda_kms_irq_handler, IRQF_SHARED,
                               drm->driver->name, drm);
        if (err)
-               goto cleanup_mode_config;
+               goto free_component_binding;
 
        err = mdev->funcs->enable_irq(mdev);
        if (err)
-               goto cleanup_mode_config;
+               goto free_component_binding;
 
        drm->irq_enabled = true;
 
+       drm_kms_helper_poll_init(drm);
+
        err = drm_dev_register(drm, 0);
        if (err)
-               goto cleanup_mode_config;
+               goto free_interrupts;
 
        return kms;
 
-cleanup_mode_config:
+free_interrupts:
+       drm_kms_helper_poll_fini(drm);
        drm->irq_enabled = false;
+       mdev->funcs->disable_irq(mdev);
+free_component_binding:
+       component_unbind_all(mdev->dev, drm);
+cleanup_mode_config:
        drm_mode_config_cleanup(drm);
        komeda_kms_cleanup_private_objs(kms);
+       drm->dev_private = NULL;
+       drm_dev_put(drm);
 free_kms:
        kfree(kms);
        return ERR_PTR(err);
@@ -335,12 +343,14 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
        struct drm_device *drm = &kms->base;
        struct komeda_dev *mdev = drm->dev_private;
 
+       drm_dev_unregister(drm);
+       drm_kms_helper_poll_fini(drm);
+       drm_atomic_helper_shutdown(drm);
        drm->irq_enabled = false;
        mdev->funcs->disable_irq(mdev);
-       drm_dev_unregister(drm);
        component_unbind_all(mdev->dev, drm);
-       komeda_kms_cleanup_private_objs(kms);
        drm_mode_config_cleanup(drm);
+       komeda_kms_cleanup_private_objs(kms);
        drm->dev_private = NULL;
        drm_dev_put(drm);
 }
index a90bcbb3cb23d6fc71a76750d69da9c1324cb098..14b683164544d8c2ea7d8d272f6f5caadaa4427f 100644 (file)
@@ -480,6 +480,7 @@ void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
                                   struct seq_file *sf);
 
 /* component APIs */
+extern __printf(10, 11)
 struct komeda_component *
 komeda_component_add(struct komeda_pipeline *pipe,
                     size_t comp_sz, u32 id, u32 hw_id,
index 617e1f7b8472e874250bf5a951856df9fa6de36c..2851cac94d8699883dbaa9a4e9b8f202e33da0eb 100644 (file)
@@ -148,7 +148,7 @@ static int komeda_wb_connector_add(struct komeda_kms_dev *kms,
        if (!kcrtc->master->wb_layer)
                return 0;
 
-       kwb_conn = kzalloc(sizeof(*wb_conn), GFP_KERNEL);
+       kwb_conn = kzalloc(sizeof(*kwb_conn), GFP_KERNEL);
        if (!kwb_conn)
                return -ENOMEM;
 
index 4c7e31cb45ffaf14073ab3ccf286dee27823f9d6..a5d1494a3dc44b853d6b19472305341c18c504fd 100644 (file)
@@ -131,8 +131,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 
 
        /* Enable extended register access */
-       ast_enable_mmio(dev);
        ast_open_key(ast);
+       ast_enable_mmio(dev);
 
        /* Find out whether P2A works or whether to use device-tree */
        ast_detect_config_mode(dev, &scu_rev);
@@ -576,6 +576,9 @@ void ast_driver_unload(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
 
+       /* enable standard VGA decode */
+       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04);
+
        ast_release_firmware(dev);
        kfree(ast->dp501_fw_addr);
        ast_mode_fini(dev);
index ffccbef962a41d44d331e1b8da970a0246483b2b..a1cb020e07e502197428bc0fca447c650c381110 100644 (file)
@@ -604,7 +604,7 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc,
                return -EINVAL;
        ast_open_key(ast);
 
-       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
+       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
 
        ast_set_std_reg(crtc, adjusted_mode, &vbios_mode);
        ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode);
index f7d421359d564756ff86d78c64293e37eea74c7e..c1d1ac51d1c207c0cb0b2f08825aa19ca7761bde 100644 (file)
@@ -46,7 +46,7 @@ void ast_enable_mmio(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
 
-       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
+       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
 }
 
 
index bc19dbd531efc237b1407bcee204e28c52474d72..359030d5d818d0bef7b64a29267ca919d24cb1f9 100644 (file)
@@ -191,6 +191,7 @@ int bochs_kms_init(struct bochs_device *bochs)
        bochs->dev->mode_config.fb_base = bochs->fb_base;
        bochs->dev->mode_config.preferred_depth = 24;
        bochs->dev->mode_config.prefer_shadow = 0;
+       bochs->dev->mode_config.prefer_shadow_fbdev = 1;
        bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
 
        bochs->dev->mode_config.funcs = &bochs_mode_funcs;
index ee777469293a4edffcd32fc27d3676539e962365..e4e22bbae2a7c7c07e32a433210725b85f90f533 100644 (file)
@@ -48,6 +48,7 @@ config DRM_DUMB_VGA_DAC
 config DRM_LVDS_ENCODER
        tristate "Transparent parallel to LVDS encoder support"
        depends on OF
+       select DRM_KMS_HELPER
        select DRM_PANEL_BRIDGE
        help
          Support for transparent parallel to LVDS encoders that don't require
@@ -116,9 +117,10 @@ config DRM_THINE_THC63LVD1024
 
 config DRM_TOSHIBA_TC358764
        tristate "TC358764 DSI/LVDS bridge"
-       depends on DRM && DRM_PANEL
        depends on OF
        select DRM_MIPI_DSI
+       select DRM_KMS_HELPER
+       select DRM_PANEL
        help
          Toshiba TC358764 DSI/LVDS bridge driver.
 
index 410572f142577e91116159246c56b26c67a4d572..e1dafb0cc5e2fbe963720e47739d9203f138a5aa 100644 (file)
@@ -254,7 +254,6 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
        struct drm_device *dev = client->dev;
        struct drm_client_buffer *buffer;
        struct drm_gem_object *obj;
-       void *vaddr;
        int ret;
 
        buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
@@ -281,6 +280,36 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
 
        buffer->gem = obj;
 
+       return buffer;
+
+err_delete:
+       drm_client_buffer_delete(buffer);
+
+       return ERR_PTR(ret);
+}
+
+/**
+ * drm_client_buffer_vmap - Map DRM client buffer into address space
+ * @buffer: DRM client buffer
+ *
+ * This function maps a client buffer into kernel address space. If the
+ * buffer is already mapped, it returns the mapping's address.
+ *
+ * Client buffer mappings are not ref'counted. Each call to
+ * drm_client_buffer_vmap() should be followed by a call to
+ * drm_client_buffer_vunmap(); or the client buffer should be mapped
+ * throughout its lifetime.
+ *
+ * Returns:
+ *     The mapped memory's address
+ */
+void *drm_client_buffer_vmap(struct drm_client_buffer *buffer)
+{
+       void *vaddr;
+
+       if (buffer->vaddr)
+               return buffer->vaddr;
+
        /*
         * FIXME: The dependency on GEM here isn't required, we could
         * convert the driver handle to a dma-buf instead and use the
@@ -289,21 +318,30 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
         * fd_install step out of the driver backend hooks, to make that
         * final step optional for internal users.
         */
-       vaddr = drm_gem_vmap(obj);
-       if (IS_ERR(vaddr)) {
-               ret = PTR_ERR(vaddr);
-               goto err_delete;
-       }
+       vaddr = drm_gem_vmap(buffer->gem);
+       if (IS_ERR(vaddr))
+               return vaddr;
 
        buffer->vaddr = vaddr;
 
-       return buffer;
-
-err_delete:
-       drm_client_buffer_delete(buffer);
+       return vaddr;
+}
+EXPORT_SYMBOL(drm_client_buffer_vmap);
 
-       return ERR_PTR(ret);
+/**
+ * drm_client_buffer_vunmap - Unmap DRM client buffer
+ * @buffer: DRM client buffer
+ *
+ * This function removes a client buffer's memory mapping. Calling this
+ * function is only required by clients that manage their buffer mappings
+ * by themselves.
+ */
+void drm_client_buffer_vunmap(struct drm_client_buffer *buffer)
+{
+       drm_gem_vunmap(buffer->gem, buffer->vaddr);
+       buffer->vaddr = NULL;
 }
+EXPORT_SYMBOL(drm_client_buffer_vunmap);
 
 static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
 {
index 56d36779d21321f0e4c74d1606b6952bdee392a9..c8922b7cac091de342253ac5938acf690c82a4b5 100644 (file)
@@ -859,7 +859,7 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
         * simple XOR between the two handle the addition nicely.
         */
        cmdline = &connector->cmdline_mode;
-       if (cmdline->specified) {
+       if (cmdline->specified && cmdline->rotation_reflection) {
                unsigned int cmdline_rest, panel_rest;
                unsigned int cmdline_rot, panel_rot;
                unsigned int sum_rot, sum_rest;
index 1984e5c54d580504fb3417d50afca9e1dd6aa105..a7ba5b4902d664fb72917b9f999b683c3fcaec58 100644 (file)
@@ -403,6 +403,7 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)
        struct drm_clip_rect *clip = &helper->dirty_clip;
        struct drm_clip_rect clip_copy;
        unsigned long flags;
+       void *vaddr;
 
        spin_lock_irqsave(&helper->dirty_lock, flags);
        clip_copy = *clip;
@@ -412,10 +413,20 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)
 
        /* call dirty callback only when it has been really touched */
        if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2) {
+
                /* Generic fbdev uses a shadow buffer */
-               if (helper->buffer)
+               if (helper->buffer) {
+                       vaddr = drm_client_buffer_vmap(helper->buffer);
+                       if (IS_ERR(vaddr))
+                               return;
                        drm_fb_helper_dirty_blit_real(helper, &clip_copy);
-               helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
+               }
+               if (helper->fb->funcs->dirty)
+                       helper->fb->funcs->dirty(helper->fb, NULL, 0, 0,
+                                                &clip_copy, 1);
+
+               if (helper->buffer)
+                       drm_client_buffer_vunmap(helper->buffer);
        }
 }
 
@@ -604,6 +615,16 @@ void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
 }
 EXPORT_SYMBOL(drm_fb_helper_unlink_fbi);
 
+static bool drm_fbdev_use_shadow_fb(struct drm_fb_helper *fb_helper)
+{
+       struct drm_device *dev = fb_helper->dev;
+       struct drm_framebuffer *fb = fb_helper->fb;
+
+       return dev->mode_config.prefer_shadow_fbdev ||
+              dev->mode_config.prefer_shadow ||
+              fb->funcs->dirty;
+}
+
 static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y,
                                u32 width, u32 height)
 {
@@ -611,7 +632,7 @@ static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y,
        struct drm_clip_rect *clip = &helper->dirty_clip;
        unsigned long flags;
 
-       if (!helper->fb->funcs->dirty)
+       if (!drm_fbdev_use_shadow_fb(helper))
                return;
 
        spin_lock_irqsave(&helper->dirty_lock, flags);
@@ -2178,6 +2199,7 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
        struct drm_framebuffer *fb;
        struct fb_info *fbi;
        u32 format;
+       void *vaddr;
 
        DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
                      sizes->surface_width, sizes->surface_height,
@@ -2200,16 +2222,10 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
        fbi->fbops = &drm_fbdev_fb_ops;
        fbi->screen_size = fb->height * fb->pitches[0];
        fbi->fix.smem_len = fbi->screen_size;
-       fbi->screen_buffer = buffer->vaddr;
-       /* Shamelessly leak the physical address to user-space */
-#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
-       if (drm_leak_fbdev_smem && fbi->fix.smem_start == 0)
-               fbi->fix.smem_start =
-                       page_to_phys(virt_to_page(fbi->screen_buffer));
-#endif
+
        drm_fb_helper_fill_info(fbi, fb_helper, sizes);
 
-       if (fb->funcs->dirty) {
+       if (drm_fbdev_use_shadow_fb(fb_helper)) {
                struct fb_ops *fbops;
                void *shadow;
 
@@ -2231,6 +2247,19 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
                fbi->fbdefio = &drm_fbdev_defio;
 
                fb_deferred_io_init(fbi);
+       } else {
+               /* buffer is mapped for HW framebuffer */
+               vaddr = drm_client_buffer_vmap(fb_helper->buffer);
+               if (IS_ERR(vaddr))
+                       return PTR_ERR(vaddr);
+
+               fbi->screen_buffer = vaddr;
+               /* Shamelessly leak the physical address to user-space */
+#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
+               if (drm_leak_fbdev_smem && fbi->fix.smem_start == 0)
+                       fbi->fix.smem_start =
+                               page_to_phys(virt_to_page(fbi->screen_buffer));
+#endif
        }
 
        return 0;
index 0b72468e8131d6c709259380c48c543cc08a4121..57564318ceeacdbdc51e6680461e4c10f979b209 100644 (file)
@@ -835,7 +835,7 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
        struct drm_device *dev = fb->dev;
        struct drm_atomic_state *state;
        struct drm_plane *plane;
-       struct drm_connector *conn;
+       struct drm_connector *conn __maybe_unused;
        struct drm_connector_state *conn_state;
        int i, ret;
        unsigned plane_mask;
index 74a5739df506aaed0994f842e024f55fec4ea4aa..c814bcef18a4007d90d5dcb85fd8abb6c69a985b 100644 (file)
@@ -1454,6 +1454,7 @@ static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
 }
 
 static int drm_mode_parse_cmdline_extra(const char *str, int length,
+                                       bool freestanding,
                                        const struct drm_connector *connector,
                                        struct drm_cmdline_mode *mode)
 {
@@ -1462,9 +1463,15 @@ static int drm_mode_parse_cmdline_extra(const char *str, int length,
        for (i = 0; i < length; i++) {
                switch (str[i]) {
                case 'i':
+                       if (freestanding)
+                               return -EINVAL;
+
                        mode->interlace = true;
                        break;
                case 'm':
+                       if (freestanding)
+                               return -EINVAL;
+
                        mode->margins = true;
                        break;
                case 'D':
@@ -1542,6 +1549,7 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
                        if (extras) {
                                int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
                                                                       1,
+                                                                      false,
                                                                       connector,
                                                                       mode);
                                if (ret)
@@ -1669,6 +1677,22 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
        return 0;
 }
 
+static const char * const drm_named_modes_whitelist[] = {
+       "NTSC",
+       "PAL",
+};
+
+static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++)
+               if (!strncmp(mode, drm_named_modes_whitelist[i], size))
+                       return true;
+
+       return false;
+}
+
 /**
  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
  * @mode_option: optional per connector mode option
@@ -1686,7 +1710,7 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
  *
  * Additionals options can be provided following the mode, using a comma to
  * separate each option. Valid options can be found in
- * Documentation/fb/modedb.txt.
+ * Documentation/fb/modedb.rst.
  *
  * The intermediate drm_cmdline_mode structure is required to store additional
  * options from the command line modline like the force-enable/disable flag.
@@ -1725,16 +1749,30 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
         * bunch of things:
         *   - We need to make sure that the first character (which
         *     would be our resolution in X) is a digit.
-        *   - However, if the X resolution is missing, then we end up
-        *     with something like x<yres>, with our first character
-        *     being an alpha-numerical character, which would be
-        *     considered a named mode.
+        *   - If not, then it's either a named mode or a force on/off.
+        *     To distinguish between the two, we need to run the
+        *     extra parsing function, and if not, then we consider it
+        *     a named mode.
         *
         * If this isn't enough, we should add more heuristics here,
         * and matching unit-tests.
         */
-       if (!isdigit(name[0]) && name[0] != 'x')
+       if (!isdigit(name[0]) && name[0] != 'x') {
+               unsigned int namelen = strlen(name);
+
+               /*
+                * Only the force on/off options can be in that case,
+                * and they all take a single character.
+                */
+               if (namelen == 1) {
+                       ret = drm_mode_parse_cmdline_extra(name, namelen, true,
+                                                          connector, mode);
+                       if (!ret)
+                               return true;
+               }
+
                named_mode = true;
+       }
 
        /* Try to locate the bpp and refresh specifiers, if any */
        bpp_ptr = strchr(name, '-');
@@ -1770,7 +1808,13 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
        }
 
        if (named_mode) {
-               strncpy(mode->name, name, mode_end);
+               if (mode_end + 1 > DRM_DISPLAY_MODE_LEN)
+                       return false;
+
+               if (!drm_named_mode_is_in_whitelist(name, mode_end))
+                       return false;
+
+               strscpy(mode->name, name, mode_end + 1);
        } else {
                ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
                                                      parse_extras,
@@ -1809,7 +1853,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
            extra_ptr != options_ptr) {
                int len = strlen(name) - (extra_ptr - name);
 
-               ret = drm_mode_parse_cmdline_extra(extra_ptr, len,
+               ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false,
                                                   connector, mode);
                if (ret)
                        return false;
index 60ce4a8ad9e1518a7e7dd287c92d158cb897b8a4..6f7d3b3b3628d2229a62f44d59ae6e3e13e645a4 100644 (file)
@@ -2,6 +2,7 @@
 config DRM_EXYNOS
        tristate "DRM Support for Samsung SoC EXYNOS Series"
        depends on OF && DRM && (ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM || COMPILE_TEST)
+       depends on MMU
        select DRM_KMS_HELPER
        select VIDEOMODE_HELPERS
        select SND_SOC_HDMI_CODEC if SND_SOC
index a594ab7be2c055f0861b00c6052aa82cf8b09499..164d914cbe9a49a437dedb86e5c5214ac645f0a5 100644 (file)
@@ -44,7 +44,7 @@ static unsigned int fimc_mask = 0xc;
 module_param_named(fimc_devs, fimc_mask, uint, 0644);
 MODULE_PARM_DESC(fimc_devs, "Alias mask for assigning FIMC devices to Exynos DRM");
 
-#define get_fimc_context(dev)  platform_get_drvdata(to_platform_device(dev))
+#define get_fimc_context(dev)  dev_get_drvdata(dev)
 
 enum {
        FIMC_CLK_LCLK,
index 50904eee96f7a4732ca029660a8f00e4bc84d2ec..2a3382d43bc9020722617f421f9d3e7c6ae6bed1 100644 (file)
@@ -267,7 +267,7 @@ static inline void g2d_hw_reset(struct g2d_data *g2d)
 static int g2d_init_cmdlist(struct g2d_data *g2d)
 {
        struct device *dev = g2d->dev;
-       struct g2d_cmdlist_node *node = g2d->cmdlist_node;
+       struct g2d_cmdlist_node *node;
        int nr;
        int ret;
        struct g2d_buf_info *buf_info;
index 1e4b21c49a06fd86b520012a0079f04be5d2e8c1..1c524db9570f8734ce508c868b4975080c4d4fd9 100644 (file)
@@ -58,7 +58,7 @@
 #define GSC_COEF_DEPTH 3
 #define GSC_AUTOSUSPEND_DELAY          2000
 
-#define get_gsc_context(dev)   platform_get_drvdata(to_platform_device(dev))
+#define get_gsc_context(dev)   dev_get_drvdata(dev)
 #define gsc_read(offset)               readl(ctx->regs + (offset))
 #define gsc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
 
index 9af096479e1cde34ebfbb0cdc0de6710941bf908..b24ba948b725eb7db36be6de088366fc769ed6ec 100644 (file)
@@ -94,12 +94,12 @@ static inline int scaler_reset(struct scaler_context *scaler)
        scaler_write(SCALER_CFG_SOFT_RESET, SCALER_CFG);
        do {
                cpu_relax();
-       } while (retry > 1 &&
+       } while (--retry > 1 &&
                 scaler_read(SCALER_CFG) & SCALER_CFG_SOFT_RESET);
        do {
                cpu_relax();
                scaler_write(1, SCALER_INT_EN);
-       } while (retry > 0 && scaler_read(SCALER_INT_EN) != 1);
+       } while (--retry > 0 && scaler_read(SCALER_INT_EN) != 1);
 
        return retry ? 0 : -EIO;
 }
index 91355c2ea8a509fb29e57859d4ed29d182dfd447..8cace65f50ce2f2966e1db86b0aa556b302ba5c4 100644 (file)
@@ -16,7 +16,6 @@ subdir-ccflags-y := -Wall -Wextra
 subdir-ccflags-y += $(call cc-disable-warning, unused-parameter)
 subdir-ccflags-y += $(call cc-disable-warning, type-limits)
 subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers)
-subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough)
 subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable)
 # clang warnings
 subdir-ccflags-y += $(call cc-disable-warning, sign-compare)
index c4710889cb321aa7d4d7e58365519dbc06d09f56..3ef4e9f573cfe1a825fc7296c27a822f071517f5 100644 (file)
@@ -765,7 +765,7 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
        }
 
        if (bdb->version >= 226) {
-               u32 wakeup_time = psr_table->psr2_tp2_tp3_wakeup_time;
+               u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
 
                wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3;
                switch (wakeup_time) {
index 753ac3165061c606ca62d7372cc4825f16fd7dcd..7b908e10d32e65f6808dcffea5d19d8d50c295db 100644 (file)
@@ -178,6 +178,8 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv)
                clpchgroup = (sa->deburst * deinterleave / num_channels) << i;
                bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
 
+               bi->num_qgv_points = qi.num_points;
+
                for (j = 0; j < qi.num_points; j++) {
                        const struct intel_qgv_point *sp = &qi.points[j];
                        int ct, bw;
@@ -195,7 +197,7 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv)
                        bi->deratedbw[j] = min(maxdebw,
                                               bw * 9 / 10); /* 90% */
 
-                       DRM_DEBUG_KMS("BW%d / QGV %d: num_planes=%d deratedbw=%d\n",
+                       DRM_DEBUG_KMS("BW%d / QGV %d: num_planes=%d deratedbw=%u\n",
                                      i, j, bi->num_planes, bi->deratedbw[j]);
                }
 
@@ -211,14 +213,17 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
 {
        int i;
 
-       /* Did we initialize the bw limits successfully? */
-       if (dev_priv->max_bw[0].num_planes == 0)
-               return UINT_MAX;
-
        for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) {
                const struct intel_bw_info *bi =
                        &dev_priv->max_bw[i];
 
+               /*
+                * Pcode will not expose all QGV points when
+                * SAGV is forced to off/min/med/max.
+                */
+               if (qgv_point >= bi->num_qgv_points)
+                       return UINT_MAX;
+
                if (num_planes >= bi->num_planes)
                        return bi->deratedbw[qgv_point];
        }
index 8993ab283562b2dc8fa65ec54ad5a0c05353c010..0d19bbd081225d02daba99ccd8b4a78b7c1a3e36 100644 (file)
@@ -2239,6 +2239,17 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
        if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9)
                min_cdclk = max(2 * 96000, min_cdclk);
 
+       /*
+        * "For DP audio configuration, cdclk frequency shall be set to
+        *  meet the following requirements:
+        *  DP Link Frequency(MHz) | Cdclk frequency(MHz)
+        *  270                    | 320 or higher
+        *  162                    | 200 or higher"
+        */
+       if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+           intel_crtc_has_dp_encoder(crtc_state) && crtc_state->has_audio)
+               min_cdclk = max(crtc_state->port_clock, min_cdclk);
+
        /*
         * On Valleyview some DSI panels lose (v|h)sync when the clock is lower
         * than 320000KHz.
index 7925a176f90073763bf189cb0bee2482b8cf5c94..1cb1fa74cfbc97d15012d6beb2c0370ebd7f570c 100644 (file)
@@ -1465,8 +1465,8 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
        else if (intel_crtc_has_dp_encoder(pipe_config))
                dotclock = intel_dotclock_calculate(pipe_config->port_clock,
                                                    &pipe_config->dp_m_n);
-       else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp == 36)
-               dotclock = pipe_config->port_clock * 2 / 3;
+       else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp > 24)
+               dotclock = pipe_config->port_clock * 24 / pipe_config->pipe_bpp;
        else
                dotclock = pipe_config->port_clock;
 
index 8592a7d422de9c147d5407cdbb225aa81fb314b9..592b92782fabfa37fd7fb026fa4525e868db3b8a 100644 (file)
@@ -1839,7 +1839,7 @@ static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
                /* FIXME: assert CPU port conditions for SNB+ */
        }
 
-       trace_intel_pipe_enable(dev_priv, pipe);
+       trace_intel_pipe_enable(crtc);
 
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
@@ -1880,7 +1880,7 @@ static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state)
         */
        assert_planes_disabled(crtc);
 
-       trace_intel_pipe_disable(dev_priv, pipe);
+       trace_intel_pipe_disable(crtc);
 
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
@@ -12042,7 +12042,7 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state)
                case INTEL_OUTPUT_DDI:
                        if (WARN_ON(!HAS_DDI(to_i915(dev))))
                                break;
-                       /* else: fall through */
+                       /* else, fall through */
                case INTEL_OUTPUT_DP:
                case INTEL_OUTPUT_HDMI:
                case INTEL_OUTPUT_EDP:
index c93ad512014ce2cca2757e4c6e3c0735a135b7c4..2d1939db108f9ef6f858faada9c69b854967b2ed 100644 (file)
@@ -438,16 +438,23 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
 #define ICL_AUX_PW_TO_CH(pw_idx)       \
        ((pw_idx) - ICL_PW_CTL_IDX_AUX_A + AUX_CH_A)
 
+#define ICL_TBT_AUX_PW_TO_CH(pw_idx)   \
+       ((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
+
 static void
 icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
                                 struct i915_power_well *power_well)
 {
-       enum aux_ch aux_ch = ICL_AUX_PW_TO_CH(power_well->desc->hsw.idx);
+       int pw_idx = power_well->desc->hsw.idx;
+       bool is_tbt = power_well->desc->hsw.is_tc_tbt;
+       enum aux_ch aux_ch;
        u32 val;
 
+       aux_ch = is_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
+                         ICL_AUX_PW_TO_CH(pw_idx);
        val = I915_READ(DP_AUX_CH_CTL(aux_ch));
        val &= ~DP_AUX_CH_CTL_TBT_IO;
-       if (power_well->desc->hsw.is_tc_tbt)
+       if (is_tbt)
                val |= DP_AUX_CH_CTL_TBT_IO;
        I915_WRITE(DP_AUX_CH_CTL(aux_ch), val);
 
index 4336df46fe7826460815a9ee621724199e1a7271..d0fc34826771791f619ea1c7a5c150930d9b8959 100644 (file)
@@ -231,6 +231,7 @@ static int intel_dp_get_fia_supported_lane_count(struct intel_dp *intel_dp)
        switch (lane_info) {
        default:
                MISSING_CASE(lane_info);
+               /* fall through */
        case 1:
        case 2:
        case 4:
index 60652ebbdf610a1cfda5228147265c77fe30f438..8aa6a31e8ad07d8e02f4e88142e665ce20997c19 100644 (file)
@@ -128,7 +128,15 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
        limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
 
        limits.min_bpp = intel_dp_min_bpp(pipe_config);
-       limits.max_bpp = pipe_config->pipe_bpp;
+       /*
+        * FIXME: If all the streams can't fit into the link with
+        * their current pipe_bpp we should reduce pipe_bpp across
+        * the board until things start to fit. Until then we
+        * limit to <= 8bpc since that's what was hardcoded for all
+        * MST streams previously. This hack should be removed once
+        * we have the proper retry logic in place.
+        */
+       limits.max_bpp = min(pipe_config->pipe_bpp, 24);
 
        intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits);
 
@@ -539,7 +547,15 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
 
        intel_attach_force_audio_property(connector);
        intel_attach_broadcast_rgb_property(connector);
-       drm_connector_attach_max_bpc_property(connector, 6, 12);
+
+       /*
+        * Reuse the prop from the SST connector because we're
+        * not allowed to create new props after device registration.
+        */
+       connector->max_bpc_property =
+               intel_dp->attached_connector->base.max_bpc_property;
+       if (connector->max_bpc_property)
+               drm_connector_attach_max_bpc_property(connector, 6, 12);
 
        return connector;
 
index bc3a94d491c4d0992b24346d011840318ade13d2..27bd7276a82dcfad356e2bc81d861d93ac99a000 100644 (file)
@@ -536,7 +536,8 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
 
        if (drm_hdcp_check_ksvs_revoked(dev, ksv_fifo, num_downstream)) {
                DRM_ERROR("Revoked Ksv(s) in ksv_fifo\n");
-               return -EPERM;
+               ret = -EPERM;
+               goto err;
        }
 
        /*
index 2f4894e9a03df336a903f24ca13b63d06ba66e97..5ddbe71ab423412307337dd9c1ae900d0b9ebc47 100644 (file)
@@ -478,13 +478,13 @@ struct psr_table {
        /* TP wake up time in multiple of 100 */
        u16 tp1_wakeup_time;
        u16 tp2_tp3_wakeup_time;
-
-       /* PSR2 TP2/TP3 wakeup time for 16 panels */
-       u32 psr2_tp2_tp3_wakeup_time;
 } __packed;
 
 struct bdb_psr {
        struct psr_table psr_table[16];
+
+       /* PSR2 TP2/TP3 wakeup time for 16 panels */
+       u32 psr2_tp2_tp3_wakeup_time;
 } __packed;
 
 /*
index ffec807b89600e6b3c63e4b222cc5f6cdcbe2317..f413904a3e960ffbc1895ee554846a024994761a 100644 (file)
@@ -541,7 +541,7 @@ static void intel_configure_pps_for_dsc_encoder(struct intel_encoder *encoder,
        pps_val |= DSC_PIC_HEIGHT(vdsc_cfg->pic_height) |
                DSC_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances);
        DRM_INFO("PPS2 = 0x%08x\n", pps_val);
-       if (encoder->type == INTEL_OUTPUT_EDP) {
+       if (cpu_transcoder == TRANSCODER_EDP) {
                I915_WRITE(DSCA_PICTURE_PARAMETER_SET_2, pps_val);
                /*
                 * If 2 VDSC instances are needed, configure PPS for second
index 99cc3e2e9c2cdc9b74b65714cf567f6a2ea2fb49..f016a776a39e32bf96f77dbd363997b7ad5caf1b 100644 (file)
@@ -396,8 +396,8 @@ static void glk_dsi_program_esc_clock(struct drm_device *dev,
        else
                txesc2_div = 10;
 
-       I915_WRITE(MIPIO_TXESC_CLK_DIV1, txesc1_div & GLK_TX_ESC_CLK_DIV1_MASK);
-       I915_WRITE(MIPIO_TXESC_CLK_DIV2, txesc2_div & GLK_TX_ESC_CLK_DIV2_MASK);
+       I915_WRITE(MIPIO_TXESC_CLK_DIV1, (1 << (txesc1_div - 1)) & GLK_TX_ESC_CLK_DIV1_MASK);
+       I915_WRITE(MIPIO_TXESC_CLK_DIV2, (1 << (txesc2_div - 1)) & GLK_TX_ESC_CLK_DIV2_MASK);
 }
 
 /* Program BXT Mipi clocks and dividers */
index 5fae0e50aad06881a53bc70c708ceccb7cbfe7d7..41dab9ea33cd4e566396550b0d9cc7aa299442ff 100644 (file)
@@ -1628,6 +1628,7 @@ static int check_relocations(const struct drm_i915_gem_exec_object2 *entry)
 
 static int eb_copy_relocations(const struct i915_execbuffer *eb)
 {
+       struct drm_i915_gem_relocation_entry *relocs;
        const unsigned int count = eb->buffer_count;
        unsigned int i;
        int err;
@@ -1635,7 +1636,6 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb)
        for (i = 0; i < count; i++) {
                const unsigned int nreloc = eb->exec[i].relocation_count;
                struct drm_i915_gem_relocation_entry __user *urelocs;
-               struct drm_i915_gem_relocation_entry *relocs;
                unsigned long size;
                unsigned long copied;
 
@@ -1663,14 +1663,8 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb)
 
                        if (__copy_from_user((char *)relocs + copied,
                                             (char __user *)urelocs + copied,
-                                            len)) {
-end_user:
-                               user_access_end();
-end:
-                               kvfree(relocs);
-                               err = -EFAULT;
-                               goto err;
-                       }
+                                            len))
+                               goto end;
 
                        copied += len;
                } while (copied < size);
@@ -1699,10 +1693,14 @@ end:
 
        return 0;
 
+end_user:
+       user_access_end();
+end:
+       kvfree(relocs);
+       err = -EFAULT;
 err:
        while (i--) {
-               struct drm_i915_gem_relocation_entry *relocs =
-                       u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr);
+               relocs = u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr);
                if (eb->exec[i].relocation_count)
                        kvfree(relocs);
        }
index 391621ee3cbb982cbaa5fd3fb811ffc666068268..39a661927d8e0f02e2d4aff967eb4b3d9bd3d989 100644 (file)
@@ -341,7 +341,7 @@ err:
                 */
                if (!i915_terminally_wedged(i915))
                        return VM_FAULT_SIGBUS;
-               /* else: fall through */
+               /* else, fall through */
        case -EAGAIN:
                /*
                 * EAGAIN means the gpu is hung and we'll wait for the error
index b36ad269f4ead8266f7355e0ee647abd8af507ad..65eb430cedba050caa9d7442407b76a2af55e95a 100644 (file)
@@ -268,7 +268,7 @@ static void *i915_gem_object_map(const struct drm_i915_gem_object *obj,
        switch (type) {
        default:
                MISSING_CASE(type);
-               /* fallthrough to use PAGE_KERNEL anyway */
+               /* fallthrough to use PAGE_KERNEL anyway */
        case I915_MAP_WB:
                pgprot = PAGE_KERNEL;
                break;
index 05011d4a3b88097a58ab6b59ff1b5dd7d42b614e..914b5d4112bbebfb375d9a1a14fd095374d304ab 100644 (file)
@@ -253,14 +253,15 @@ void i915_gem_resume(struct drm_i915_private *i915)
        i915_gem_restore_gtt_mappings(i915);
        i915_gem_restore_fences(i915);
 
+       if (i915_gem_init_hw(i915))
+               goto err_wedged;
+
        /*
         * As we didn't flush the kernel context before suspend, we cannot
         * guarantee that the context image is complete. So let's just reset
         * it and start again.
         */
-       intel_gt_resume(i915);
-
-       if (i915_gem_init_hw(i915))
+       if (intel_gt_resume(i915))
                goto err_wedged;
 
        intel_uc_resume(i915);
index 2c454f227c2e47cf94d05e8b2333e998fff5f6f0..23120901c55f410140f0b6029547de14014bb96e 100644 (file)
@@ -126,6 +126,7 @@ static void intel_context_retire(struct i915_active *active)
        if (ce->state)
                __context_unpin_state(ce->state);
 
+       intel_ring_unpin(ce->ring);
        intel_context_put(ce);
 }
 
@@ -160,27 +161,35 @@ int intel_context_active_acquire(struct intel_context *ce, unsigned long flags)
 
        intel_context_get(ce);
 
+       err = intel_ring_pin(ce->ring);
+       if (err)
+               goto err_put;
+
        if (!ce->state)
                return 0;
 
        err = __context_pin_state(ce->state, flags);
-       if (err) {
-               i915_active_cancel(&ce->active);
-               intel_context_put(ce);
-               return err;
-       }
+       if (err)
+               goto err_ring;
 
        /* Preallocate tracking nodes */
        if (!i915_gem_context_is_kernel(ce->gem_context)) {
                err = i915_active_acquire_preallocate_barrier(&ce->active,
                                                              ce->engine);
-               if (err) {
-                       i915_active_release(&ce->active);
-                       return err;
-               }
+               if (err)
+                       goto err_state;
        }
 
        return 0;
+
+err_state:
+       __context_unpin_state(ce->state);
+err_ring:
+       intel_ring_unpin(ce->ring);
+err_put:
+       intel_context_put(ce);
+       i915_active_cancel(&ce->active);
+       return err;
 }
 
 void intel_context_active_release(struct intel_context *ce)
index 7fd33e81c2d97dad11122b94d1bc515a03085725..f25632c9b292b2a841fdd75eb162e4b82d1bf02d 100644 (file)
@@ -969,9 +969,14 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
 u32 intel_calculate_mcr_s_ss_select(struct drm_i915_private *dev_priv)
 {
        const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
+       unsigned int slice = fls(sseu->slice_mask) - 1;
+       unsigned int subslice;
        u32 mcr_s_ss_select;
-       u32 slice = fls(sseu->slice_mask);
-       u32 subslice = fls(sseu->subslice_mask[slice]);
+
+       GEM_BUG_ON(slice >= ARRAY_SIZE(sseu->subslice_mask));
+       subslice = fls(sseu->subslice_mask[slice]);
+       GEM_BUG_ON(!subslice);
+       subslice--;
 
        if (IS_GEN(dev_priv, 10))
                mcr_s_ss_select = GEN8_MCR_SLICE(slice) |
@@ -1471,6 +1476,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
        struct i915_gpu_error * const error = &engine->i915->gpu_error;
        struct i915_request *rq;
        intel_wakeref_t wakeref;
+       unsigned long flags;
 
        if (header) {
                va_list ap;
@@ -1490,10 +1496,9 @@ void intel_engine_dump(struct intel_engine_cs *engine,
                   i915_reset_engine_count(error, engine),
                   i915_reset_count(error));
 
-       rcu_read_lock();
-
        drm_printf(m, "\tRequests:\n");
 
+       spin_lock_irqsave(&engine->active.lock, flags);
        rq = intel_engine_find_active_request(engine);
        if (rq) {
                print_request(m, rq, "\t\tactive ");
@@ -1513,8 +1518,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
 
                print_request_ring(m, rq);
        }
-
-       rcu_read_unlock();
+       spin_unlock_irqrestore(&engine->active.lock, flags);
 
        wakeref = intel_runtime_pm_get_if_in_use(&engine->i915->runtime_pm);
        if (wakeref) {
@@ -1672,7 +1676,6 @@ struct i915_request *
 intel_engine_find_active_request(struct intel_engine_cs *engine)
 {
        struct i915_request *request, *active = NULL;
-       unsigned long flags;
 
        /*
         * We are called by the error capture, reset and to dump engine
@@ -1685,7 +1688,7 @@ intel_engine_find_active_request(struct intel_engine_cs *engine)
         * At all other times, we must assume the GPU is still running, but
         * we only care about the snapshot of this moment.
         */
-       spin_lock_irqsave(&engine->active.lock, flags);
+       lockdep_assert_held(&engine->active.lock);
        list_for_each_entry(request, &engine->active.requests, sched.link) {
                if (i915_request_completed(request))
                        continue;
@@ -1700,7 +1703,6 @@ intel_engine_find_active_request(struct intel_engine_cs *engine)
                active = request;
                break;
        }
-       spin_unlock_irqrestore(&engine->active.lock, flags);
 
        return active;
 }
index 2ce00d3dc42a1a5fa17b2175b78cd3657f88abe1..ae5b6baf6dff1ee77e6ed5fae6df008ac551523c 100644 (file)
@@ -142,27 +142,3 @@ void intel_engine_init__pm(struct intel_engine_cs *engine)
 {
        intel_wakeref_init(&engine->wakeref);
 }
-
-int intel_engines_resume(struct drm_i915_private *i915)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-       int err = 0;
-
-       intel_gt_pm_get(i915);
-       for_each_engine(engine, i915, id) {
-               intel_engine_pm_get(engine);
-               engine->serial++; /* kernel context lost */
-               err = engine->resume(engine);
-               intel_engine_pm_put(engine);
-               if (err) {
-                       dev_err(i915->drm.dev,
-                               "Failed to restart %s (%d)\n",
-                               engine->name, err);
-                       break;
-               }
-       }
-       intel_gt_pm_put(i915);
-
-       return err;
-}
index b326cd993d60f23008abe85fe640160a23203a76..a11c893f64c6627cbaa266885160528af0a06c42 100644 (file)
@@ -7,16 +7,22 @@
 #ifndef INTEL_ENGINE_PM_H
 #define INTEL_ENGINE_PM_H
 
+#include "intel_engine_types.h"
+#include "intel_wakeref.h"
+
 struct drm_i915_private;
-struct intel_engine_cs;
 
 void intel_engine_pm_get(struct intel_engine_cs *engine);
 void intel_engine_pm_put(struct intel_engine_cs *engine);
 
+static inline bool
+intel_engine_pm_get_if_awake(struct intel_engine_cs *engine)
+{
+       return intel_wakeref_get_if_active(&engine->wakeref);
+}
+
 void intel_engine_park(struct intel_engine_cs *engine);
 
 void intel_engine_init__pm(struct intel_engine_cs *engine);
 
-int intel_engines_resume(struct drm_i915_private *i915);
-
 #endif /* INTEL_ENGINE_PM_H */
index 868b220214f81b23087d7d8641345fea137b6640..43e975a26016bf75038a044c55e222aefcf8ff2b 100644 (file)
@@ -70,6 +70,18 @@ struct intel_ring {
        struct list_head request_list;
        struct list_head active_link;
 
+       /*
+        * As we have two types of rings, one global to the engine used
+        * by ringbuffer submission and those that are exclusive to a
+        * context used by execlists, we have to play safe and allow
+        * atomic updates to the pin_count. However, the actual pinning
+        * of the context is either done during initialisation for
+        * ringbuffer submission or serialised as part of the context
+        * pinning for execlists, and so we do not need a mutex ourselves
+        * to serialise intel_ring_pin/intel_ring_unpin.
+        */
+       atomic_t pin_count;
+
        u32 head;
        u32 tail;
        u32 emit;
index 7b59677517629278341981ebdfd71aeb3a75353e..9f8f7f54191f06fbdca97dc8dbcae4a9d8a74ee2 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "i915_drv.h"
+#include "intel_engine_pm.h"
 #include "intel_gt_pm.h"
 #include "intel_pm.h"
 #include "intel_wakeref.h"
@@ -118,10 +119,11 @@ void intel_gt_sanitize(struct drm_i915_private *i915, bool force)
                intel_engine_reset(engine, false);
 }
 
-void intel_gt_resume(struct drm_i915_private *i915)
+int intel_gt_resume(struct drm_i915_private *i915)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
+       int err = 0;
 
        /*
         * After resume, we may need to poke into the pinned kernel
@@ -129,9 +131,12 @@ void intel_gt_resume(struct drm_i915_private *i915)
         * Only the kernel contexts should remain pinned over suspend,
         * allowing us to fixup the user contexts on their first pin.
         */
+       intel_gt_pm_get(i915);
        for_each_engine(engine, i915, id) {
                struct intel_context *ce;
 
+               intel_engine_pm_get(engine);
+
                ce = engine->kernel_context;
                if (ce)
                        ce->ops->reset(ce);
@@ -139,5 +144,19 @@ void intel_gt_resume(struct drm_i915_private *i915)
                ce = engine->preempt_context;
                if (ce)
                        ce->ops->reset(ce);
+
+               engine->serial++; /* kernel context lost */
+               err = engine->resume(engine);
+
+               intel_engine_pm_put(engine);
+               if (err) {
+                       dev_err(i915->drm.dev,
+                               "Failed to restart %s (%d)\n",
+                               engine->name, err);
+                       break;
+               }
        }
+       intel_gt_pm_put(i915);
+
+       return err;
 }
index 7dd1130a19a480ce02b07d99afb2d2358ec32709..53f342b20181a8e03d651dd48926e4fa747f6ce4 100644 (file)
@@ -22,6 +22,6 @@ void intel_gt_pm_put(struct drm_i915_private *i915);
 void intel_gt_pm_init(struct drm_i915_private *i915);
 
 void intel_gt_sanitize(struct drm_i915_private *i915, bool force);
-void intel_gt_resume(struct drm_i915_private *i915);
+int intel_gt_resume(struct drm_i915_private *i915);
 
 #endif /* INTEL_GT_PM_H */
index b42b5f158295953b7b6da42f4846e96b9d4b4afb..82b7ace62d97ec13f110b4454115ae313d0791e0 100644 (file)
@@ -1414,6 +1414,7 @@ static void execlists_context_destroy(struct kref *kref)
 {
        struct intel_context *ce = container_of(kref, typeof(*ce), ref);
 
+       GEM_BUG_ON(!i915_active_is_idle(&ce->active));
        GEM_BUG_ON(intel_context_is_pinned(ce));
 
        if (ce->state)
@@ -1426,7 +1427,6 @@ static void execlists_context_unpin(struct intel_context *ce)
 {
        i915_gem_context_unpin_hw_id(ce->gem_context);
        i915_gem_object_unpin_map(ce->state->obj);
-       intel_ring_unpin(ce->ring);
 }
 
 static void
@@ -1478,13 +1478,9 @@ __execlists_context_pin(struct intel_context *ce,
                goto unpin_active;
        }
 
-       ret = intel_ring_pin(ce->ring);
-       if (ret)
-               goto unpin_map;
-
        ret = i915_gem_context_pin_hw_id(ce->gem_context);
        if (ret)
-               goto unpin_ring;
+               goto unpin_map;
 
        ce->lrc_desc = lrc_descriptor(ce, engine);
        ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
@@ -1492,8 +1488,6 @@ __execlists_context_pin(struct intel_context *ce,
 
        return 0;
 
-unpin_ring:
-       intel_ring_unpin(ce->ring);
 unpin_map:
        i915_gem_object_unpin_map(ce->state->obj);
 unpin_active:
index 4c478b38e4209aab66e7b3078431ac785602a659..3f907701ef4d658a91a275fe089743a05b1cf702 100644 (file)
@@ -687,7 +687,6 @@ static void reset_prepare_engine(struct intel_engine_cs *engine)
         * written to the powercontext is undefined and so we may lose
         * GPU state upon resume, i.e. fail to restart after a reset.
         */
-       intel_engine_pm_get(engine);
        intel_uncore_forcewake_get(engine->uncore, FORCEWAKE_ALL);
        engine->reset.prepare(engine);
 }
@@ -718,16 +717,21 @@ static void revoke_mmaps(struct drm_i915_private *i915)
        }
 }
 
-static void reset_prepare(struct drm_i915_private *i915)
+static intel_engine_mask_t reset_prepare(struct drm_i915_private *i915)
 {
        struct intel_engine_cs *engine;
+       intel_engine_mask_t awake = 0;
        enum intel_engine_id id;
 
-       intel_gt_pm_get(i915);
-       for_each_engine(engine, i915, id)
+       for_each_engine(engine, i915, id) {
+               if (intel_engine_pm_get_if_awake(engine))
+                       awake |= engine->mask;
                reset_prepare_engine(engine);
+       }
 
        intel_uc_reset_prepare(i915);
+
+       return awake;
 }
 
 static void gt_revoke(struct drm_i915_private *i915)
@@ -761,20 +765,22 @@ static int gt_reset(struct drm_i915_private *i915,
 static void reset_finish_engine(struct intel_engine_cs *engine)
 {
        engine->reset.finish(engine);
-       intel_engine_pm_put(engine);
        intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL);
+
+       intel_engine_signal_breadcrumbs(engine);
 }
 
-static void reset_finish(struct drm_i915_private *i915)
+static void reset_finish(struct drm_i915_private *i915,
+                        intel_engine_mask_t awake)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
 
        for_each_engine(engine, i915, id) {
                reset_finish_engine(engine);
-               intel_engine_signal_breadcrumbs(engine);
+               if (awake & engine->mask)
+                       intel_engine_pm_put(engine);
        }
-       intel_gt_pm_put(i915);
 }
 
 static void nop_submit_request(struct i915_request *request)
@@ -798,6 +804,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915)
 {
        struct i915_gpu_error *error = &i915->gpu_error;
        struct intel_engine_cs *engine;
+       intel_engine_mask_t awake;
        enum intel_engine_id id;
 
        if (test_bit(I915_WEDGED, &error->flags))
@@ -817,7 +824,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915)
         * rolling the global seqno forward (since this would complete requests
         * for which we haven't set the fence error to EIO yet).
         */
-       reset_prepare(i915);
+       awake = reset_prepare(i915);
 
        /* Even if the GPU reset fails, it should still stop the engines */
        if (!INTEL_INFO(i915)->gpu_reset_clobbers_display)
@@ -841,7 +848,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915)
        for_each_engine(engine, i915, id)
                engine->cancel_requests(engine);
 
-       reset_finish(i915);
+       reset_finish(i915, awake);
 
        GEM_TRACE("end\n");
 }
@@ -951,6 +958,21 @@ static int do_reset(struct drm_i915_private *i915,
        return gt_reset(i915, stalled_mask);
 }
 
+static int resume(struct drm_i915_private *i915)
+{
+       struct intel_engine_cs *engine;
+       enum intel_engine_id id;
+       int ret;
+
+       for_each_engine(engine, i915, id) {
+               ret = engine->resume(engine);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 /**
  * i915_reset - reset chip after a hang
  * @i915: #drm_i915_private to reset
@@ -973,6 +995,7 @@ void i915_reset(struct drm_i915_private *i915,
                const char *reason)
 {
        struct i915_gpu_error *error = &i915->gpu_error;
+       intel_engine_mask_t awake;
        int ret;
 
        GEM_TRACE("flags=%lx\n", error->flags);
@@ -989,7 +1012,7 @@ void i915_reset(struct drm_i915_private *i915,
                dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason);
        error->reset_count++;
 
-       reset_prepare(i915);
+       awake = reset_prepare(i915);
 
        if (!intel_has_gpu_reset(i915)) {
                if (i915_modparams.reset)
@@ -1024,13 +1047,17 @@ void i915_reset(struct drm_i915_private *i915,
        if (ret) {
                DRM_ERROR("Failed to initialise HW following reset (%d)\n",
                          ret);
-               goto error;
+               goto taint;
        }
 
+       ret = resume(i915);
+       if (ret)
+               goto taint;
+
        i915_queue_hangcheck(i915);
 
 finish:
-       reset_finish(i915);
+       reset_finish(i915, awake);
 unlock:
        mutex_unlock(&error->wedge_mutex);
        return;
@@ -1081,7 +1108,7 @@ int i915_reset_engine(struct intel_engine_cs *engine, const char *msg)
        GEM_TRACE("%s flags=%lx\n", engine->name, error->flags);
        GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags));
 
-       if (!intel_wakeref_active(&engine->wakeref))
+       if (!intel_engine_pm_get_if_awake(engine))
                return 0;
 
        reset_prepare_engine(engine);
@@ -1116,12 +1143,11 @@ int i915_reset_engine(struct intel_engine_cs *engine, const char *msg)
         * process to program RING_MODE, HWSP and re-enable submission.
         */
        ret = engine->resume(engine);
-       if (ret)
-               goto out;
 
 out:
        intel_engine_cancel_stop_cs(engine);
        reset_finish_engine(engine);
+       intel_engine_pm_put(engine);
        return ret;
 }
 
index c6023bc9452d0d90f8252d824d1492c07bc7022b..12010e79886888c5bbf2c0ae58a888f69e00dd6e 100644 (file)
@@ -1149,16 +1149,16 @@ i915_emit_bb_start(struct i915_request *rq,
 int intel_ring_pin(struct intel_ring *ring)
 {
        struct i915_vma *vma = ring->vma;
-       enum i915_map_type map = i915_coherent_map_type(vma->vm->i915);
        unsigned int flags;
        void *addr;
        int ret;
 
-       GEM_BUG_ON(ring->vaddr);
+       if (atomic_fetch_inc(&ring->pin_count))
+               return 0;
 
        ret = i915_timeline_pin(ring->timeline);
        if (ret)
-               return ret;
+               goto err_unpin;
 
        flags = PIN_GLOBAL;
 
@@ -1172,26 +1172,31 @@ int intel_ring_pin(struct intel_ring *ring)
 
        ret = i915_vma_pin(vma, 0, 0, flags);
        if (unlikely(ret))
-               goto unpin_timeline;
+               goto err_timeline;
 
        if (i915_vma_is_map_and_fenceable(vma))
                addr = (void __force *)i915_vma_pin_iomap(vma);
        else
-               addr = i915_gem_object_pin_map(vma->obj, map);
+               addr = i915_gem_object_pin_map(vma->obj,
+                                              i915_coherent_map_type(vma->vm->i915));
        if (IS_ERR(addr)) {
                ret = PTR_ERR(addr);
-               goto unpin_ring;
+               goto err_ring;
        }
 
        vma->obj->pin_global++;
 
+       GEM_BUG_ON(ring->vaddr);
        ring->vaddr = addr;
+
        return 0;
 
-unpin_ring:
+err_ring:
        i915_vma_unpin(vma);
-unpin_timeline:
+err_timeline:
        i915_timeline_unpin(ring->timeline);
+err_unpin:
+       atomic_dec(&ring->pin_count);
        return ret;
 }
 
@@ -1207,16 +1212,19 @@ void intel_ring_reset(struct intel_ring *ring, u32 tail)
 
 void intel_ring_unpin(struct intel_ring *ring)
 {
-       GEM_BUG_ON(!ring->vma);
-       GEM_BUG_ON(!ring->vaddr);
+       if (!atomic_dec_and_test(&ring->pin_count))
+               return;
 
        /* Discard any unused bytes beyond that submitted to hw. */
        intel_ring_reset(ring, ring->tail);
 
+       GEM_BUG_ON(!ring->vma);
        if (i915_vma_is_map_and_fenceable(ring->vma))
                i915_vma_unpin_iomap(ring->vma);
        else
                i915_gem_object_unpin_map(ring->vma->obj);
+
+       GEM_BUG_ON(!ring->vaddr);
        ring->vaddr = NULL;
 
        ring->vma->obj->pin_global--;
@@ -2081,10 +2089,11 @@ static void ring_destroy(struct intel_engine_cs *engine)
        WARN_ON(INTEL_GEN(dev_priv) > 2 &&
                (ENGINE_READ(engine, RING_MI_MODE) & MODE_IDLE) == 0);
 
+       intel_engine_cleanup_common(engine);
+
        intel_ring_unpin(engine->buffer);
        intel_ring_put(engine->buffer);
 
-       intel_engine_cleanup_common(engine);
        kfree(engine);
 }
 
index 15e90fd2cfdc2e9882cfeff9f2e2e1e4a1ff1a7e..99e8242194c00891698ce9659e9960efe0d39b4e 100644 (file)
@@ -308,11 +308,6 @@ static void gen9_ctx_workarounds_init(struct intel_engine_cs *engine,
                          FLOW_CONTROL_ENABLE |
                          PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
 
-       /* Syncing dependencies between camera and graphics:skl,bxt,kbl */
-       if (!IS_COFFEELAKE(i915))
-               WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
-                                 GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
-
        /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl,glk,cfl */
        /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl,cfl */
        WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
@@ -1098,10 +1093,25 @@ static void glk_whitelist_build(struct intel_engine_cs *engine)
 
 static void cfl_whitelist_build(struct intel_engine_cs *engine)
 {
+       struct i915_wa_list *w = &engine->whitelist;
+
        if (engine->class != RENDER_CLASS)
                return;
 
-       gen9_whitelist_build(&engine->whitelist);
+       gen9_whitelist_build(w);
+
+       /*
+        * WaAllowPMDepthAndInvocationCountAccessFromUMD:cfl,whl,cml,aml
+        *
+        * This covers 4 register which are next to one another :
+        *   - PS_INVOCATION_COUNT
+        *   - PS_INVOCATION_COUNT_UDW
+        *   - PS_DEPTH_COUNT
+        *   - PS_DEPTH_COUNT_UDW
+        */
+       whitelist_reg_ext(w, PS_INVOCATION_COUNT,
+                         RING_FORCE_TO_NONPRIV_RD |
+                         RING_FORCE_TO_NONPRIV_RANGE_4);
 }
 
 static void cnl_whitelist_build(struct intel_engine_cs *engine)
@@ -1129,6 +1139,19 @@ static void icl_whitelist_build(struct intel_engine_cs *engine)
 
                /* WaEnableStateCacheRedirectToCS:icl */
                whitelist_reg(w, GEN9_SLICE_COMMON_ECO_CHICKEN1);
+
+               /*
+                * WaAllowPMDepthAndInvocationCountAccessFromUMD:icl
+                *
+                * This covers 4 register which are next to one another :
+                *   - PS_INVOCATION_COUNT
+                *   - PS_INVOCATION_COUNT_UDW
+                *   - PS_DEPTH_COUNT
+                *   - PS_DEPTH_COUNT_UDW
+                */
+               whitelist_reg_ext(w, PS_INVOCATION_COUNT,
+                                 RING_FORCE_TO_NONPRIV_RD |
+                                 RING_FORCE_TO_NONPRIV_RANGE_4);
                break;
 
        case VIDEO_DECODE_CLASS:
@@ -1258,8 +1281,12 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
                if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
                        wa_write_or(wal,
                                    GEN7_SARCHKMD,
-                                   GEN7_DISABLE_DEMAND_PREFETCH |
-                                   GEN7_DISABLE_SAMPLER_PREFETCH);
+                                   GEN7_DISABLE_DEMAND_PREFETCH);
+
+               /* Wa_1606682166:icl */
+               wa_write_or(wal,
+                           GEN7_SARCHKMD,
+                           GEN7_DISABLE_SAMPLER_PREFETCH);
        }
 
        if (IS_GEN_RANGE(i915, 9, 11)) {
index 086801b514416d0f175b1088ef87dde907a6708a..486c6953dcb182463ce7ceedcf2df716af8ca53f 100644 (file)
@@ -66,6 +66,7 @@ static struct intel_ring *mock_ring(struct intel_engine_cs *engine)
        ring->base.effective_size = sz;
        ring->base.vaddr = (void *)(ring + 1);
        ring->base.timeline = &ring->timeline;
+       atomic_set(&ring->base.pin_count, 1);
 
        INIT_LIST_HEAD(&ring->base.request_list);
        intel_ring_update_space(&ring->base);
index 89da9e7cc1bae0c65bf64054253a975d5829fc94..b5c590c9ccba9355a5e66a1a33a732c345f0ea4a 100644 (file)
@@ -71,13 +71,16 @@ static int igt_atomic_reset(void *arg)
                goto unlock;
 
        for (p = igt_atomic_phases; p->name; p++) {
+               intel_engine_mask_t awake;
+
                GEM_TRACE("intel_gpu_reset under %s\n", p->name);
 
+               awake = reset_prepare(i915);
                p->critical_section_begin();
                reset_prepare(i915);
                err = intel_gpu_reset(i915, ALL_ENGINES);
-               reset_finish(i915);
                p->critical_section_end();
+               reset_finish(i915, awake);
 
                if (err) {
                        pr_err("intel_gpu_reset failed under %s\n", p->name);
index 9eaf030affd0f43db998da9d4445ca810e33ef2d..44becd9538bed54d0d266a7b9e4b68455bdc9e61 100644 (file)
@@ -925,7 +925,12 @@ check_whitelisted_registers(struct intel_engine_cs *engine,
 
        err = 0;
        for (i = 0; i < engine->whitelist.count; i++) {
-               if (!fn(engine, a[i], b[i], engine->whitelist.list[i].reg))
+               const struct i915_wa *wa = &engine->whitelist.list[i];
+
+               if (i915_mmio_reg_offset(wa->reg) & RING_FORCE_TO_NONPRIV_RD)
+                       continue;
+
+               if (!fn(engine, a[i], b[i], wa->reg))
                        err = -EINVAL;
        }
 
index 6ea88270c818ff62680e56f95cfef8a3c3c1f1f3..b09dc315e2dab7674275482b8908b3c902962e85 100644 (file)
@@ -2674,11 +2674,6 @@ static int scan_workload(struct intel_vgpu_workload *workload)
                gma_head == gma_tail)
                return 0;
 
-       if (!intel_gvt_ggtt_validate_range(s.vgpu, s.ring_start, s.ring_size)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
        ret = ip_gma_set(&s, gma_head);
        if (ret)
                goto out;
@@ -2724,11 +2719,6 @@ static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
        s.workload = workload;
        s.is_ctx_wa = true;
 
-       if (!intel_gvt_ggtt_validate_range(s.vgpu, s.ring_start, s.ring_size)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
        ret = ip_gma_set(&s, gma_head);
        if (ret)
                goto out;
index 65e847392aea788f2feb17c381f75f0defc62709..8bb292b01271600eae8bd835e71fba2b209f5cc4 100644 (file)
@@ -245,7 +245,7 @@ int intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu,
        plane->hw_format = fmt;
 
        plane->base = vgpu_vreg_t(vgpu, DSPSURF(pipe)) & I915_GTT_PAGE_MASK;
-       if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
+       if (!vgpu_gmadr_is_valid(vgpu, plane->base))
                return  -EINVAL;
 
        plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
@@ -368,7 +368,7 @@ int intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu,
                        alpha_plane, alpha_force);
 
        plane->base = vgpu_vreg_t(vgpu, CURBASE(pipe)) & I915_GTT_PAGE_MASK;
-       if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
+       if (!vgpu_gmadr_is_valid(vgpu, plane->base))
                return  -EINVAL;
 
        plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
@@ -472,7 +472,7 @@ int intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu,
        plane->drm_format = drm_format;
 
        plane->base = vgpu_vreg_t(vgpu, SPRSURF(pipe)) & I915_GTT_PAGE_MASK;
-       if (!intel_gvt_ggtt_validate_range(vgpu, plane->base, 0))
+       if (!vgpu_gmadr_is_valid(vgpu, plane->base))
                return  -EINVAL;
 
        plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base);
index 53115bdae12be320e3de82562fa6d36a39684686..4b04af569c05c13df7cc4f6ca235abb0b281d025 100644 (file)
@@ -2141,11 +2141,20 @@ static int emulate_ggtt_mmio_read(struct intel_vgpu *vgpu,
        struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
        const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
        unsigned long index = off >> info->gtt_entry_size_shift;
+       unsigned long gma;
        struct intel_gvt_gtt_entry e;
 
        if (bytes != 4 && bytes != 8)
                return -EINVAL;
 
+       gma = index << I915_GTT_PAGE_SHIFT;
+       if (!intel_gvt_ggtt_validate_range(vgpu,
+                                          gma, 1 << I915_GTT_PAGE_SHIFT)) {
+               gvt_dbg_mm("read invalid ggtt at 0x%lx\n", gma);
+               memset(p_data, 0, bytes);
+               return 0;
+       }
+
        ggtt_get_guest_entry(ggtt_mm, &e, index);
        memcpy(p_data, (void *)&e.val64 + (off & (info->gtt_entry_size - 1)),
                        bytes);
index 144301b778df275e1327217de3eb497ac5317252..23aa3e50cbf89fdf82948c9159ca2455c8f122a1 100644 (file)
@@ -1904,6 +1904,18 @@ static int kvmgt_dma_map_guest_page(unsigned long handle, unsigned long gfn,
 
        entry = __gvt_cache_find_gfn(info->vgpu, gfn);
        if (!entry) {
+               ret = gvt_dma_map_page(vgpu, gfn, dma_addr, size);
+               if (ret)
+                       goto err_unlock;
+
+               ret = __gvt_cache_add(info->vgpu, gfn, *dma_addr, size);
+               if (ret)
+                       goto err_unmap;
+       } else if (entry->size != size) {
+               /* the same gfn with different size: unmap and re-map */
+               gvt_dma_unmap_page(vgpu, gfn, entry->dma_addr, entry->size);
+               __gvt_cache_remove_entry(vgpu, entry);
+
                ret = gvt_dma_map_page(vgpu, gfn, dma_addr, size);
                if (ret)
                        goto err_unlock;
index 2144fb46d0e1ce5f45c125cf3286694e78ff8708..75baff657e4331f28fc58d938c7a9de7087e0fcc 100644 (file)
@@ -364,16 +364,13 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
        wa_ctx->indirect_ctx.shadow_va = NULL;
 }
 
-static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
-                                        struct i915_gem_context *ctx)
+static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
+                                         struct i915_gem_context *ctx)
 {
        struct intel_vgpu_mm *mm = workload->shadow_mm;
        struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(ctx->vm);
        int i = 0;
 
-       if (mm->type != INTEL_GVT_MM_PPGTT || !mm->ppgtt_mm.shadowed)
-               return -EINVAL;
-
        if (mm->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
                px_dma(ppgtt->pd) = mm->ppgtt_mm.shadow_pdps[0];
        } else {
@@ -384,8 +381,6 @@ static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
                        px_dma(pd) = mm->ppgtt_mm.shadow_pdps[i];
                }
        }
-
-       return 0;
 }
 
 static int
@@ -614,6 +609,8 @@ static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload)
 static int prepare_workload(struct intel_vgpu_workload *workload)
 {
        struct intel_vgpu *vgpu = workload->vgpu;
+       struct intel_vgpu_submission *s = &vgpu->submission;
+       int ring = workload->ring_id;
        int ret = 0;
 
        ret = intel_vgpu_pin_mm(workload->shadow_mm);
@@ -622,8 +619,16 @@ static int prepare_workload(struct intel_vgpu_workload *workload)
                return ret;
        }
 
+       if (workload->shadow_mm->type != INTEL_GVT_MM_PPGTT ||
+           !workload->shadow_mm->ppgtt_mm.shadowed) {
+               gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
+               return -EINVAL;
+       }
+
        update_shadow_pdps(workload);
 
+       set_context_ppgtt_from_shadow(workload, s->shadow[ring]->gem_context);
+
        ret = intel_vgpu_sync_oos_pages(workload->vgpu);
        if (ret) {
                gvt_vgpu_err("fail to vgpu sync oos pages\n");
@@ -674,7 +679,6 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
 {
        struct intel_vgpu *vgpu = workload->vgpu;
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
-       struct intel_vgpu_submission *s = &vgpu->submission;
        struct i915_request *rq;
        int ring_id = workload->ring_id;
        int ret;
@@ -685,13 +689,6 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
        mutex_lock(&vgpu->vgpu_lock);
        mutex_lock(&dev_priv->drm.struct_mutex);
 
-       ret = set_context_ppgtt_from_shadow(workload,
-                                           s->shadow[ring_id]->gem_context);
-       if (ret < 0) {
-               gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
-               goto err_req;
-       }
-
        ret = intel_gvt_workload_req_alloc(workload);
        if (ret)
                goto err_req;
@@ -990,6 +987,7 @@ static int workload_thread(void *priv)
        int ret;
        bool need_force_wake = (INTEL_GEN(gvt->dev_priv) >= 9);
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
+       struct intel_runtime_pm *rpm = &gvt->dev_priv->runtime_pm;
 
        kfree(p);
 
@@ -1013,6 +1011,8 @@ static int workload_thread(void *priv)
                                workload->ring_id, workload,
                                workload->vgpu->id);
 
+               intel_runtime_pm_get(rpm);
+
                gvt_dbg_sched("ring id %d will dispatch workload %p\n",
                                workload->ring_id, workload);
 
@@ -1042,6 +1042,7 @@ complete:
                        intel_uncore_forcewake_put(&gvt->dev_priv->uncore,
                                        FORCEWAKE_ALL);
 
+               intel_runtime_pm_put_unchecked(rpm);
                if (ret && (vgpu_is_vm_unhealthy(ret)))
                        enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
        }
@@ -1492,6 +1493,12 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
        intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
                        RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4);
 
+       if (!intel_gvt_ggtt_validate_range(vgpu, start,
+                               _RING_CTL_BUF_SIZE(ctl))) {
+               gvt_vgpu_err("context contain invalid rb at: 0x%x\n", start);
+               return ERR_PTR(-EINVAL);
+       }
+
        workload = alloc_workload(vgpu);
        if (IS_ERR(workload))
                return workload;
@@ -1516,9 +1523,31 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
                workload->wa_ctx.indirect_ctx.size =
                        (indirect_ctx & INDIRECT_CTX_SIZE_MASK) *
                        CACHELINE_BYTES;
+
+               if (workload->wa_ctx.indirect_ctx.size != 0) {
+                       if (!intel_gvt_ggtt_validate_range(vgpu,
+                               workload->wa_ctx.indirect_ctx.guest_gma,
+                               workload->wa_ctx.indirect_ctx.size)) {
+                               gvt_vgpu_err("invalid wa_ctx at: 0x%lx\n",
+                                   workload->wa_ctx.indirect_ctx.guest_gma);
+                               kmem_cache_free(s->workloads, workload);
+                               return ERR_PTR(-EINVAL);
+                       }
+               }
+
                workload->wa_ctx.per_ctx.guest_gma =
                        per_ctx & PER_CTX_ADDR_MASK;
                workload->wa_ctx.per_ctx.valid = per_ctx & 1;
+               if (workload->wa_ctx.per_ctx.valid) {
+                       if (!intel_gvt_ggtt_validate_range(vgpu,
+                               workload->wa_ctx.per_ctx.guest_gma,
+                               CACHELINE_BYTES)) {
+                               gvt_vgpu_err("invalid per_ctx at: 0x%lx\n",
+                                       workload->wa_ctx.per_ctx.guest_gma);
+                               kmem_cache_free(s->workloads, workload);
+                               return ERR_PTR(-EINVAL);
+                       }
+               }
        }
 
        gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n",
index a3deed692b9c4a5a5faeebac9dea625a2a16ed59..fe552e877e096911a37cda531e8ae7abdbecfa34 100644 (file)
@@ -28,8 +28,6 @@
  *
  */
 
-#include "trace.h"
-
 #ifndef __CHECKER__
 #define CREATE_TRACE_POINTS
 #include "trace.h"
index f62e3397d9363e81185ace4663f14243b3e24855..bac1ee94f63fc0be121cb371cd9e38351494c322 100644 (file)
@@ -1598,6 +1598,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
 
        pci_set_master(pdev);
 
+       /*
+        * We don't have a max segment size, so set it to the max so sg's
+        * debugging layer doesn't complain
+        */
+       dma_set_max_seg_size(&pdev->dev, UINT_MAX);
+
        /* overlay on gen2 is broken and can't address above 1G */
        if (IS_GEN(dev_priv, 2)) {
                ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30));
index bc909ec5d9c3bb6a5f543d71bae292091acba5ea..fe7a6ec2c199c49bd2750b4ac92b2690fada1435 100644 (file)
@@ -1674,8 +1674,9 @@ struct drm_i915_private {
        } dram_info;
 
        struct intel_bw_info {
-               int num_planes;
-               int deratedbw[3];
+               unsigned int deratedbw[3]; /* for each QGV point */
+               u8 num_qgv_points;
+               u8 num_planes;
        } max_bw[6];
 
        struct drm_private_obj bw_obj;
index 190ad54fb072dedf5b44cdd0fd18f0fbe006d8b0..8a659d3d7435d14198614250cb7296c2ca956b96 100644 (file)
@@ -46,7 +46,6 @@
 #include "gem/i915_gem_ioctls.h"
 #include "gem/i915_gem_pm.h"
 #include "gem/i915_gemfs.h"
-#include "gt/intel_engine_pm.h"
 #include "gt/intel_gt_pm.h"
 #include "gt/intel_mocs.h"
 #include "gt/intel_reset.h"
@@ -1307,21 +1306,13 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
 
        intel_mocs_init_l3cc_table(dev_priv);
 
-       /* Only when the HW is re-initialised, can we replay the requests */
-       ret = intel_engines_resume(dev_priv);
-       if (ret)
-               goto cleanup_uc;
-
        intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
 
        intel_engines_set_scheduler_caps(dev_priv);
        return 0;
 
-cleanup_uc:
-       intel_uc_fini_hw(dev_priv);
 out:
        intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
-
        return ret;
 }
 
@@ -1580,6 +1571,11 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
        if (ret)
                goto err_uc_init;
 
+       /* Only when the HW is re-initialised, can we replay the requests */
+       ret = intel_gt_resume(dev_priv);
+       if (ret)
+               goto err_init_hw;
+
        /*
         * Despite its name intel_init_clock_gating applies both display
         * clock gating workarounds; GT mmio workarounds and the occasional
@@ -1593,20 +1589,20 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
 
        ret = intel_engines_verify_workarounds(dev_priv);
        if (ret)
-               goto err_init_hw;
+               goto err_gt;
 
        ret = __intel_engines_record_defaults(dev_priv);
        if (ret)
-               goto err_init_hw;
+               goto err_gt;
 
        if (i915_inject_load_failure()) {
                ret = -ENODEV;
-               goto err_init_hw;
+               goto err_gt;
        }
 
        if (i915_inject_load_failure()) {
                ret = -EIO;
-               goto err_init_hw;
+               goto err_gt;
        }
 
        intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
@@ -1620,7 +1616,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
         * HW as irrevisibly wedged, but keep enough state around that the
         * driver doesn't explode during runtime.
         */
-err_init_hw:
+err_gt:
        mutex_unlock(&dev_priv->drm.struct_mutex);
 
        i915_gem_set_wedged(dev_priv);
@@ -1630,6 +1626,7 @@ err_init_hw:
        i915_gem_drain_workqueue(dev_priv);
 
        mutex_lock(&dev_priv->drm.struct_mutex);
+err_init_hw:
        intel_uc_fini_hw(dev_priv);
 err_uc_init:
        intel_uc_fini(dev_priv);
index 8ab820145ea6cacd8b025ad8f8e2371088a91bc3..7015a97b10979ab147fa4dc90fca9b0c11c8f0a4 100644 (file)
@@ -1444,9 +1444,11 @@ unwind_pd:
        spin_lock(&pdp->lock);
        if (atomic_dec_and_test(&pd->used)) {
                gen8_ppgtt_set_pdpe(pdp, vm->scratch_pd, pdpe);
+               pdp->entry[pdpe] = vm->scratch_pd;
                GEM_BUG_ON(!atomic_read(&pdp->used));
                atomic_dec(&pdp->used);
-               free_pd(vm, pd);
+               GEM_BUG_ON(alloc);
+               alloc = pd; /* defer the free to after the lock */
        }
        spin_unlock(&pdp->lock);
 unwind:
@@ -1515,7 +1517,9 @@ unwind_pdp:
        spin_lock(&pml4->lock);
        if (atomic_dec_and_test(&pdp->used)) {
                gen8_ppgtt_set_pml4e(pml4, vm->scratch_pdp, pml4e);
-               free_pd(vm, pdp);
+               pml4->entry[pml4e] = vm->scratch_pdp;
+               GEM_BUG_ON(alloc);
+               alloc = pdp; /* defer the free until after the lock */
        }
        spin_unlock(&pml4->lock);
 unwind:
index b7e9fddef270a27811d352368789e4d79cdcbc56..8bc76fcff70d96acfcca3d19fafbcd57bd2a8ee8 100644 (file)
@@ -1194,6 +1194,7 @@ static void error_record_engine_registers(struct i915_gpu_state *error,
                        switch (engine->id) {
                        default:
                                MISSING_CASE(engine->id);
+                               /* fall through */
                        case RCS0:
                                mmio = RENDER_HWS_PGA_GEN7;
                                break;
@@ -1417,6 +1418,7 @@ static void gem_record_rings(struct i915_gpu_state *error)
                struct intel_engine_cs *engine = i915->engine[i];
                struct drm_i915_error_engine *ee = &error->engine[i];
                struct i915_request *request;
+               unsigned long flags;
 
                ee->engine_id = -1;
 
@@ -1428,10 +1430,11 @@ static void gem_record_rings(struct i915_gpu_state *error)
                error_record_engine_registers(error, engine, ee);
                error_record_engine_execlists(engine, ee);
 
+               spin_lock_irqsave(&engine->active.lock, flags);
                request = intel_engine_find_active_request(engine);
                if (request) {
                        struct i915_gem_context *ctx = request->gem_context;
-                       struct intel_ring *ring;
+                       struct intel_ring *ring = request->ring;
 
                        ee->vm = ctx->vm ?: &ggtt->vm;
 
@@ -1461,7 +1464,6 @@ static void gem_record_rings(struct i915_gpu_state *error)
                        ee->rq_post = request->postfix;
                        ee->rq_tail = request->tail;
 
-                       ring = request->ring;
                        ee->cpu_ring_head = ring->head;
                        ee->cpu_ring_tail = ring->tail;
                        ee->ringbuffer =
@@ -1469,6 +1471,7 @@ static void gem_record_rings(struct i915_gpu_state *error)
 
                        engine_record_requests(engine, request, ee);
                }
+               spin_unlock_irqrestore(&engine->active.lock, flags);
 
                ee->hws_page =
                        i915_error_object_create(i915,
index a700c5c3d1673516355bdbac0468adca9cfc664e..5140017f9a392c52cf24057b20aec4c331461761 100644 (file)
@@ -1567,28 +1567,10 @@ static void config_oa_regs(struct drm_i915_private *dev_priv,
        }
 }
 
-static int hsw_enable_metric_set(struct i915_perf_stream *stream)
+static void delay_after_mux(void)
 {
-       struct drm_i915_private *dev_priv = stream->dev_priv;
-       const struct i915_oa_config *oa_config = stream->oa_config;
-
-       /* PRM:
-        *
-        * OA unit is using “crclk” for its functionality. When trunk
-        * level clock gating takes place, OA clock would be gated,
-        * unable to count the events from non-render clock domain.
-        * Render clock gating must be disabled when OA is enabled to
-        * count the events from non-render domain. Unit level clock
-        * gating for RCS should also be disabled.
-        */
-       I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
-                                   ~GEN7_DOP_CLOCK_GATE_ENABLE));
-       I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) |
-                                 GEN6_CSUNIT_CLOCK_GATE_DISABLE));
-
-       config_oa_regs(dev_priv, oa_config->mux_regs, oa_config->mux_regs_len);
-
-       /* It apparently takes a fairly long time for a new MUX
+       /*
+        * It apparently takes a fairly long time for a new MUX
         * configuration to be be applied after these register writes.
         * This delay duration was derived empirically based on the
         * render_basic config but hopefully it covers the maximum
@@ -1610,6 +1592,30 @@ static int hsw_enable_metric_set(struct i915_perf_stream *stream)
         * a delay at this location would mitigate any invalid reports.
         */
        usleep_range(15000, 20000);
+}
+
+static int hsw_enable_metric_set(struct i915_perf_stream *stream)
+{
+       struct drm_i915_private *dev_priv = stream->dev_priv;
+       const struct i915_oa_config *oa_config = stream->oa_config;
+
+       /*
+        * PRM:
+        *
+        * OA unit is using “crclk” for its functionality. When trunk
+        * level clock gating takes place, OA clock would be gated,
+        * unable to count the events from non-render clock domain.
+        * Render clock gating must be disabled when OA is enabled to
+        * count the events from non-render domain. Unit level clock
+        * gating for RCS should also be disabled.
+        */
+       I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
+                                   ~GEN7_DOP_CLOCK_GATE_ENABLE));
+       I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) |
+                                 GEN6_CSUNIT_CLOCK_GATE_DISABLE));
+
+       config_oa_regs(dev_priv, oa_config->mux_regs, oa_config->mux_regs_len);
+       delay_after_mux();
 
        config_oa_regs(dev_priv, oa_config->b_counter_regs,
                       oa_config->b_counter_regs_len);
@@ -1835,6 +1841,7 @@ static int gen8_enable_metric_set(struct i915_perf_stream *stream)
                return ret;
 
        config_oa_regs(dev_priv, oa_config->mux_regs, oa_config->mux_regs_len);
+       delay_after_mux();
 
        config_oa_regs(dev_priv, oa_config->b_counter_regs,
                       oa_config->b_counter_regs_len);
@@ -2515,6 +2522,9 @@ static int i915_perf_release(struct inode *inode, struct file *file)
        i915_perf_destroy_locked(stream);
        mutex_unlock(&dev_priv->perf.lock);
 
+       /* Release the reference the perf stream kept on the driver. */
+       drm_dev_put(&dev_priv->drm);
+
        return 0;
 }
 
@@ -2650,6 +2660,11 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv,
        if (!(param->flags & I915_PERF_FLAG_DISABLED))
                i915_perf_enable_locked(stream);
 
+       /* Take a reference on the driver that will be kept with stream_fd
+        * until its release.
+        */
+       drm_dev_get(&dev_priv->drm);
+
        return stream_fd;
 
 err_open:
@@ -3477,9 +3492,13 @@ void i915_perf_init(struct drm_i915_private *dev_priv)
                        dev_priv->perf.oa.ops.enable_metric_set = gen8_enable_metric_set;
                        dev_priv->perf.oa.ops.disable_metric_set = gen10_disable_metric_set;
 
-                       dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128;
-                       dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de;
-
+                       if (IS_GEN(dev_priv, 10)) {
+                               dev_priv->perf.oa.ctx_oactxctrl_offset = 0x128;
+                               dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de;
+                       } else {
+                               dev_priv->perf.oa.ctx_oactxctrl_offset = 0x124;
+                               dev_priv->perf.oa.ctx_flexeu0_offset = 0x78e;
+                       }
                        dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16);
                }
        }
index f4ce643b3bc3ea00ff563979de1e112b2315dac0..cce426b23a240a8a30449b9a1b220c0de8ce92e3 100644 (file)
 /* watermark/fifo updates */
 
 TRACE_EVENT(intel_pipe_enable,
-           TP_PROTO(struct drm_i915_private *dev_priv, enum pipe pipe),
-           TP_ARGS(dev_priv, pipe),
+           TP_PROTO(struct intel_crtc *crtc),
+           TP_ARGS(crtc),
 
            TP_STRUCT__entry(
                             __array(u32, frame, 3)
                             __array(u32, scanline, 3)
                             __field(enum pipe, pipe)
                             ),
-
            TP_fast_assign(
-                          enum pipe _pipe;
-                          for_each_pipe(dev_priv, _pipe) {
-                                  __entry->frame[_pipe] =
-                                          dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, _pipe);
-                                  __entry->scanline[_pipe] =
-                                          intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, _pipe));
+                          struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+                          struct intel_crtc *it__;
+                          for_each_intel_crtc(&dev_priv->drm, it__) {
+                                  __entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
+                                  __entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
                           }
-                          __entry->pipe = pipe;
+                          __entry->pipe = crtc->pipe;
                           ),
 
            TP_printk("pipe %c enable, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
@@ -49,8 +47,8 @@ TRACE_EVENT(intel_pipe_enable,
 );
 
 TRACE_EVENT(intel_pipe_disable,
-           TP_PROTO(struct drm_i915_private *dev_priv, enum pipe pipe),
-           TP_ARGS(dev_priv, pipe),
+           TP_PROTO(struct intel_crtc *crtc),
+           TP_ARGS(crtc),
 
            TP_STRUCT__entry(
                             __array(u32, frame, 3)
@@ -59,14 +57,13 @@ TRACE_EVENT(intel_pipe_disable,
                             ),
 
            TP_fast_assign(
-                          enum pipe _pipe;
-                          for_each_pipe(dev_priv, _pipe) {
-                                  __entry->frame[_pipe] =
-                                          dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, _pipe);
-                                  __entry->scanline[_pipe] =
-                                          intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, _pipe));
+                          struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+                          struct intel_crtc *it__;
+                          for_each_intel_crtc(&dev_priv->drm, it__) {
+                                  __entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
+                                  __entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
                           }
-                          __entry->pipe = pipe;
+                          __entry->pipe = crtc->pipe;
                           ),
 
            TP_printk("pipe %c disable, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
@@ -89,8 +86,7 @@ TRACE_EVENT(intel_pipe_crc,
 
            TP_fast_assign(
                           __entry->pipe = crtc->pipe;
-                          __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
-                                                                                      crtc->pipe);
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
                           __entry->scanline = intel_get_crtc_scanline(crtc);
                           memcpy(__entry->crcs, crcs, sizeof(__entry->crcs));
                           ),
@@ -112,9 +108,10 @@ TRACE_EVENT(intel_cpu_fifo_underrun,
                             ),
 
            TP_fast_assign(
+                           struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
                           __entry->pipe = pipe;
-                          __entry->frame = dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, pipe);
-                          __entry->scanline = intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, pipe));
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
+                          __entry->scanline = intel_get_crtc_scanline(crtc);
                           ),
 
            TP_printk("pipe %c, frame=%u, scanline=%u",
@@ -134,9 +131,10 @@ TRACE_EVENT(intel_pch_fifo_underrun,
 
            TP_fast_assign(
                           enum pipe pipe = pch_transcoder;
+                          struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
                           __entry->pipe = pipe;
-                          __entry->frame = dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, pipe);
-                          __entry->scanline = intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, pipe));
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
+                          __entry->scanline = intel_get_crtc_scanline(crtc);
                           ),
 
            TP_printk("pch transcoder %c, frame=%u, scanline=%u",
@@ -156,12 +154,10 @@ TRACE_EVENT(intel_memory_cxsr,
                             ),
 
            TP_fast_assign(
-                          enum pipe pipe;
-                          for_each_pipe(dev_priv, pipe) {
-                                  __entry->frame[pipe] =
-                                          dev_priv->drm.driver->get_vblank_counter(&dev_priv->drm, pipe);
-                                  __entry->scanline[pipe] =
-                                          intel_get_crtc_scanline(intel_get_crtc_for_pipe(dev_priv, pipe));
+                          struct intel_crtc *crtc;
+                          for_each_intel_crtc(&dev_priv->drm, crtc) {
+                                  __entry->frame[crtc->pipe] = intel_crtc_get_vblank_counter(crtc);
+                                  __entry->scanline[crtc->pipe] = intel_get_crtc_scanline(crtc);
                           }
                           __entry->old = old;
                           __entry->new = new;
@@ -198,8 +194,7 @@ TRACE_EVENT(g4x_wm,
 
            TP_fast_assign(
                           __entry->pipe = crtc->pipe;
-                          __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
-                                                                                      crtc->pipe);
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
                           __entry->scanline = intel_get_crtc_scanline(crtc);
                           __entry->primary = wm->pipe[crtc->pipe].plane[PLANE_PRIMARY];
                           __entry->sprite = wm->pipe[crtc->pipe].plane[PLANE_SPRITE0];
@@ -243,8 +238,7 @@ TRACE_EVENT(vlv_wm,
 
            TP_fast_assign(
                           __entry->pipe = crtc->pipe;
-                          __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
-                                                                                      crtc->pipe);
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
                           __entry->scanline = intel_get_crtc_scanline(crtc);
                           __entry->level = wm->level;
                           __entry->cxsr = wm->cxsr;
@@ -278,8 +272,7 @@ TRACE_EVENT(vlv_fifo_size,
 
            TP_fast_assign(
                           __entry->pipe = crtc->pipe;
-                          __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
-                                                                                      crtc->pipe);
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
                           __entry->scanline = intel_get_crtc_scanline(crtc);
                           __entry->sprite0_start = sprite0_start;
                           __entry->sprite1_start = sprite1_start;
@@ -310,8 +303,7 @@ TRACE_EVENT(intel_update_plane,
            TP_fast_assign(
                           __entry->pipe = crtc->pipe;
                           __entry->name = plane->name;
-                          __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
-                                                                                      crtc->pipe);
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
                           __entry->scanline = intel_get_crtc_scanline(crtc);
                           memcpy(__entry->src, &plane->state->src, sizeof(__entry->src));
                           memcpy(__entry->dst, &plane->state->dst, sizeof(__entry->dst));
@@ -338,8 +330,7 @@ TRACE_EVENT(intel_disable_plane,
            TP_fast_assign(
                           __entry->pipe = crtc->pipe;
                           __entry->name = plane->name;
-                          __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
-                                                                                      crtc->pipe);
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
                           __entry->scanline = intel_get_crtc_scanline(crtc);
                           ),
 
@@ -364,8 +355,7 @@ TRACE_EVENT(i915_pipe_update_start,
 
            TP_fast_assign(
                           __entry->pipe = crtc->pipe;
-                          __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
-                                                                                      crtc->pipe);
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
                           __entry->scanline = intel_get_crtc_scanline(crtc);
                           __entry->min = crtc->debug.min_vbl;
                           __entry->max = crtc->debug.max_vbl;
index 94d3992b599d24a88c473839e831ab81f903427b..724627afdedc2ef70430e2bee94518ad8c0e09c8 100644 (file)
@@ -101,6 +101,9 @@ static struct _balloon_info_ bl_info;
 static void vgt_deballoon_space(struct i915_ggtt *ggtt,
                                struct drm_mm_node *node)
 {
+       if (!drm_mm_node_allocated(node))
+               return;
+
        DRM_DEBUG_DRIVER("deballoon space: range [0x%llx - 0x%llx] %llu KiB.\n",
                         node->start,
                         node->start + node->size,
index 1d58f7ec5d84b29229854d50df63abfc2683f357..f11979879e7bc094ccb4a0274e49eda960180a28 100644 (file)
@@ -829,7 +829,7 @@ struct intel_crtc_state {
 
        /*
         * Frequence the dpll for the port should run at. Differs from the
-        * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
+        * adjusted dotclock e.g. for DP or 10/12bpc hdmi mode. This is also
         * already multiplied by pixel_multiplier.
         */
        int port_clock;
index 502c54428570c7a75130781862bbe308c3fac0e9..8d1aebc3e8574652153553f82370f7a210d14c84 100644 (file)
@@ -221,13 +221,11 @@ __untrack_all_wakerefs(struct intel_runtime_pm_debug *debug,
 static void
 dump_and_free_wakeref_tracking(struct intel_runtime_pm_debug *debug)
 {
-       struct drm_printer p;
+       if (debug->count) {
+               struct drm_printer p = drm_debug_printer("i915");
 
-       if (!debug->count)
-               return;
-
-       p = drm_debug_printer("i915");
-       __print_intel_runtime_pm_wakeref(&p, debug);
+               __print_intel_runtime_pm_wakeref(&p, debug);
+       }
 
        kfree(debug->owners);
 }
index 9cbb2ebf575b5f610c27535728c4f9fd79c25ff4..38275310b196dbea82402d3b49648070049c1611 100644 (file)
@@ -65,6 +65,21 @@ intel_wakeref_get(struct intel_runtime_pm *rpm,
        return 0;
 }
 
+/**
+ * intel_wakeref_get_if_in_use: Acquire the wakeref
+ * @wf: the wakeref
+ *
+ * Acquire a hold on the wakeref, but only if the wakeref is already
+ * active.
+ *
+ * Returns: true if the wakeref was acquired, false otherwise.
+ */
+static inline bool
+intel_wakeref_get_if_active(struct intel_wakeref *wf)
+{
+       return atomic_inc_not_zero(&wf->count);
+}
+
 /**
  * intel_wakeref_put: Release the wakeref
  * @i915: the drm_i915_private device
index e9f9e9fb9b1773a1a40d6b1e9a8a063a10e8f530..6381652a8829127800300e16a118400c3535029b 100644 (file)
@@ -656,10 +656,9 @@ static int ingenic_drm_probe(struct platform_device *pdev)
                return ret;
        }
 
-       if (panel) {
+       if (panel)
                bridge = devm_drm_panel_bridge_add(dev, panel,
-                                                  DRM_MODE_CONNECTOR_Unknown);
-       }
+                                                  DRM_MODE_CONNECTOR_DPI);
 
        priv->dma_hwdesc = dma_alloc_coherent(dev, sizeof(*priv->dma_hwdesc),
                                              &priv->dma_hwdesc_phys,
index 477c0f766663de92dfd4bf263e7e374896eef73a..b609dc030d6ca906f61ffd8bba47dce8bf1e644d 100644 (file)
@@ -342,7 +342,7 @@ int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, s64 timeout_ns)
        timeout = drm_timeout_abs_to_jiffies(timeout_ns);
 
        ret = drm_gem_reservation_object_wait(file, handle, write, timeout);
-       if (ret == 0)
+       if (ret == -ETIME)
                ret = timeout ? -ETIMEDOUT : -EBUSY;
 
        return ret;
index 95fdbd0fbcace01f26e3c1c393210ba09e60a952..945bc20f1d33f0d5aada0a7d9d7c0e52fb15c28a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
 
 #include "mtk_drm_crtc.h"
 #include "mtk_drm_ddp.h"
@@ -213,6 +214,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
        struct mtk_drm_private *private = drm->dev_private;
        struct platform_device *pdev;
        struct device_node *np;
+       struct device *dma_dev;
        int ret;
 
        if (!iommu_present(&platform_bus_type))
@@ -275,7 +277,29 @@ static int mtk_drm_kms_init(struct drm_device *drm)
                goto err_component_unbind;
        }
 
-       private->dma_dev = &pdev->dev;
+       dma_dev = &pdev->dev;
+       private->dma_dev = dma_dev;
+
+       /*
+        * Configure the DMA segment size to make sure we get contiguous IOVA
+        * when importing PRIME buffers.
+        */
+       if (!dma_dev->dma_parms) {
+               private->dma_parms_allocated = true;
+               dma_dev->dma_parms =
+                       devm_kzalloc(drm->dev, sizeof(*dma_dev->dma_parms),
+                                    GFP_KERNEL);
+       }
+       if (!dma_dev->dma_parms) {
+               ret = -ENOMEM;
+               goto err_component_unbind;
+       }
+
+       ret = dma_set_max_seg_size(dma_dev, (unsigned int)DMA_BIT_MASK(32));
+       if (ret) {
+               dev_err(dma_dev, "Failed to set DMA segment size\n");
+               goto err_unset_dma_parms;
+       }
 
        /*
         * We don't use the drm_irq_install() helpers provided by the DRM
@@ -285,13 +309,16 @@ static int mtk_drm_kms_init(struct drm_device *drm)
        drm->irq_enabled = true;
        ret = drm_vblank_init(drm, MAX_CRTC);
        if (ret < 0)
-               goto err_component_unbind;
+               goto err_unset_dma_parms;
 
        drm_kms_helper_poll_init(drm);
        drm_mode_config_reset(drm);
 
        return 0;
 
+err_unset_dma_parms:
+       if (private->dma_parms_allocated)
+               dma_dev->dma_parms = NULL;
 err_component_unbind:
        component_unbind_all(drm->dev, drm);
 err_config_cleanup:
@@ -302,9 +329,14 @@ err_config_cleanup:
 
 static void mtk_drm_kms_deinit(struct drm_device *drm)
 {
+       struct mtk_drm_private *private = drm->dev_private;
+
        drm_kms_helper_poll_fini(drm);
        drm_atomic_helper_shutdown(drm);
 
+       if (private->dma_parms_allocated)
+               private->dma_dev->dma_parms = NULL;
+
        component_unbind_all(drm->dev, drm);
        drm_mode_config_cleanup(drm);
 }
@@ -320,6 +352,18 @@ static const struct file_operations mtk_drm_fops = {
        .compat_ioctl = drm_compat_ioctl,
 };
 
+/*
+ * We need to override this because the device used to import the memory is
+ * not dev->dev, as drm_gem_prime_import() expects.
+ */
+struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
+                                               struct dma_buf *dma_buf)
+{
+       struct mtk_drm_private *private = dev->dev_private;
+
+       return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
+}
+
 static struct drm_driver mtk_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
                           DRIVER_ATOMIC,
@@ -331,7 +375,7 @@ static struct drm_driver mtk_drm_driver = {
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = drm_gem_prime_export,
-       .gem_prime_import = drm_gem_prime_import,
+       .gem_prime_import = mtk_drm_gem_prime_import,
        .gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
        .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
        .gem_prime_mmap = mtk_drm_gem_mmap_buf,
@@ -524,12 +568,15 @@ static int mtk_drm_probe(struct platform_device *pdev)
                        comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
                        if (!comp) {
                                ret = -ENOMEM;
+                               of_node_put(node);
                                goto err_node;
                        }
 
                        ret = mtk_ddp_comp_init(dev, node, comp, comp_id, NULL);
-                       if (ret)
+                       if (ret) {
+                               of_node_put(node);
                                goto err_node;
+                       }
 
                        private->ddp_comp[comp_id] = comp;
                }
index 598ff3e7044652ef19dfe71420354e0f18b058c4..e03fea12ff5988de393ee6fc2165dce7189700c9 100644 (file)
@@ -51,6 +51,8 @@ struct mtk_drm_private {
        } commit;
 
        struct drm_atomic_state *suspend_state;
+
+       bool dma_parms_allocated;
 };
 
 extern struct platform_driver mtk_ddp_driver;
index 1671db47aa579090d48eb18f0ceabf3aa530219f..e9c55d1d6c044273a63e53bd0fbbf674497a7506 100644 (file)
@@ -59,6 +59,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
                case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
                        if (priv->lastctx == ctx)
                                break;
+                       /* fall-thru */
                case MSM_SUBMIT_CMD_BUF:
                        /* copy commands into RB: */
                        obj = submit->bos[submit->cmd[i].idx].obj;
@@ -149,6 +150,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
                case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
                        if (priv->lastctx == ctx)
                                break;
+                       /* fall-thru */
                case MSM_SUBMIT_CMD_BUF:
                        OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
                        OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
index be39cf01e51ecf73cf28bde06c3f6b6480207c80..dc8ec2c94301b67f057f918e6d7bdb36722938d3 100644 (file)
@@ -115,6 +115,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
                case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
                        if (priv->lastctx == ctx)
                                break;
+                       /* fall-thru */
                case MSM_SUBMIT_CMD_BUF:
                        OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
                        OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
index 9acbbc0f323240e641087a158bbea5d4c9fef582..048c8be426f3254c37294cca600a0714d1fd84cf 100644 (file)
@@ -428,6 +428,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
                        /* ignore if there has not been a ctx switch: */
                        if (priv->lastctx == ctx)
                                break;
+                       /* fall-thru */
                case MSM_SUBMIT_CMD_BUF:
                        OUT_PKT3(ring, adreno_is_a430(adreno_gpu) ?
                                CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2);
index 0e2f74163a165040dd4c468c502bb6a1e832f0be..0aa8a12c99520b6f3c110869a7edb3eaa82cb404 100644 (file)
@@ -2221,8 +2221,6 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
        if (ret)
                goto fail;
 
-       spin_lock_init(&dpu_enc->enc_spinlock);
-
        atomic_set(&dpu_enc->frame_done_timeout_ms, 0);
        timer_setup(&dpu_enc->frame_done_timer,
                        dpu_encoder_frame_done_timeout, 0);
@@ -2276,6 +2274,7 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
 
        drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs);
 
+       spin_lock_init(&dpu_enc->enc_spinlock);
        dpu_enc->enabled = false;
 
        return &dpu_enc->base;
index ff14555372d09dec06016da145c60db6a569fe09..78d5fa230c165e9f7a0c784902e0189ee30afc78 100644 (file)
@@ -439,6 +439,18 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
        mdp5_crtc->enabled = false;
 }
 
+static void mdp5_crtc_vblank_on(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+       struct mdp5_interface *intf = mdp5_cstate->pipeline.intf;
+       u32 count;
+
+       count = intf->mode == MDP5_INTF_DSI_MODE_COMMAND ? 0 : 0xffffffff;
+       drm_crtc_set_max_vblank_count(crtc, count);
+
+       drm_crtc_vblank_on(crtc);
+}
+
 static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_state)
 {
@@ -475,7 +487,7 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
        }
 
        /* Restore vblank irq handling after power is enabled */
-       drm_crtc_vblank_on(crtc);
+       mdp5_crtc_vblank_on(crtc);
 
        mdp5_crtc_mode_set_nofb(crtc);
 
@@ -1028,6 +1040,8 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc)
                mdp5_crtc_destroy_state(crtc, crtc->state);
 
        __drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base);
+
+       drm_crtc_vblank_reset(crtc);
 }
 
 static const struct drm_crtc_funcs mdp5_crtc_funcs = {
index 4a60f5fca6b0bdc90d0fdf758c9196a26381120a..fec6ef1ae3b9839a5b5916d15b6f4a58b5e05692 100644 (file)
@@ -740,7 +740,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
        dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos;
        dev->driver->get_scanout_position = mdp5_get_scanoutpos;
        dev->driver->get_vblank_counter = mdp5_get_vblank_counter;
-       dev->max_vblank_count = 0xffffffff;
+       dev->max_vblank_count = 0; /* max_vblank_count is set on each CRTC */
        dev->vblank_disable_immediate = true;
 
        return kms;
index ab64ab470de742764b36cc338c07c52bd7e39f10..c356f5ccf25360627a62e0e3feb89f7511cbc8fd 100644 (file)
@@ -619,7 +619,7 @@ static int context_init(struct drm_device *dev, struct drm_file *file)
 
        msm_submitqueue_init(dev, ctx);
 
-       ctx->aspace = priv->gpu->aspace;
+       ctx->aspace = priv->gpu ? priv->gpu->aspace : NULL;
        file->driver_priv = ctx;
 
        return 0;
@@ -1279,7 +1279,8 @@ static int add_gpu_components(struct device *dev,
        if (!np)
                return 0;
 
-       drm_of_component_match_add(dev, matchptr, compare_of, np);
+       if (of_device_is_available(np))
+               drm_of_component_match_add(dev, matchptr, compare_of, np);
 
        of_node_put(np);
 
index 8b78554cfde3ed9392297eacb07295273ee9b37d..8cf6362e64bfeb314b2fcc222d16f5394964155e 100644 (file)
@@ -32,6 +32,46 @@ static bool use_pages(struct drm_gem_object *obj)
        return !msm_obj->vram_node;
 }
 
+/*
+ * Cache sync.. this is a bit over-complicated, to fit dma-mapping
+ * API.  Really GPU cache is out of scope here (handled on cmdstream)
+ * and all we need to do is invalidate newly allocated pages before
+ * mapping to CPU as uncached/writecombine.
+ *
+ * On top of this, we have the added headache, that depending on
+ * display generation, the display's iommu may be wired up to either
+ * the toplevel drm device (mdss), or to the mdp sub-node, meaning
+ * that here we either have dma-direct or iommu ops.
+ *
+ * Let this be a cautionary tail of abstraction gone wrong.
+ */
+
+static void sync_for_device(struct msm_gem_object *msm_obj)
+{
+       struct device *dev = msm_obj->base.dev->dev;
+
+       if (get_dma_ops(dev)) {
+               dma_sync_sg_for_device(dev, msm_obj->sgt->sgl,
+                       msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+       } else {
+               dma_map_sg(dev, msm_obj->sgt->sgl,
+                       msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+       }
+}
+
+static void sync_for_cpu(struct msm_gem_object *msm_obj)
+{
+       struct device *dev = msm_obj->base.dev->dev;
+
+       if (get_dma_ops(dev)) {
+               dma_sync_sg_for_cpu(dev, msm_obj->sgt->sgl,
+                       msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+       } else {
+               dma_unmap_sg(dev, msm_obj->sgt->sgl,
+                       msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+       }
+}
+
 /* allocate pages from VRAM carveout, used when no IOMMU: */
 static struct page **get_pages_vram(struct drm_gem_object *obj, int npages)
 {
@@ -97,8 +137,7 @@ static struct page **get_pages(struct drm_gem_object *obj)
                 * because display controller, GPU, etc. are not coherent:
                 */
                if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED))
-                       dma_map_sg(dev->dev, msm_obj->sgt->sgl,
-                                       msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+                       sync_for_device(msm_obj);
        }
 
        return msm_obj->pages;
@@ -127,9 +166,7 @@ static void put_pages(struct drm_gem_object *obj)
                         * GPU, etc. are not coherent:
                         */
                        if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED))
-                               dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl,
-                                            msm_obj->sgt->nents,
-                                            DMA_BIDIRECTIONAL);
+                               sync_for_cpu(msm_obj);
 
                        sg_free_table(msm_obj->sgt);
                        kfree(msm_obj->sgt);
index 8497768f1b4102ac76d7e5d45257aec2bb72a82b..5c36c75232e6d0364f4d90419b7a7010da8985e9 100644 (file)
@@ -771,16 +771,20 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
        struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
        int slots;
 
-       /* When restoring duplicated states, we need to make sure that the
-        * bw remains the same and avoid recalculating it, as the connector's
-        * bpc may have changed after the state was duplicated
-        */
-       if (!state->duplicated)
-               asyh->dp.pbn =
-                       drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
-                                            connector->display_info.bpc * 3);
+       if (crtc_state->mode_changed || crtc_state->connectors_changed) {
+               /*
+                * When restoring duplicated states, we need to make sure that
+                * the bw remains the same and avoid recalculating it, as the
+                * connector's bpc may have changed after the state was
+                * duplicated
+                */
+               if (!state->duplicated) {
+                       const int bpp = connector->display_info.bpc * 3;
+                       const int clock = crtc_state->adjusted_mode.clock;
+
+                       asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
+               }
 
-       if (drm_atomic_crtc_needs_modeset(crtc_state)) {
                slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
                                                      mstc->port,
                                                      asyh->dp.pbn);
index 8c92374afcf227980d659748052fad072173b773..a835cebb6d901103d9f46e0d90286b52b08bd2c6 100644 (file)
@@ -475,6 +475,47 @@ nouveau_svm_fault_cache(struct nouveau_svm *svm,
                fault->inst, fault->addr, fault->access);
 }
 
+static inline bool
+nouveau_range_done(struct hmm_range *range)
+{
+       bool ret = hmm_range_valid(range);
+
+       hmm_range_unregister(range);
+       return ret;
+}
+
+static int
+nouveau_range_fault(struct hmm_mirror *mirror, struct hmm_range *range)
+{
+       long ret;
+
+       range->default_flags = 0;
+       range->pfn_flags_mask = -1UL;
+
+       ret = hmm_range_register(range, mirror,
+                                range->start, range->end,
+                                PAGE_SHIFT);
+       if (ret) {
+               up_read(&range->vma->vm_mm->mmap_sem);
+               return (int)ret;
+       }
+
+       if (!hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT)) {
+               up_read(&range->vma->vm_mm->mmap_sem);
+               return -EAGAIN;
+       }
+
+       ret = hmm_range_fault(range, true);
+       if (ret <= 0) {
+               if (ret == 0)
+                       ret = -EBUSY;
+               up_read(&range->vma->vm_mm->mmap_sem);
+               hmm_range_unregister(range);
+               return ret;
+       }
+       return 0;
+}
+
 static int
 nouveau_svm_fault(struct nvif_notify *notify)
 {
@@ -649,10 +690,10 @@ nouveau_svm_fault(struct nvif_notify *notify)
                range.values = nouveau_svm_pfn_values;
                range.pfn_shift = NVIF_VMM_PFNMAP_V0_ADDR_SHIFT;
 again:
-               ret = hmm_vma_fault(&svmm->mirror, &range, true);
+               ret = nouveau_range_fault(&svmm->mirror, &range);
                if (ret == 0) {
                        mutex_lock(&svmm->mutex);
-                       if (!hmm_vma_range_done(&range)) {
+                       if (!nouveau_range_done(&range)) {
                                mutex_unlock(&svmm->mutex);
                                goto again;
                        }
@@ -666,8 +707,8 @@ again:
                                                NULL);
                        svmm->vmm->vmm.object.client->super = false;
                        mutex_unlock(&svmm->mutex);
+                       up_read(&svmm->mm->mmap_sem);
                }
-               up_read(&svmm->mm->mmap_sem);
 
                /* Cancel any faults in the window whose pages didn't manage
                 * to keep their valid bit, or stay writeable when required.
index b4e7404fe660e24937bde1e518533feecad376d9..a11637b0f6ccf43cc39c417dc64a8fb349815a22 100644 (file)
@@ -40,8 +40,7 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                u8 *ptr = msg->buf;
 
                while (remaining) {
-                       u8 cnt = (remaining > 16) ? 16 : remaining;
-                       u8 cmd;
+                       u8 cnt, retries, cmd;
 
                        if (msg->flags & I2C_M_RD)
                                cmd = 1;
@@ -51,10 +50,19 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                        if (mcnt || remaining > 16)
                                cmd |= 4; /* MOT */
 
-                       ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, &cnt);
-                       if (ret < 0) {
-                               nvkm_i2c_aux_release(aux);
-                               return ret;
+                       for (retries = 0, cnt = 0;
+                            retries < 32 && !cnt;
+                            retries++) {
+                               cnt = min_t(u8, remaining, 16);
+                               ret = aux->func->xfer(aux, true, cmd,
+                                                     msg->addr, ptr, &cnt);
+                               if (ret < 0)
+                                       goto out;
+                       }
+                       if (!cnt) {
+                               AUX_TRACE(aux, "no data after 32 retries");
+                               ret = -EIO;
+                               goto out;
                        }
 
                        ptr += cnt;
@@ -64,8 +72,10 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                msg++;
        }
 
+       ret = num;
+out:
        nvkm_i2c_aux_release(aux);
-       return num;
+       return ret;
 }
 
 static u32
index 84a2f243ed9bd16a59bf752f1f01602c72519c03..4695f1c8e33f4f32219102ac569462bb7516a1ea 100644 (file)
@@ -190,6 +190,9 @@ MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin");
 MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin");
 MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin");
 MODULE_FIRMWARE("nvidia/gp104/acr/bl.bin");
 MODULE_FIRMWARE("nvidia/gp104/acr/unload_bl.bin");
 MODULE_FIRMWARE("nvidia/gp104/acr/ucode_load.bin");
@@ -210,6 +213,9 @@ MODULE_FIRMWARE("nvidia/gp104/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin");
 MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin");
 MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin");
 MODULE_FIRMWARE("nvidia/gp106/acr/bl.bin");
 MODULE_FIRMWARE("nvidia/gp106/acr/unload_bl.bin");
 MODULE_FIRMWARE("nvidia/gp106/acr/ucode_load.bin");
@@ -230,6 +236,9 @@ MODULE_FIRMWARE("nvidia/gp106/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin");
 MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin");
 MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin");
 MODULE_FIRMWARE("nvidia/gp107/acr/bl.bin");
 MODULE_FIRMWARE("nvidia/gp107/acr/unload_bl.bin");
 MODULE_FIRMWARE("nvidia/gp107/acr/ucode_load.bin");
@@ -250,3 +259,6 @@ MODULE_FIRMWARE("nvidia/gp107/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin");
 MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin");
 MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin");
+MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin");
index de0f882f0f7b07d7b591df64b38f14c4d6a6fac0..14b41de44ebcda9a6c6ebda7de21817b22de2a90 100644 (file)
@@ -4,6 +4,7 @@
  * Author: Archit Taneja <archit@ti.com>
  */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -20,7 +21,8 @@ int omapdss_device_init_output(struct omap_dss_device *out)
 {
        struct device_node *remote_node;
 
-       remote_node = of_graph_get_remote_node(out->dev->of_node, 0, 0);
+       remote_node = of_graph_get_remote_node(out->dev->of_node,
+                                              ffs(out->of_ports) - 1, 0);
        if (!remote_node) {
                dev_dbg(out->dev, "failed to find video sink\n");
                return 0;
index 288c59dae56ad9326d3e50699deb8ec0445d071d..1bad0a2cc5c6362045c29439bc2a3e2cf9d9ccc1 100644 (file)
@@ -669,7 +669,7 @@ static int pdev_probe(struct platform_device *pdev)
        if (omapdss_is_initialized() == false)
                return -EPROBE_DEFER;
 
-       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
        if (ret) {
                dev_err(&pdev->dev, "Failed to set the DMA mask\n");
                return ret;
index f33e349c4ec5b4f48db8edd7b69d11f0e4a3c83a..952201c6d821d719f6520c83462923918ebf31f4 100644 (file)
@@ -59,6 +59,11 @@ module_param_named(num_heads, qxl_num_crtc, int, 0400);
 static struct drm_driver qxl_driver;
 static struct pci_driver qxl_pci_driver;
 
+static bool is_vga(struct pci_dev *pdev)
+{
+       return pdev->class == PCI_CLASS_DISPLAY_VGA << 8;
+}
+
 static int
 qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -83,9 +88,17 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ret)
                goto disable_pci;
 
+       if (is_vga(pdev)) {
+               ret = vga_get_interruptible(pdev, VGA_RSRC_LEGACY_IO);
+               if (ret) {
+                       DRM_ERROR("can't get legacy vga ioports\n");
+                       goto disable_pci;
+               }
+       }
+
        ret = qxl_device_init(qdev, &qxl_driver, pdev);
        if (ret)
-               goto disable_pci;
+               goto put_vga;
 
        ret = qxl_modeset_init(qdev);
        if (ret)
@@ -105,6 +118,9 @@ modeset_cleanup:
        qxl_modeset_fini(qdev);
 unload:
        qxl_device_fini(qdev);
+put_vga:
+       if (is_vga(pdev))
+               vga_put(pdev, VGA_RSRC_LEGACY_IO);
 disable_pci:
        pci_disable_device(pdev);
 free_dev:
@@ -122,6 +138,8 @@ qxl_pci_remove(struct pci_dev *pdev)
 
        qxl_modeset_fini(qdev);
        qxl_device_fini(qdev);
+       if (is_vga(pdev))
+               vga_put(pdev, VGA_RSRC_LEGACY_IO);
 
        dev->dev_private = NULL;
        kfree(qdev);
index 1c62578590f462fbc4ab8fb1e102c6bfef57b8f5..082d02c840249c49e79de11465feb44e3fe28950 100644 (file)
@@ -673,10 +673,8 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
 
        /* Locate the companion LVDS encoder for dual-link operation, if any. */
        companion = of_parse_phandle(dev->of_node, "renesas,companion", 0);
-       if (!companion) {
-               dev_err(dev, "Companion LVDS encoder not found\n");
-               return -ENXIO;
-       }
+       if (!companion)
+               return 0;
 
        /*
         * Sanity check: the companion encoder must have the same compatible
index 95e5c517a15f766132981eebc148f488e13a4074..9aae3d8e99ef426743d21533f3b1168449a56fe5 100644 (file)
@@ -432,7 +432,7 @@ static int rockchip_dp_resume(struct device *dev)
 
 static const struct dev_pm_ops rockchip_dp_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
-       .suspend = rockchip_dp_suspend,
+       .suspend_late = rockchip_dp_suspend,
        .resume_early = rockchip_dp_resume,
 #endif
 };
index 35ddbec1375ae880bba180a4d7f46173b38e2ec2..671c90f34ede6ba6ed6eb40e3159243cf142e7be 100644 (file)
@@ -95,7 +95,7 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity)
        rmb(); /* for list_empty to work without lock */
 
        if (list_empty(&entity->list) ||
-           spsc_queue_peek(&entity->job_queue) == NULL)
+           spsc_queue_count(&entity->job_queue) == 0)
                return true;
 
        return false;
@@ -281,7 +281,7 @@ void drm_sched_entity_fini(struct drm_sched_entity *entity)
        /* Consumption of existing IBs wasn't completed. Forcefully
         * remove them here.
         */
-       if (spsc_queue_peek(&entity->job_queue)) {
+       if (spsc_queue_count(&entity->job_queue)) {
                if (sched) {
                        /* Park the kernel for a moment to make sure it isn't processing
                         * our enity.
index b45824ec7c8f2cb6eb70ea2dd24ea77246f7f09c..6d61a0eb5d64f00ee9c6adb6fabdc1ae40f9c507 100644 (file)
@@ -9,6 +9,13 @@
 
 #define cmdline_test(test)     selftest(test, test)
 
+cmdline_test(drm_cmdline_test_force_d_only)
+cmdline_test(drm_cmdline_test_force_D_only_dvi)
+cmdline_test(drm_cmdline_test_force_D_only_hdmi)
+cmdline_test(drm_cmdline_test_force_D_only_not_digital)
+cmdline_test(drm_cmdline_test_force_e_only)
+cmdline_test(drm_cmdline_test_margin_only)
+cmdline_test(drm_cmdline_test_interlace_only)
 cmdline_test(drm_cmdline_test_res)
 cmdline_test(drm_cmdline_test_res_missing_x)
 cmdline_test(drm_cmdline_test_res_missing_y)
index 14c96edb13dff89c49dce49a486752a5b3fb5129..013de9d27c35dcda2043a0e6f45082944d34fea8 100644 (file)
 
 static const struct drm_connector no_connector = {};
 
+static int drm_cmdline_test_force_e_only(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("e",
+                                                          &no_connector,
+                                                          &mode));
+       FAIL_ON(mode.specified);
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_ON);
+
+       return 0;
+}
+
+static int drm_cmdline_test_force_D_only_not_digital(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
+                                                          &no_connector,
+                                                          &mode));
+       FAIL_ON(mode.specified);
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_ON);
+
+       return 0;
+}
+
+static const struct drm_connector connector_hdmi = {
+       .connector_type = DRM_MODE_CONNECTOR_HDMIB,
+};
+
+static int drm_cmdline_test_force_D_only_hdmi(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
+                                                          &connector_hdmi,
+                                                          &mode));
+       FAIL_ON(mode.specified);
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
+
+       return 0;
+}
+
+static const struct drm_connector connector_dvi = {
+       .connector_type = DRM_MODE_CONNECTOR_DVII,
+};
+
+static int drm_cmdline_test_force_D_only_dvi(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
+                                                          &connector_dvi,
+                                                          &mode));
+       FAIL_ON(mode.specified);
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
+
+       return 0;
+}
+
+static int drm_cmdline_test_force_d_only(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(!drm_mode_parse_command_line_for_connector("d",
+                                                          &no_connector,
+                                                          &mode));
+       FAIL_ON(mode.specified);
+       FAIL_ON(mode.refresh_specified);
+       FAIL_ON(mode.bpp_specified);
+
+       FAIL_ON(mode.rb);
+       FAIL_ON(mode.cvt);
+       FAIL_ON(mode.interlace);
+       FAIL_ON(mode.margins);
+       FAIL_ON(mode.force != DRM_FORCE_OFF);
+
+       return 0;
+}
+
+static int drm_cmdline_test_margin_only(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(drm_mode_parse_command_line_for_connector("m",
+                                                         &no_connector,
+                                                         &mode));
+
+       return 0;
+}
+
+static int drm_cmdline_test_interlace_only(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(drm_mode_parse_command_line_for_connector("i",
+                                                         &no_connector,
+                                                         &mode));
+
+       return 0;
+}
+
 static int drm_cmdline_test_res(void *ignored)
 {
        struct drm_cmdline_mode mode = { };
index 64c43ee6bd92ffe01938afa69e9683e897e7fca6..df0cc8f46d7bdcc63578b30e0f97cb2f1e36f409 100644 (file)
@@ -314,6 +314,7 @@ static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
                /* R and B components are only 5 bits deep */
                val |= SUN4I_TCON0_FRM_CTL_MODE_R;
                val |= SUN4I_TCON0_FRM_CTL_MODE_B;
+               /* Fall through */
        case MEDIA_BUS_FMT_RGB666_1X18:
        case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
                /* Fall through: enable dithering */
index a1fc8b520985506a5f050af1d9d3eb2729f120ea..b889ad3e86e179fa8b3f404aaaa28855d97be21b 100644 (file)
@@ -993,6 +993,7 @@ static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
                        ret = sun6i_dsi_dcs_read(dsi, msg);
                        break;
                }
+               /* Else, fall through */
 
        default:
                ret = -EINVAL;
index 274cb955e2e19f496ed0be39c0610fe98609d645..bdcaa4c7168cfac967290347808bf08642dbe576 100644 (file)
@@ -126,8 +126,12 @@ int tegra_output_probe(struct tegra_output *output)
                                                       "nvidia,hpd-gpio", 0,
                                                       GPIOD_IN,
                                                       "HDMI hotplug detect");
-       if (IS_ERR(output->hpd_gpio))
-               return PTR_ERR(output->hpd_gpio);
+       if (IS_ERR(output->hpd_gpio)) {
+               if (PTR_ERR(output->hpd_gpio) != -ENOENT)
+                       return PTR_ERR(output->hpd_gpio);
+
+               output->hpd_gpio = NULL;
+       }
 
        if (output->hpd_gpio) {
                err = gpiod_to_irq(output->hpd_gpio);
index d594f7520b7b0c8f8609ffefbd374009995d3b2a..7d78e6deac89737276f6151ee934e9a6614deefd 100644 (file)
@@ -285,9 +285,13 @@ static int ttm_set_pages_caching(struct dma_pool *pool,
 
 static void __ttm_dma_free_page(struct dma_pool *pool, struct dma_page *d_page)
 {
+       unsigned long attrs = 0;
        dma_addr_t dma = d_page->dma;
        d_page->vaddr &= ~VADDR_FLAG_HUGE_POOL;
-       dma_free_coherent(pool->dev, pool->size, (void *)d_page->vaddr, dma);
+       if (pool->type & IS_HUGE)
+               attrs = DMA_ATTR_NO_WARN;
+
+       dma_free_attrs(pool->dev, pool->size, (void *)d_page->vaddr, dma, attrs);
 
        kfree(d_page);
        d_page = NULL;
index b2da31310d24c041750b92a96f91ddf8084978c7..09b526518f5a64b75288cc5738ae9ad7e6d0ff12 100644 (file)
@@ -204,6 +204,7 @@ int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
                .interruptible = false,
                .no_wait_gpu = false
        };
+       size_t max_segment;
 
        /* wtf swapping */
        if (bo->pages)
@@ -215,8 +216,13 @@ int virtio_gpu_object_get_sg_table(struct virtio_gpu_device *qdev,
        if (!bo->pages)
                goto out;
 
-       ret = sg_alloc_table_from_pages(bo->pages, pages, nr_pages, 0,
-                                       nr_pages << PAGE_SHIFT, GFP_KERNEL);
+       max_segment = virtio_max_dma_size(qdev->vdev);
+       max_segment &= PAGE_MASK;
+       if (max_segment > SCATTERLIST_MAX_SEGMENT)
+               max_segment = SCATTERLIST_MAX_SEGMENT;
+       ret = __sg_alloc_table_from_pages(bo->pages, pages, nr_pages, 0,
+                                         nr_pages << PAGE_SHIFT,
+                                         max_segment, GFP_KERNEL);
        if (ret)
                goto out;
        return 0;
index e4e09d47c5c0e001934a14a2df103e13a7a328aa..0af048d1a8156acfdb24af337f3b3479c4bb1004 100644 (file)
@@ -353,7 +353,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
                                     !!(HIGH_WORD(ecx) & MESSAGE_STATUS_HB));
                if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) == 0) {
                        kfree(reply);
-
+                       reply = NULL;
                        if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) {
                                /* A checkpoint occurred. Retry. */
                                continue;
@@ -377,7 +377,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
 
                if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
                        kfree(reply);
-
+                       reply = NULL;
                        if ((HIGH_WORD(ecx) & MESSAGE_STATUS_CPT) != 0) {
                                /* A checkpoint occurred. Retry. */
                                continue;
@@ -389,7 +389,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
                break;
        }
 
-       if (retries == RETRIES)
+       if (!reply)
                return -EINVAL;
 
        *msg_len = reply_len;
index 98bf694626f71a7e50318ca5b2f3aaf8f2eb6d4f..3a8c4a5971f70d51e7c21f0ecf2c4417c102bd80 100644 (file)
 #define A4_2WHEEL_MOUSE_HACK_7 0x01
 #define A4_2WHEEL_MOUSE_HACK_B8        0x02
 
+#define A4_WHEEL_ORIENTATION   (HID_UP_GENDESK | 0x000000b8)
+
 struct a4tech_sc {
        unsigned long quirks;
        unsigned int hw_wheel;
        __s32 delayed_value;
 };
 
+static int a4_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+                           struct hid_field *field, struct hid_usage *usage,
+                           unsigned long **bit, int *max)
+{
+       struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+
+       if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8 &&
+           usage->hid == A4_WHEEL_ORIENTATION) {
+               /*
+                * We do not want to have this usage mapped to anything as it's
+                * nonstandard and doesn't really behave like an HID report.
+                * It's only selecting the orientation (vertical/horizontal) of
+                * the previous mouse wheel report. The input_events will be
+                * generated once both reports are recorded in a4_event().
+                */
+               return -1;
+       }
+
+       return 0;
+
+}
+
 static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
@@ -52,8 +76,7 @@ static int a4_event(struct hid_device *hdev, struct hid_field *field,
        struct a4tech_sc *a4 = hid_get_drvdata(hdev);
        struct input_dev *input;
 
-       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
-                       !usage->type)
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
                return 0;
 
        input = field->hidinput->input;
@@ -64,7 +87,7 @@ static int a4_event(struct hid_device *hdev, struct hid_field *field,
                        return 1;
                }
 
-               if (usage->hid == 0x000100b8) {
+               if (usage->hid == A4_WHEEL_ORIENTATION) {
                        input_event(input, EV_REL, value ? REL_HWHEEL :
                                        REL_WHEEL, a4->delayed_value);
                        input_event(input, EV_REL, value ? REL_HWHEEL_HI_RES :
@@ -131,6 +154,7 @@ MODULE_DEVICE_TABLE(hid, a4_devices);
 static struct hid_driver a4_driver = {
        .name = "a4tech",
        .id_table = a4_devices,
+       .input_mapping = a4_input_mapping,
        .input_mapped = a4_input_mapped,
        .event = a4_event,
        .probe = a4_probe,
index 2310c96ccf4a6a9d85fb81bd36b8e83308d7930d..db1b55df0d1319c21b382fd8430e95f1821e3415 100644 (file)
@@ -1153,8 +1153,6 @@ static unsigned int cp2112_gpio_irq_startup(struct irq_data *d)
 
        INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
 
-       cp2112_gpio_direction_input(gc, d->hwirq);
-
        if (!dev->gpio_poll) {
                dev->gpio_poll = true;
                schedule_delayed_work(&dev->gpio_poll_worker, 0);
@@ -1204,6 +1202,12 @@ static int __maybe_unused cp2112_allocate_irq(struct cp2112_device *dev,
                return PTR_ERR(dev->desc[pin]);
        }
 
+       ret = cp2112_gpio_direction_input(&dev->gc, pin);
+       if (ret < 0) {
+               dev_err(dev->gc.parent, "Failed to set GPIO to input dir\n");
+               goto err_desc;
+       }
+
        ret = gpiochip_lock_as_irq(&dev->gc, pin);
        if (ret) {
                dev_err(dev->gc.parent, "Failed to lock GPIO as interrupt\n");
index b3d502421b79d327a5032f4429ff3d39327ea051..0a38e8e9bc783051f8bc634cff597885fdcb6161 100644 (file)
@@ -123,9 +123,14 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
 
        /* Locate the boot interface, to receive the LED change events */
        struct usb_interface *boot_interface = usb_ifnum_to_if(usb_dev, 0);
+       struct hid_device *boot_hid;
+       struct hid_input *boot_hid_input;
 
-       struct hid_device *boot_hid = usb_get_intfdata(boot_interface);
-       struct hid_input *boot_hid_input = list_first_entry(&boot_hid->inputs,
+       if (unlikely(boot_interface == NULL))
+               return -ENODEV;
+
+       boot_hid = usb_get_intfdata(boot_interface);
+       boot_hid_input = list_first_entry(&boot_hid->inputs,
                struct hid_input, list);
 
        return boot_hid_input->input->event(boot_hid_input->input, type, code,
index 0d695f8e1b2c4cb5771e6fdf28d75af076d886fa..0a00be19f7a0de2f1d8d4ddcf5c96ece894f7fcf 100644 (file)
 #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A  0x0b4a
 #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE         0x134a
 #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A    0x094a
+#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641    0x0641
 
 #define USB_VENDOR_ID_HUION            0x256c
 #define USB_DEVICE_ID_HUION_TABLET     0x006e
 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER           0xc52f
 #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2     0xc532
 #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2         0xc534
-#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING    0xc539
+#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED        0xc539
+#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a
 #define USB_DEVICE_ID_SPACETRAVELLER   0xc623
 #define USB_DEVICE_ID_SPACENAVIGATOR   0xc626
 #define USB_DEVICE_ID_DINOVO_DESKTOP   0xc704
 #define USB_DEVICE_ID_SAITEK_RAT7      0x0cd7
 #define USB_DEVICE_ID_SAITEK_RAT9      0x0cfa
 #define USB_DEVICE_ID_SAITEK_MMO7      0x0cd0
+#define USB_DEVICE_ID_SAITEK_X52       0x075c
 
 #define USB_VENDOR_ID_SAMSUNG          0x0419
 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE        0x0001
index 6196217a7d936c6371743354619c3564cd9e0c69..cc47f948c1d0c54632e683a0d094cc1ae4902b32 100644 (file)
@@ -1125,7 +1125,7 @@ static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev)
                                    HID_REQ_SET_REPORT);
 
        kfree(hidpp_report);
-       return retval;
+       return (retval < 0) ? retval : 0;
 }
 
 static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
@@ -1832,13 +1832,17 @@ static const struct hid_device_id logi_dj_receivers[] = {
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
                         USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2),
         .driver_data = recvr_type_hidpp},
-       { /* Logitech gaming receiver (0xc539) */
+       { /* Logitech lightspeed receiver (0xc539) */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
-               USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING),
+               USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED),
         .driver_data = recvr_type_gaming_hidpp},
        { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
         .driver_data = recvr_type_27mhz},
+       { /* Logitech powerplay receiver (0xc53a) */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+               USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY),
+        .driver_data = recvr_type_gaming_hidpp},
        { /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
                USB_DEVICE_ID_S510_RECEIVER_2),
index e3b6245bf4b23454423724ea18d2ef3e3664ad5b..0179f7ed77e5b13f852f4c4fb3fa9619f1c15677 100644 (file)
@@ -3749,15 +3749,23 @@ static const struct hid_device_id hidpp_devices[] = {
 
        { L27MHZ_DEVICE(HID_ANY_ID) },
 
-       { /* Logitech G403 Gaming Mouse over USB */
+       { /* Logitech G403 Wireless Gaming Mouse over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
-       { /* Logitech G700 Gaming Mouse over USB */
-         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC06B) },
+       { /* Logitech G703 Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC087) },
+       { /* Logitech G703 Hero Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC090) },
        { /* Logitech G900 Gaming Mouse over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC081) },
+       { /* Logitech G903 Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC086) },
+       { /* Logitech G903 Hero Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC091) },
        { /* Logitech G920 Wheel over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
                .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS},
+       { /* Logitech G Pro Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) },
 
        { /* MX5000 keyboard over Bluetooth */
          HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305),
index 185a577c46f61b0fd7888de55ca9e86e526e9844..166f41f3173b8baa52bb033141f89db9ca9b967b 100644 (file)
@@ -92,6 +92,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
+       { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT },
@@ -141,6 +142,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPAD), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
        { HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
        { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
index 93942063b51b6011dd0e73fce7e4a07fdfa0d459..49dd2d905c7f6b7f799e9de24c484a901808eddb 100644 (file)
@@ -585,10 +585,14 @@ static void sony_set_leds(struct sony_sc *sc);
 static inline void sony_schedule_work(struct sony_sc *sc,
                                      enum sony_worker which)
 {
+       unsigned long flags;
+
        switch (which) {
        case SONY_WORKER_STATE:
-               if (!sc->defer_initialization)
+               spin_lock_irqsave(&sc->lock, flags);
+               if (!sc->defer_initialization && sc->state_worker_initialized)
                        schedule_work(&sc->state_worker);
+               spin_unlock_irqrestore(&sc->lock, flags);
                break;
        case SONY_WORKER_HOTPLUG:
                if (sc->hotplug_worker_initialized)
@@ -2558,13 +2562,18 @@ static inline void sony_init_output_report(struct sony_sc *sc,
 
 static inline void sony_cancel_work_sync(struct sony_sc *sc)
 {
+       unsigned long flags;
+
        if (sc->hotplug_worker_initialized)
                cancel_work_sync(&sc->hotplug_worker);
-       if (sc->state_worker_initialized)
+       if (sc->state_worker_initialized) {
+               spin_lock_irqsave(&sc->lock, flags);
+               sc->state_worker_initialized = 0;
+               spin_unlock_irqrestore(&sc->lock, flags);
                cancel_work_sync(&sc->state_worker);
+       }
 }
 
-
 static int sony_input_configured(struct hid_device *hdev,
                                        struct hid_input *hidinput)
 {
index e12f2588ddebb028712ea212876154f50a1c7830..bdfc5ff3b2c5c9211291f71d8f0304e233f076bd 100644 (file)
@@ -22,6 +22,8 @@
 
 #include "hid-ids.h"
 
+#define THRUSTMASTER_DEVICE_ID_2_IN_1_DT       0xb320
+
 static const signed short ff_rumble[] = {
        FF_RUMBLE,
        -1
@@ -76,6 +78,7 @@ static int tmff_play(struct input_dev *dev, void *data,
        struct hid_field *ff_field = tmff->ff_field;
        int x, y;
        int left, right;        /* Rumbling */
+       int motor_swap;
 
        switch (effect->type) {
        case FF_CONSTANT:
@@ -100,6 +103,13 @@ static int tmff_play(struct input_dev *dev, void *data,
                                        ff_field->logical_minimum,
                                        ff_field->logical_maximum);
 
+               /* 2-in-1 strong motor is left */
+               if (hid->product == THRUSTMASTER_DEVICE_ID_2_IN_1_DT) {
+                       motor_swap = left;
+                       left = right;
+                       right = motor_swap;
+               }
+
                dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
                ff_field->value[0] = left;
                ff_field->value[1] = right;
@@ -226,6 +236,8 @@ static const struct hid_device_id tm_devices[] = {
                .driver_data = (unsigned long)ff_rumble },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304),   /* FireStorm Dual Power 2 (and 3) */
                .driver_data = (unsigned long)ff_rumble },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, THRUSTMASTER_DEVICE_ID_2_IN_1_DT),   /* Dual Trigger 2-in-1 */
+               .driver_data = (unsigned long)ff_rumble },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323),   /* Dual Trigger 3-in-1 (PC Mode) */
                .driver_data = (unsigned long)ff_rumble },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324),   /* Dual Trigger 3-in-1 (PS3 Mode) */
index 1065692f90e20d528be161a0059c2f45ccb0b22c..5792a104000a915c55a2eae60354b47309433237 100644 (file)
@@ -24,6 +24,7 @@
 #define ICL_MOBILE_DEVICE_ID   0x34FC
 #define SPT_H_DEVICE_ID                0xA135
 #define CML_LP_DEVICE_ID       0x02FC
+#define EHL_Ax_DEVICE_ID       0x4BB3
 
 #define        REVISION_ID_CHT_A0      0x6
 #define        REVISION_ID_CHT_Ax_SI   0x0
index aa80b4d3b740411ab8159f0c82d683d7c3d24d1c..279567baca3d95bd127256e84805a84f94f54a67 100644 (file)
@@ -33,6 +33,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
index 55b72573066b93ce070708b2f9496d4570e0c381..4e11cc6fc34bc68afc856a20315e0092ed8f97c7 100644 (file)
@@ -284,6 +284,14 @@ static int hiddev_open(struct inode *inode, struct file *file)
        spin_unlock_irq(&list->hiddev->list_lock);
 
        mutex_lock(&hiddev->existancelock);
+       /*
+        * recheck exist with existance lock held to
+        * avoid opening a disconnected device
+        */
+       if (!list->hiddev->exist) {
+               res = -ENODEV;
+               goto bail_unlock;
+       }
        if (!list->hiddev->open++)
                if (list->hiddev->exist) {
                        struct hid_device *hid = hiddev->hid;
@@ -300,6 +308,10 @@ bail_normal_power:
        hid_hw_power(hid, PM_HINT_NORMAL);
 bail_unlock:
        mutex_unlock(&hiddev->existancelock);
+
+       spin_lock_irq(&list->hiddev->list_lock);
+       list_del(&list->node);
+       spin_unlock_irq(&list->hiddev->list_lock);
 bail:
        file->private_data = NULL;
        vfree(list);
index 8fc36a28081bbe4b42e2d8beb3d4cff714a87faa..1713235d28cb01c1038b6fd1590849f684018510 100644 (file)
@@ -533,14 +533,14 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
                 */
                buttons = (data[4] << 1) | (data[3] & 0x01);
        } else if (features->type == CINTIQ_COMPANION_2) {
-               /* d-pad right  -> data[4] & 0x10
-                * d-pad up     -> data[4] & 0x20
-                * d-pad left   -> data[4] & 0x40
-                * d-pad down   -> data[4] & 0x80
-                * d-pad center -> data[3] & 0x01
+               /* d-pad right  -> data[2] & 0x10
+                * d-pad up     -> data[2] & 0x20
+                * d-pad left   -> data[2] & 0x40
+                * d-pad down   -> data[2] & 0x80
+                * d-pad center -> data[1] & 0x01
                 */
                buttons = ((data[2] >> 4) << 7) |
-                         ((data[1] & 0x04) << 6) |
+                         ((data[1] & 0x04) << 4) |
                          ((data[2] & 0x0F) << 2) |
                          (data[1] & 0x03);
        } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
@@ -846,6 +846,8 @@ static int wacom_intuos_general(struct wacom_wac *wacom)
                y >>= 1;
                distance >>= 1;
        }
+       if (features->type == INTUOSHT2)
+               distance = features->distance_max - distance;
        input_report_abs(input, ABS_X, x);
        input_report_abs(input, ABS_Y, y);
        input_report_abs(input, ABS_DISTANCE, distance);
@@ -1059,7 +1061,7 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len)
        input_report_key(input, BTN_BASE2, (data[11] & 0x02));
 
        if (data[12] & 0x80)
-               input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f));
+               input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f) - 1);
        else
                input_report_abs(input, ABS_WHEEL, 0);
 
@@ -1290,7 +1292,8 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
                }
                if (wacom->tool[0]) {
                        input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
-                       if (wacom->features.type == INTUOSP2_BT) {
+                       if (wacom->features.type == INTUOSP2_BT ||
+                           wacom->features.type == INTUOSP2S_BT) {
                                input_report_abs(pen_input, ABS_DISTANCE,
                                                 range ? frame[13] : wacom->features.distance_max);
                        } else {
index 5f9505a087f61bbfd33172257a7d0bb6340140d9..23f358cb7f494c159e2ca9d74046b470b75673a1 100644 (file)
@@ -26,7 +26,7 @@
 
 static unsigned long virt_to_hvpfn(void *addr)
 {
-       unsigned long paddr;
+       phys_addr_t paddr;
 
        if (is_vmalloc_addr(addr))
                paddr = page_to_phys(vmalloc_to_page(addr)) +
index 999f80a63bffab43abf57c5daf5bd1a2b952d797..e70783e33680f1ec2ffa6b2bf46b266093907e57 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM hyperv
index 362e70e9d145410f71dd14c1561a761195ac971c..fb16a622e8ab8dd9623e734baf5ef6b6f23d18ff 100644 (file)
@@ -146,8 +146,6 @@ struct hv_context {
         */
        u64 guestid;
 
-       void *tsc_page;
-
        struct hv_per_cpu_context __percpu *cpu_context;
 
        /*
index 3fb9c0a2d6d0bc2241d6777901d9a7da49057ceb..ce5ec403ec739c819ee8f896e5958d63380246ee 100644 (file)
@@ -343,7 +343,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                data->sample_time = MSEC_PER_SEC / 2;
                break;
        case tmp75b:  /* not one-shot mode, Conversion rate 37Hz */
-               clr_mask |= 1 << 15 | 0x3 << 13;
+               clr_mask |= 1 << 7 | 0x3 << 5;
                data->resolution = 12;
                data->sample_time = MSEC_PER_SEC / 37;
                break;
index e7dff5febe161f11761d23a7b22f62f4ed99254a..d42bc0883a32b4ba115f113d84e6503ecd43e081 100644 (file)
@@ -852,7 +852,7 @@ static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
 static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
 static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
 static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
-static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
+static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x18b };
 static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
 static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
 
@@ -3764,6 +3764,7 @@ static int nct6775_probe(struct platform_device *pdev)
                data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
                data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
                data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
+               data->REG_TOLERANCE_H = NCT6106_REG_TOLERANCE_H;
                data->REG_PWM[0] = NCT6106_REG_PWM;
                data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
                data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
index ec7bcf8d7cd66d3280e752481c21774c2310fc17..f3dd2a17bd426244d72d26a8d027fa24523cbb00 100644 (file)
@@ -704,7 +704,7 @@ static struct attribute *nct7802_in_attrs[] = {
        &sensor_dev_attr_in3_alarm.dev_attr.attr,
        &sensor_dev_attr_in3_beep.dev_attr.attr,
 
-       &sensor_dev_attr_in4_input.dev_attr.attr,       /* 17 */
+       &sensor_dev_attr_in4_input.dev_attr.attr,       /* 16 */
        &sensor_dev_attr_in4_min.dev_attr.attr,
        &sensor_dev_attr_in4_max.dev_attr.attr,
        &sensor_dev_attr_in4_alarm.dev_attr.attr,
@@ -730,9 +730,9 @@ static umode_t nct7802_in_is_visible(struct kobject *kobj,
 
        if (index >= 6 && index < 11 && (reg & 0x03) != 0x03)   /* VSEN1 */
                return 0;
-       if (index >= 11 && index < 17 && (reg & 0x0c) != 0x0c)  /* VSEN2 */
+       if (index >= 11 && index < 16 && (reg & 0x0c) != 0x0c)  /* VSEN2 */
                return 0;
-       if (index >= 17 && (reg & 0x30) != 0x30)                /* VSEN3 */
+       if (index >= 16 && (reg & 0x30) != 0x30)                /* VSEN3 */
                return 0;
 
        return attr->mode;
index a7d2b16dd702c9ae4a312caa40888ea6ad7f1f6c..30e18eb60da79eb61ba9194a056de8a2198311ad 100644 (file)
@@ -408,8 +408,10 @@ static ssize_t occ_show_power_1(struct device *dev,
 
 static u64 occ_get_powr_avg(u64 *accum, u32 *samples)
 {
-       return div64_u64(get_unaligned_be64(accum) * 1000000ULL,
-                        get_unaligned_be32(samples));
+       u64 divisor = get_unaligned_be32(samples);
+
+       return (divisor == 0) ? 0 :
+               div64_u64(get_unaligned_be64(accum) * 1000000ULL, divisor);
 }
 
 static ssize_t occ_show_power_2(struct device *dev,
index 5c1ca0df5cb0064d3e0c633805bf42b8ef00622c..84f1dcb6982724c88980285c239e9342b08da6b0 100644 (file)
@@ -544,6 +544,7 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev)
        /* See function coresight_get_sink_by_id() to know where this is used */
        hash = hashlen_hash(hashlen_string(NULL, name));
 
+       sysfs_attr_init(&ea->attr.attr);
        ea->attr.attr.name = devm_kstrdup(dev, name, GFP_KERNEL);
        if (!ea->attr.attr.name)
                return -ENOMEM;
index 574c16004cb2e266f892ef73d0c3e88fa0fbbb68..13d9b141daaaaf3da7e4b8195e2ec6c41929fb42 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Intel(R) Trace Hub Memory Storage Unit (MSU) data structures
  *
index c0378c3de9a41a7ec65b994e18b907e56fc3b88e..91dfeba624855b32b3c3c43a2ad276ea87c294da 100644 (file)
@@ -164,6 +164,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6),
                .driver_data = (kernel_ulong_t)0,
        },
+       {
+               /* Lewisburg PCH */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa226),
+               .driver_data = (kernel_ulong_t)0,
+       },
        {
                /* Gemini Lake */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e),
@@ -199,6 +204,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Tiger Lake PCH */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        { 0 },
 };
 
index e9381babc84c37f662ee8e822806a99a1dd9bab3..7dfc0431333b77f81f822ffd0bd988de259c5bbe 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Intel(R) Trace Hub PTI output data structures
  *
index e55b902560dee28f854718b72f40ca48803de249..181e7ff1ec4fc374e31968e3a89c0fc9592a6d73 100644 (file)
@@ -1276,7 +1276,6 @@ int stm_source_register_device(struct device *parent,
 
 err:
        put_device(&src->dev);
-       kfree(src);
 
        return err;
 }
index 8d55cdd69ff48eee01a21aa65caa2c145461deed..435c7d7377a36beef286a1c6ef5c749cbecf7386 100644 (file)
@@ -142,7 +142,7 @@ static struct at91_twi_pdata sama5d4_config = {
 
 static struct at91_twi_pdata sama5d2_config = {
        .clk_max_div = 7,
-       .clk_offset = 4,
+       .clk_offset = 3,
        .has_unre_flag = true,
        .has_alt_cmd = true,
        .has_hold_field = true,
index e87232f2e70855c3c5a21b1028597b8fd298a114..a3fcc35ffd3b65b037965efb5ededd808b82ea8b 100644 (file)
@@ -122,9 +122,11 @@ static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
        writeb_relaxed(*dev->buf, dev->base + AT91_TWI_THR);
 
        /* send stop when last byte has been written */
-       if (--dev->buf_len == 0)
+       if (--dev->buf_len == 0) {
                if (!dev->use_alt_cmd)
                        at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+               at91_twi_write(dev, AT91_TWI_IDR, AT91_TWI_TXRDY);
+       }
 
        dev_dbg(dev->dev, "wrote 0x%x, to go %zu\n", *dev->buf, dev->buf_len);
 
@@ -542,9 +544,8 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
                } else {
                        at91_twi_write_next_byte(dev);
                        at91_twi_write(dev, AT91_TWI_IER,
-                                      AT91_TWI_TXCOMP |
-                                      AT91_TWI_NACK |
-                                      AT91_TWI_TXRDY);
+                                      AT91_TWI_TXCOMP | AT91_TWI_NACK |
+                                      (dev->buf_len ? AT91_TWI_TXRDY : 0));
                }
        }
 
index 2c7f145a036e62d291afd5a645430fcb12966c71..19ef2b0c682a9992b2ef74c669d7f45e80254eb5 100644 (file)
@@ -392,16 +392,18 @@ static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
 static void bcm_iproc_i2c_read_valid_bytes(struct bcm_iproc_i2c_dev *iproc_i2c)
 {
        struct i2c_msg *msg = iproc_i2c->msg;
+       uint32_t val;
 
        /* Read valid data from RX FIFO */
        while (iproc_i2c->rx_bytes < msg->len) {
-               if (!((iproc_i2c_rd_reg(iproc_i2c, M_FIFO_CTRL_OFFSET) >> M_FIFO_RX_CNT_SHIFT)
-                     & M_FIFO_RX_CNT_MASK))
+               val = iproc_i2c_rd_reg(iproc_i2c, M_RX_OFFSET);
+
+               /* rx fifo empty */
+               if (!((val >> M_RX_STATUS_SHIFT) & M_RX_STATUS_MASK))
                        break;
 
                msg->buf[iproc_i2c->rx_bytes] =
-                       (iproc_i2c_rd_reg(iproc_i2c, M_RX_OFFSET) >>
-                       M_RX_DATA_SHIFT) & M_RX_DATA_MASK;
+                       (val >> M_RX_DATA_SHIFT) & M_RX_DATA_MASK;
                iproc_i2c->rx_bytes++;
        }
 }
@@ -788,7 +790,10 @@ static int bcm_iproc_i2c_xfer(struct i2c_adapter *adapter,
 
 static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap)
 {
-       u32 val = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+       u32 val;
+
+       /* We do not support the SMBUS Quick command */
+       val = I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
 
        if (adap->algo->reg_slave)
                val |= I2C_FUNC_SLAVE;
index e7f9305b2dd9f661c8863839dee346aa49438c4e..f5f001738df5e2b1b8c6e9db4973a9ce8f065140 100644 (file)
@@ -94,6 +94,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)
 
        dev->disable_int(dev);
        dev->disable(dev);
+       synchronize_irq(dev->irq);
        dev->slave = NULL;
        pm_runtime_put(dev->dev);
 
index 35b302d983e0d93d74b255d57f113226f9c799f9..959d4912ec0d5ce1082c4713cee86e13b10a228d 100644 (file)
@@ -69,6 +69,7 @@ struct em_i2c_device {
        struct completion msg_done;
        struct clk *sclk;
        struct i2c_client *slave;
+       int irq;
 };
 
 static inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
@@ -339,6 +340,12 @@ static int em_i2c_unreg_slave(struct i2c_client *slave)
 
        writeb(0, priv->base + I2C_OFS_SVA0);
 
+       /*
+        * Wait for interrupt to finish. New slave irqs cannot happen because we
+        * cleared the slave address and, thus, only extension codes will be
+        * detected which do not use the slave ptr.
+        */
+       synchronize_irq(priv->irq);
        priv->slave = NULL;
 
        return 0;
@@ -355,7 +362,7 @@ static int em_i2c_probe(struct platform_device *pdev)
 {
        struct em_i2c_device *priv;
        struct resource *r;
-       int irq, ret;
+       int ret;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -390,8 +397,8 @@ static int em_i2c_probe(struct platform_device *pdev)
 
        em_i2c_reset(&priv->adap);
 
-       irq = platform_get_irq(pdev, 0);
-       ret = devm_request_irq(&pdev->dev, irq, em_i2c_irq_handler, 0,
+       priv->irq = platform_get_irq(pdev, 0);
+       ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0,
                                "em_i2c", priv);
        if (ret)
                goto err_clk;
@@ -401,7 +408,8 @@ static int em_i2c_probe(struct platform_device *pdev)
        if (ret)
                goto err_clk;
 
-       dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr, irq);
+       dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr,
+                priv->irq);
 
        return 0;
 
index f2956936c3f2d3f5a28b21d79d3d56e578f90793..2e08b4722dc41bd2821a9bce4c2871d89de94755 100644 (file)
@@ -1194,19 +1194,28 @@ static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle,
        int i;
 
        status = acpi_get_object_info(obj_handle, &info);
-       if (!ACPI_SUCCESS(status) || !(info->valid & ACPI_VALID_HID))
+       if (ACPI_FAILURE(status))
                return AE_OK;
 
+       if (!(info->valid & ACPI_VALID_HID))
+               goto smo88xx_not_found;
+
        hid = info->hardware_id.string;
        if (!hid)
-               return AE_OK;
+               goto smo88xx_not_found;
 
        i = match_string(acpi_smo8800_ids, ARRAY_SIZE(acpi_smo8800_ids), hid);
        if (i < 0)
-               return AE_OK;
+               goto smo88xx_not_found;
+
+       kfree(info);
 
        *((bool *)return_value) = true;
        return AE_CTRL_TERMINATE;
+
+smo88xx_not_found:
+       kfree(info);
+       return AE_OK;
 }
 
 static bool is_dell_system_with_lis3lv02d(void)
index b1b8b938d7f423714b52582d0c203c4143846409..15f6cde6452f7113b30cd85784bf22a40a40b25c 100644 (file)
@@ -273,8 +273,8 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
 }
 
 /* Functions for DMA support */
-static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
-                              dma_addr_t phy_addr)
+static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
+                                               dma_addr_t phy_addr)
 {
        struct imx_i2c_dma *dma;
        struct dma_slave_config dma_sconfig;
@@ -283,7 +283,7 @@ static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
 
        dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
        if (!dma)
-               return -ENOMEM;
+               return;
 
        dma->chan_tx = dma_request_chan(dev, "tx");
        if (IS_ERR(dma->chan_tx)) {
@@ -328,7 +328,7 @@ static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
        dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
                dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
 
-       return 0;
+       return;
 
 fail_rx:
        dma_release_channel(dma->chan_rx);
@@ -336,8 +336,6 @@ fail_tx:
        dma_release_channel(dma->chan_tx);
 fail_al:
        devm_kfree(dev, dma);
-       /* return successfully if there is no dma support */
-       return ret == -ENODEV ? 0 : ret;
 }
 
 static void i2c_imx_dma_callback(void *arg)
@@ -1165,17 +1163,13 @@ static int i2c_imx_probe(struct platform_device *pdev)
        dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
        dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
                i2c_imx->adapter.name);
+       dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
 
        /* Init DMA config if supported */
-       ret = i2c_imx_dma_request(i2c_imx, phy_addr);
-       if (ret < 0)
-               goto del_adapter;
+       i2c_imx_dma_request(i2c_imx, phy_addr);
 
-       dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
        return 0;   /* Return OK */
 
-del_adapter:
-       i2c_del_adapter(&i2c_imx->adapter);
 clk_notifier_unregister:
        clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
 rpm_disable:
index 252edb433fdfb14f43a777763f3e99e5ae7014d8..29eae1bf4f861a39078091644aa329326aa1c2ed 100644 (file)
@@ -234,6 +234,10 @@ static const struct i2c_adapter_quirks mt7622_i2c_quirks = {
        .max_num_msgs = 255,
 };
 
+static const struct i2c_adapter_quirks mt8183_i2c_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 static const struct mtk_i2c_compatible mt2712_compat = {
        .regs = mt_i2c_regs_v1,
        .pmic_i2c = 0,
@@ -298,6 +302,7 @@ static const struct mtk_i2c_compatible mt8173_compat = {
 };
 
 static const struct mtk_i2c_compatible mt8183_compat = {
+       .quirks = &mt8183_i2c_quirks,
        .regs = mt_i2c_regs_v2,
        .pmic_i2c = 0,
        .dcm = 0,
@@ -870,7 +875,11 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
 
 static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+       if (adap->quirks->flags & I2C_AQ_NO_ZERO_LEN)
+               return I2C_FUNC_I2C |
+                       (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+       else
+               return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
 static const struct i2c_algorithm mtk_i2c_algorithm = {
index cfc76b5de7269b393c238ffc302d78cbf4e1ec28..5a1235fd86bbecb4a302119c92db48f1784f67fd 100644 (file)
@@ -364,7 +364,7 @@ static void gpu_i2c_remove(struct pci_dev *pdev)
 /*
  * We need gpu_i2c_suspend() even if it is stub, for runtime pm to work
  * correctly. Without it, lspci shows runtime pm status as "D0" for the card.
- * Documentation/power/pci.txt also insists for driver to provide this.
+ * Documentation/power/pci.rst also insists for driver to provide this.
  */
 static __maybe_unused int gpu_i2c_suspend(struct device *dev)
 {
index c46c4bddc7ca360f2241aa1d213da9d8b9dc2486..cba325eb852fed527fe4c73d72fb718113db5097 100644 (file)
@@ -91,7 +91,7 @@
 #define SB800_PIIX4_PORT_IDX_MASK      0x06
 #define SB800_PIIX4_PORT_IDX_SHIFT     1
 
-/* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */
+/* On kerncz and Hudson2, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */
 #define SB800_PIIX4_PORT_IDX_KERNCZ            0x02
 #define SB800_PIIX4_PORT_IDX_MASK_KERNCZ       0x18
 #define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ      3
@@ -358,18 +358,16 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
        /* Find which register is used for port selection */
        if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD ||
            PIIX4_dev->vendor == PCI_VENDOR_ID_HYGON) {
-               switch (PIIX4_dev->device) {
-               case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS:
+               if (PIIX4_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS ||
+                   (PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
+                    PIIX4_dev->revision >= 0x1F)) {
                        piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ;
                        piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ;
                        piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ;
-                       break;
-               case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS:
-               default:
+               } else {
                        piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT;
                        piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
                        piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
-                       break;
                }
        } else {
                if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2,
index d39a4606f72d3d7849d2727a4f83cad298bd58e3..531c01100b560be3c4960e0ff916b533505267a9 100644 (file)
@@ -139,6 +139,7 @@ struct rcar_i2c_priv {
        enum dma_data_direction dma_direction;
 
        struct reset_control *rstc;
+       int irq;
 };
 
 #define rcar_i2c_priv_to_dev(p)                ((p)->adap.dev.parent)
@@ -861,9 +862,11 @@ static int rcar_unreg_slave(struct i2c_client *slave)
 
        WARN_ON(!priv->slave);
 
+       /* disable irqs and ensure none is running before clearing ptr */
        rcar_i2c_write(priv, ICSIER, 0);
        rcar_i2c_write(priv, ICSCR, 0);
 
+       synchronize_irq(priv->irq);
        priv->slave = NULL;
 
        pm_runtime_put(rcar_i2c_priv_to_dev(priv));
@@ -918,7 +921,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
        struct i2c_adapter *adap;
        struct device *dev = &pdev->dev;
        struct i2c_timings i2c_t;
-       int irq, ret;
+       int ret;
 
        /* Otherwise logic will break because some bytes must always use PIO */
        BUILD_BUG_ON_MSG(RCAR_MIN_DMA_LEN < 3, "Invalid min DMA length");
@@ -984,10 +987,10 @@ static int rcar_i2c_probe(struct platform_device *pdev)
                pm_runtime_put(dev);
 
 
-       irq = platform_get_irq(pdev, 0);
-       ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0, dev_name(dev), priv);
+       priv->irq = platform_get_irq(pdev, 0);
+       ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0, dev_name(dev), priv);
        if (ret < 0) {
-               dev_err(dev, "cannot get irq %d\n", irq);
+               dev_err(dev, "cannot get irq %d\n", priv->irq);
                goto out_pm_disable;
        }
 
index d97fb857b0ea9fb3f23de8ebb8b807fa85e0b021..c98ef4c4a0c9ea844c162a48811783762aa13331 100644 (file)
@@ -435,6 +435,7 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
                 * fall through to the write state, as we will need to
                 * send a byte as well
                 */
+               /* Fall through */
 
        case STATE_WRITE:
                /*
index 868755f82f884be35c67aa30edcba5f16057f9f6..2c21893905a30148f622e362f969cba32e94122e 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * i2c-stm32.h
  *
index f26ed495d38420b3864c997945940941dcf5e754..9c440fa6a3dd109349a86365a678e46ffe8b89f7 100644 (file)
@@ -832,7 +832,7 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
  */
 void i2c_unregister_device(struct i2c_client *client)
 {
-       if (!client)
+       if (IS_ERR_OR_NULL(client))
                return;
 
        if (client->dev.of_node) {
index 46bb2e421bb91a2a21fd6ee6ee08b04616d30509..ad19d9c716f41e4611af354511b1354711e2701c 100644 (file)
@@ -319,7 +319,6 @@ static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = {
                .modified = 1,                                          \
                .info_mask_separate =                                   \
                        BIT(IIO_CHAN_INFO_RAW) |                        \
-                       BIT(IIO_CHAN_INFO_SCALE) |                      \
                        BIT(IIO_CHAN_INFO_CALIBBIAS),                   \
                .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),    \
                .ext_info = cros_ec_accel_legacy_ext_info,              \
index 92b1d5037ac984a4a013ccfb395342996f6ffb45..e234970b7150fb743e33f56e5cb28662b3ecf92c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/iio/iio.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 #define JZ_ADC_REG_ADTCH               0x18
 #define JZ_ADC_REG_ADBDAT              0x1c
 #define JZ_ADC_REG_ADSDAT              0x20
+#define JZ_ADC_REG_ADCLK               0x28
 
 #define JZ_ADC_REG_CFG_BAT_MD          BIT(4)
+#define JZ_ADC_REG_ADCLK_CLKDIV_LSB    0
+#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB        16
 
 #define JZ_ADC_AUX_VREF                                3300
 #define JZ_ADC_AUX_VREF_BITS                   12
@@ -34,6 +38,8 @@
 #define JZ4740_ADC_BATTERY_HIGH_VREF           (7500 * 0.986)
 #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS      12
 
+struct ingenic_adc;
+
 struct ingenic_adc_soc_data {
        unsigned int battery_high_vref;
        unsigned int battery_high_vref_bits;
@@ -41,6 +47,7 @@ struct ingenic_adc_soc_data {
        size_t battery_raw_avail_size;
        const int *battery_scale_avail;
        size_t battery_scale_avail_size;
+       int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
 };
 
 struct ingenic_adc {
@@ -151,6 +158,42 @@ static const int jz4740_adc_battery_scale_avail[] = {
        JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
 };
 
+static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
+{
+       struct clk *parent_clk;
+       unsigned long parent_rate, rate;
+       unsigned int div_main, div_10us;
+
+       parent_clk = clk_get_parent(adc->clk);
+       if (!parent_clk) {
+               dev_err(dev, "ADC clock has no parent\n");
+               return -ENODEV;
+       }
+       parent_rate = clk_get_rate(parent_clk);
+
+       /*
+        * The JZ4725B ADC works at 500 kHz to 8 MHz.
+        * We pick the highest rate possible.
+        * In practice we typically get 6 MHz, half of the 12 MHz EXT clock.
+        */
+       div_main = DIV_ROUND_UP(parent_rate, 8000000);
+       div_main = clamp(div_main, 1u, 64u);
+       rate = parent_rate / div_main;
+       if (rate < 500000 || rate > 8000000) {
+               dev_err(dev, "No valid divider for ADC main clock\n");
+               return -EINVAL;
+       }
+
+       /* We also need a divider that produces a 10us clock. */
+       div_10us = DIV_ROUND_UP(rate, 100000);
+
+       writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
+              (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
+              adc->base + JZ_ADC_REG_ADCLK);
+
+       return 0;
+}
+
 static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
        .battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
        .battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
@@ -158,6 +201,7 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
        .battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
        .battery_scale_avail = jz4725b_adc_battery_scale_avail,
        .battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
+       .init_clk_div = jz4725b_adc_init_clk_div,
 };
 
 static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
@@ -167,6 +211,7 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
        .battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
        .battery_scale_avail = jz4740_adc_battery_scale_avail,
        .battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
+       .init_clk_div = NULL, /* no ADCLK register on JZ4740 */
 };
 
 static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
@@ -317,6 +362,15 @@ static int ingenic_adc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       /* Set clock dividers. */
+       if (soc_data->init_clk_div) {
+               ret = soc_data->init_clk_div(dev, adc);
+               if (ret) {
+                       clk_disable_unprepare(adc->clk);
+                       return ret;
+               }
+       }
+
        /* Put hardware in a known passive state. */
        writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
        writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
index 917223d5ff5bb635125bca95c38150471d7e772b..da073d72f649f829997f6f3ca9a43c13399aba0d 100644 (file)
@@ -83,7 +83,7 @@
 #define MAX9611_TEMP_MAX_POS           0x7f80
 #define MAX9611_TEMP_MAX_NEG           0xff80
 #define MAX9611_TEMP_MIN_NEG           0xd980
-#define MAX9611_TEMP_MASK              GENMASK(7, 15)
+#define MAX9611_TEMP_MASK              GENMASK(15, 7)
 #define MAX9611_TEMP_SHIFT             0x07
 #define MAX9611_TEMP_RAW(_r)           ((_r) >> MAX9611_TEMP_SHIFT)
 #define MAX9611_TEMP_SCALE_NUM         1000000
@@ -480,7 +480,7 @@ static int max9611_init(struct max9611_dev *max9611)
        if (ret)
                return ret;
 
-       regval = ret & MAX9611_TEMP_MASK;
+       regval &= MAX9611_TEMP_MASK;
 
        if ((regval > MAX9611_TEMP_MAX_POS &&
             regval < MAX9611_TEMP_MIN_NEG) ||
index 2d685730f8673e650e1f32d16dc22fe481445438..c37f201294b2ae95f25b8c4636ee1b07c5b996ab 100644 (file)
@@ -382,7 +382,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
                                dev_err(dev,
                                        "Only %i channels supported with %pOFn, but reg = <%i>.\n",
                                        num_channels, child, reg);
-                               return ret;
+                               return -EINVAL;
                        }
                }
 
@@ -391,7 +391,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
                        dev_err(dev,
                                "Channel %i uses different ADC mode than the rest.\n",
                                reg);
-                       return ret;
+                       return -EINVAL;
                }
 
                /* Channel is valid, grab the regulator. */
index e48f15cc9ab5c36d0f140a3f5210e8087fa42acf..ff82863cbf42d4d1f7b59edbe8c1e3052135cf71 100644 (file)
@@ -276,11 +276,11 @@ static int adf4371_set_freq(struct adf4371_state *st, unsigned long long freq,
        st->buf[0] = st->integer >> 8;
        st->buf[1] = 0x40; /* REG12 default */
        st->buf[2] = 0x00;
-       st->buf[3] = st->fract2 & 0xFF;
-       st->buf[4] = st->fract2 >> 7;
-       st->buf[5] = st->fract2 >> 15;
+       st->buf[3] = st->fract1 & 0xFF;
+       st->buf[4] = st->fract1 >> 8;
+       st->buf[5] = st->fract1 >> 16;
        st->buf[6] = ADF4371_FRAC2WORD_L(st->fract2 & 0x7F) |
-                    ADF4371_FRAC1WORD(st->fract1 >> 23);
+                    ADF4371_FRAC1WORD(st->fract1 >> 24);
        st->buf[7] = ADF4371_FRAC2WORD_H(st->fract2 >> 7);
        st->buf[8] = st->mod2 & 0xFF;
        st->buf[9] = ADF4371_MOD2WORD(st->mod2 >> 8);
index 53a59957cc5428d4ae6905b19f958acb8bfa4707..8a704cd5bddb7d7399bf8dc6d7d39652974267d7 100644 (file)
@@ -845,6 +845,25 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
        INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
 };
 
+static const unsigned long inv_mpu_scan_masks[] = {
+       /* 3-axis accel */
+       BIT(INV_MPU6050_SCAN_ACCL_X)
+               | BIT(INV_MPU6050_SCAN_ACCL_Y)
+               | BIT(INV_MPU6050_SCAN_ACCL_Z),
+       /* 3-axis gyro */
+       BIT(INV_MPU6050_SCAN_GYRO_X)
+               | BIT(INV_MPU6050_SCAN_GYRO_Y)
+               | BIT(INV_MPU6050_SCAN_GYRO_Z),
+       /* 6-axis accel + gyro */
+       BIT(INV_MPU6050_SCAN_ACCL_X)
+               | BIT(INV_MPU6050_SCAN_ACCL_Y)
+               | BIT(INV_MPU6050_SCAN_ACCL_Z)
+               | BIT(INV_MPU6050_SCAN_GYRO_X)
+               | BIT(INV_MPU6050_SCAN_GYRO_Y)
+               | BIT(INV_MPU6050_SCAN_GYRO_Z),
+       0,
+};
+
 static const struct iio_chan_spec inv_icm20602_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP),
        {
@@ -871,6 +890,28 @@ static const struct iio_chan_spec inv_icm20602_channels[] = {
        INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_ICM20602_SCAN_ACCL_Z),
 };
 
+static const unsigned long inv_icm20602_scan_masks[] = {
+       /* 3-axis accel + temp (mandatory) */
+       BIT(INV_ICM20602_SCAN_ACCL_X)
+               | BIT(INV_ICM20602_SCAN_ACCL_Y)
+               | BIT(INV_ICM20602_SCAN_ACCL_Z)
+               | BIT(INV_ICM20602_SCAN_TEMP),
+       /* 3-axis gyro + temp (mandatory) */
+       BIT(INV_ICM20602_SCAN_GYRO_X)
+               | BIT(INV_ICM20602_SCAN_GYRO_Y)
+               | BIT(INV_ICM20602_SCAN_GYRO_Z)
+               | BIT(INV_ICM20602_SCAN_TEMP),
+       /* 6-axis accel + gyro + temp (mandatory) */
+       BIT(INV_ICM20602_SCAN_ACCL_X)
+               | BIT(INV_ICM20602_SCAN_ACCL_Y)
+               | BIT(INV_ICM20602_SCAN_ACCL_Z)
+               | BIT(INV_ICM20602_SCAN_GYRO_X)
+               | BIT(INV_ICM20602_SCAN_GYRO_Y)
+               | BIT(INV_ICM20602_SCAN_GYRO_Z)
+               | BIT(INV_ICM20602_SCAN_TEMP),
+       0,
+};
+
 /*
  * The user can choose any frequency between INV_MPU6050_MIN_FIFO_RATE and
  * INV_MPU6050_MAX_FIFO_RATE, but only these frequencies are matched by the
@@ -1130,9 +1171,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
        if (chip_type == INV_ICM20602) {
                indio_dev->channels = inv_icm20602_channels;
                indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels);
+               indio_dev->available_scan_masks = inv_icm20602_scan_masks;
        } else {
                indio_dev->channels = inv_mpu_channels;
                indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
+               indio_dev->available_scan_masks = inv_mpu_scan_masks;
        }
 
        indio_dev->info = &mpu_info;
index 19f1730a4f2442a175536f290ae40941d3bf954c..a68d0ccf67a431f915822b1f943800c8c3655b8c 100644 (file)
@@ -4724,10 +4724,14 @@ static int __init cma_init(void)
        if (ret)
                goto err;
 
-       cma_configfs_init();
+       ret = cma_configfs_init();
+       if (ret)
+               goto err_ib;
 
        return 0;
 
+err_ib:
+       ib_unregister_client(&cma_client);
 err:
        unregister_netdevice_notifier(&cma_nb);
        ib_sa_unregister_client(&sa_client);
index 888d89ce81df07118fd21683241921a1499e6aea..beee7b7e0d9acf6526a52f6205950d561f547067 100644 (file)
@@ -302,7 +302,9 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
                                          struct ib_udata *udata,
                                          struct ib_uobject *uobj)
 {
+       enum ib_qp_type qp_type = attr->qp_type;
        struct ib_qp *qp;
+       bool is_xrc;
 
        if (!dev->ops.create_qp)
                return ERR_PTR(-EOPNOTSUPP);
@@ -320,7 +322,8 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
         * and more importantly they are created internaly by driver,
         * see mlx5 create_dev_resources() as an example.
         */
-       if (attr->qp_type < IB_QPT_XRC_INI) {
+       is_xrc = qp_type == IB_QPT_XRC_INI || qp_type == IB_QPT_XRC_TGT;
+       if ((qp_type < IB_QPT_MAX && !is_xrc) || qp_type == IB_QPT_DRIVER) {
                qp->res.type = RDMA_RESTRACK_QP;
                if (uobj)
                        rdma_restrack_uadd(&qp->res);
index 01faef7bc0615838d37c57b82b069df0a9c89da9..af8c85d18e62ffde7e7bc0cf78b2a8d294a27f76 100644 (file)
@@ -38,6 +38,9 @@ int rdma_counter_set_auto_mode(struct ib_device *dev, u8 port,
        int ret;
 
        port_counter = &dev->port_data[port].port_counter;
+       if (!port_counter->hstats)
+               return -EOPNOTSUPP;
+
        mutex_lock(&port_counter->lock);
        if (on) {
                ret = __counter_set_mode(&port_counter->mode,
@@ -146,13 +149,11 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,
        struct auto_mode_param *param = &counter->mode.param;
        bool match = true;
 
-       if (rdma_is_kernel_res(&counter->res) != rdma_is_kernel_res(&qp->res))
+       if (!rdma_is_visible_in_pid_ns(&qp->res))
                return false;
 
-       /* Ensure that counter belong to right PID */
-       if (!rdma_is_kernel_res(&counter->res) &&
-           !rdma_is_kernel_res(&qp->res) &&
-           (task_pid_vnr(counter->res.task) != current->pid))
+       /* Ensure that counter belongs to the right PID */
+       if (task_pid_nr(counter->res.task) != task_pid_nr(qp->res.task))
                return false;
 
        if (auto_mask & RDMA_COUNTER_MASK_QP_TYPE)
@@ -393,6 +394,9 @@ u64 rdma_counter_get_hwstat_value(struct ib_device *dev, u8 port, u32 index)
        u64 sum;
 
        port_counter = &dev->port_data[port].port_counter;
+       if (!port_counter->hstats)
+               return 0;
+
        sum = get_running_counters_hwstat_sum(dev, port, index);
        sum += port_counter->hstats->value[index];
 
@@ -418,7 +422,7 @@ static struct ib_qp *rdma_counter_get_qp(struct ib_device *dev, u32 qp_num)
        return qp;
 
 err:
-       rdma_restrack_put(&qp->res);
+       rdma_restrack_put(res);
        return NULL;
 }
 
@@ -506,6 +510,9 @@ int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port,
        if (!rdma_is_port_valid(dev, port))
                return -EINVAL;
 
+       if (!dev->port_data[port].port_counter.hstats)
+               return -EOPNOTSUPP;
+
        qp = rdma_counter_get_qp(dev, qp_num);
        if (!qp)
                return -ENOENT;
@@ -594,7 +601,7 @@ void rdma_counter_init(struct ib_device *dev)
        struct rdma_port_counter *port_counter;
        u32 port;
 
-       if (!dev->ops.alloc_hw_stats || !dev->port_data)
+       if (!dev->port_data)
                return;
 
        rdma_for_each_port(dev, port) {
@@ -602,6 +609,9 @@ void rdma_counter_init(struct ib_device *dev)
                port_counter->mode.mode = RDMA_COUNTER_MODE_NONE;
                mutex_init(&port_counter->lock);
 
+               if (!dev->ops.alloc_hw_stats)
+                       continue;
+
                port_counter->hstats = dev->ops.alloc_hw_stats(dev, port);
                if (!port_counter->hstats)
                        goto fail;
@@ -624,9 +634,6 @@ void rdma_counter_release(struct ib_device *dev)
        struct rdma_port_counter *port_counter;
        u32 port;
 
-       if (!dev->ops.alloc_hw_stats)
-               return;
-
        rdma_for_each_port(dev, port) {
                port_counter = &dev->port_data[port].port_counter;
                kfree(port_counter->hstats);
index 9773145dee0996d0d058230bc6ce18f9c138d34f..ea8661a00651bba68f496a7bd2a398b9289f9a68 100644 (file)
@@ -94,11 +94,17 @@ static DEFINE_XARRAY_FLAGS(devices, XA_FLAGS_ALLOC);
 static DECLARE_RWSEM(devices_rwsem);
 #define DEVICE_REGISTERED XA_MARK_1
 
-static LIST_HEAD(client_list);
+static u32 highest_client_id;
 #define CLIENT_REGISTERED XA_MARK_1
 static DEFINE_XARRAY_FLAGS(clients, XA_FLAGS_ALLOC);
 static DECLARE_RWSEM(clients_rwsem);
 
+static void ib_client_put(struct ib_client *client)
+{
+       if (refcount_dec_and_test(&client->uses))
+               complete(&client->uses_zero);
+}
+
 /*
  * If client_data is registered then the corresponding client must also still
  * be registered.
@@ -660,6 +666,14 @@ static int add_client_context(struct ib_device *device,
                return 0;
 
        down_write(&device->client_data_rwsem);
+       /*
+        * So long as the client is registered hold both the client and device
+        * unregistration locks.
+        */
+       if (!refcount_inc_not_zero(&client->uses))
+               goto out_unlock;
+       refcount_inc(&device->refcount);
+
        /*
         * Another caller to add_client_context got here first and has already
         * completely initialized context.
@@ -683,6 +697,9 @@ static int add_client_context(struct ib_device *device,
        return 0;
 
 out:
+       ib_device_put(device);
+       ib_client_put(client);
+out_unlock:
        up_write(&device->client_data_rwsem);
        return ret;
 }
@@ -702,7 +719,7 @@ static void remove_client_context(struct ib_device *device,
        client_data = xa_load(&device->client_data, client_id);
        xa_clear_mark(&device->client_data, client_id, CLIENT_DATA_REGISTERED);
        client = xa_load(&clients, client_id);
-       downgrade_write(&device->client_data_rwsem);
+       up_write(&device->client_data_rwsem);
 
        /*
         * Notice we cannot be holding any exclusive locks when calling the
@@ -712,17 +729,13 @@ static void remove_client_context(struct ib_device *device,
         *
         * For this reason clients and drivers should not call the
         * unregistration functions will holdling any locks.
-        *
-        * It tempting to drop the client_data_rwsem too, but this is required
-        * to ensure that unregister_client does not return until all clients
-        * are completely unregistered, which is required to avoid module
-        * unloading races.
         */
        if (client->remove)
                client->remove(device, client_data);
 
        xa_erase(&device->client_data, client_id);
-       up_read(&device->client_data_rwsem);
+       ib_device_put(device);
+       ib_client_put(client);
 }
 
 static int alloc_port_data(struct ib_device *device)
@@ -1224,7 +1237,7 @@ static int setup_device(struct ib_device *device)
 
 static void disable_device(struct ib_device *device)
 {
-       struct ib_client *client;
+       u32 cid;
 
        WARN_ON(!refcount_read(&device->refcount));
 
@@ -1232,10 +1245,19 @@ static void disable_device(struct ib_device *device)
        xa_clear_mark(&devices, device->index, DEVICE_REGISTERED);
        up_write(&devices_rwsem);
 
+       /*
+        * Remove clients in LIFO order, see assign_client_id. This could be
+        * more efficient if xarray learns to reverse iterate. Since no new
+        * clients can be added to this ib_device past this point we only need
+        * the maximum possible client_id value here.
+        */
        down_read(&clients_rwsem);
-       list_for_each_entry_reverse(client, &client_list, list)
-               remove_client_context(device, client->client_id);
+       cid = highest_client_id;
        up_read(&clients_rwsem);
+       while (cid) {
+               cid--;
+               remove_client_context(device, cid);
+       }
 
        /* Pairs with refcount_set in enable_device */
        ib_device_put(device);
@@ -1662,30 +1684,31 @@ static int assign_client_id(struct ib_client *client)
        /*
         * The add/remove callbacks must be called in FIFO/LIFO order. To
         * achieve this we assign client_ids so they are sorted in
-        * registration order, and retain a linked list we can reverse iterate
-        * to get the LIFO order. The extra linked list can go away if xarray
-        * learns to reverse iterate.
+        * registration order.
         */
-       if (list_empty(&client_list)) {
-               client->client_id = 0;
-       } else {
-               struct ib_client *last;
-
-               last = list_last_entry(&client_list, struct ib_client, list);
-               client->client_id = last->client_id + 1;
-       }
+       client->client_id = highest_client_id;
        ret = xa_insert(&clients, client->client_id, client, GFP_KERNEL);
        if (ret)
                goto out;
 
+       highest_client_id++;
        xa_set_mark(&clients, client->client_id, CLIENT_REGISTERED);
-       list_add_tail(&client->list, &client_list);
 
 out:
        up_write(&clients_rwsem);
        return ret;
 }
 
+static void remove_client_id(struct ib_client *client)
+{
+       down_write(&clients_rwsem);
+       xa_erase(&clients, client->client_id);
+       for (; highest_client_id; highest_client_id--)
+               if (xa_load(&clients, highest_client_id - 1))
+                       break;
+       up_write(&clients_rwsem);
+}
+
 /**
  * ib_register_client - Register an IB client
  * @client:Client to register
@@ -1705,6 +1728,8 @@ int ib_register_client(struct ib_client *client)
        unsigned long index;
        int ret;
 
+       refcount_set(&client->uses, 1);
+       init_completion(&client->uses_zero);
        ret = assign_client_id(client);
        if (ret)
                return ret;
@@ -1740,21 +1765,30 @@ void ib_unregister_client(struct ib_client *client)
        unsigned long index;
 
        down_write(&clients_rwsem);
+       ib_client_put(client);
        xa_clear_mark(&clients, client->client_id, CLIENT_REGISTERED);
        up_write(&clients_rwsem);
-       /*
-        * Every device still known must be serialized to make sure we are
-        * done with the client callbacks before we return.
-        */
-       down_read(&devices_rwsem);
-       xa_for_each (&devices, index, device)
+
+       /* We do not want to have locks while calling client->remove() */
+       rcu_read_lock();
+       xa_for_each (&devices, index, device) {
+               if (!ib_device_try_get(device))
+                       continue;
+               rcu_read_unlock();
+
                remove_client_context(device, client->client_id);
-       up_read(&devices_rwsem);
 
-       down_write(&clients_rwsem);
-       list_del(&client->list);
-       xa_erase(&clients, client->client_id);
-       up_write(&clients_rwsem);
+               ib_device_put(device);
+               rcu_read_lock();
+       }
+       rcu_read_unlock();
+
+       /*
+        * remove_client_context() is not a fence, it can return even though a
+        * removal is ongoing. Wait until all removals are completed.
+        */
+       wait_for_completion(&client->uses_zero);
+       remove_client_id(client);
 }
 EXPORT_SYMBOL(ib_unregister_client);
 
index cc99479b2c09dc9258718aa139a91d45055ade12..9947d16edef210d39145720fef6db1ca6240603e 100644 (file)
@@ -3224,18 +3224,18 @@ static int ib_mad_port_open(struct ib_device *device,
        if (has_smi)
                cq_size *= 2;
 
+       port_priv->pd = ib_alloc_pd(device, 0);
+       if (IS_ERR(port_priv->pd)) {
+               dev_err(&device->dev, "Couldn't create ib_mad PD\n");
+               ret = PTR_ERR(port_priv->pd);
+               goto error3;
+       }
+
        port_priv->cq = ib_alloc_cq(port_priv->device, port_priv, cq_size, 0,
                        IB_POLL_UNBOUND_WORKQUEUE);
        if (IS_ERR(port_priv->cq)) {
                dev_err(&device->dev, "Couldn't create ib_mad CQ\n");
                ret = PTR_ERR(port_priv->cq);
-               goto error3;
-       }
-
-       port_priv->pd = ib_alloc_pd(device, 0);
-       if (IS_ERR(port_priv->pd)) {
-               dev_err(&device->dev, "Couldn't create ib_mad PD\n");
-               ret = PTR_ERR(port_priv->pd);
                goto error4;
        }
 
@@ -3278,11 +3278,11 @@ error8:
 error7:
        destroy_mad_qp(&port_priv->qp_info[0]);
 error6:
-       ib_dealloc_pd(port_priv->pd);
-error4:
        ib_free_cq(port_priv->cq);
        cleanup_recv_queue(&port_priv->qp_info[1]);
        cleanup_recv_queue(&port_priv->qp_info[0]);
+error4:
+       ib_dealloc_pd(port_priv->pd);
 error3:
        kfree(port_priv);
 
@@ -3312,8 +3312,8 @@ static int ib_mad_port_close(struct ib_device *device, int port_num)
        destroy_workqueue(port_priv->wq);
        destroy_mad_qp(&port_priv->qp_info[1]);
        destroy_mad_qp(&port_priv->qp_info[0]);
-       ib_dealloc_pd(port_priv->pd);
        ib_free_cq(port_priv->cq);
+       ib_dealloc_pd(port_priv->pd);
        cleanup_recv_queue(&port_priv->qp_info[1]);
        cleanup_recv_queue(&port_priv->qp_info[0]);
        /* XXX: Handle deallocation of MAD registration tables */
index 783e465e7c412988903088911fa655c4aa169346..020c269765584e9792ddb1f19c64a6971171f3c6 100644 (file)
@@ -382,8 +382,7 @@ static int fill_res_info(struct sk_buff *msg, struct ib_device *device)
        for (i = 0; i < RDMA_RESTRACK_MAX; i++) {
                if (!names[i])
                        continue;
-               curr = rdma_restrack_count(device, i,
-                                          task_active_pid_ns(current));
+               curr = rdma_restrack_count(device, i);
                ret = fill_res_info_entry(msg, names[i], curr);
                if (ret)
                        goto err;
@@ -1952,12 +1951,16 @@ static int stat_get_doit_qp(struct sk_buff *skb, struct nlmsghdr *nlh,
 
        if (fill_nldev_handle(msg, device) ||
            nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
-           nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode))
+           nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode)) {
+               ret = -EMSGSIZE;
                goto err_msg;
+       }
 
        if ((mode == RDMA_COUNTER_MODE_AUTO) &&
-           nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask))
+           nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask)) {
+               ret = -EMSGSIZE;
                goto err_msg;
+       }
 
        nlmsg_end(msg, nlh);
        ib_device_put(device);
index bddff426ee0f0d37dfb32a9e03f97dc9cde7a9ad..a07665f7ef8ceffa81d9dd1ede9b4c71e4c977b7 100644 (file)
@@ -107,10 +107,8 @@ void rdma_restrack_clean(struct ib_device *dev)
  * rdma_restrack_count() - the current usage of specific object
  * @dev:  IB device
  * @type: actual type of object to operate
- * @ns:   PID namespace
  */
-int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
-                       struct pid_namespace *ns)
+int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type)
 {
        struct rdma_restrack_root *rt = &dev->res[type];
        struct rdma_restrack_entry *e;
@@ -119,10 +117,9 @@ int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
 
        xa_lock(&rt->xa);
        xas_for_each(&xas, e, U32_MAX) {
-               if (ns == &init_pid_ns ||
-                   (!rdma_is_kernel_res(e) &&
-                    ns == task_active_pid_ns(e->task)))
-                       cnt++;
+               if (!rdma_is_visible_in_pid_ns(e))
+                       continue;
+               cnt++;
        }
        xa_unlock(&rt->xa);
        return cnt;
@@ -360,5 +357,7 @@ bool rdma_is_visible_in_pid_ns(struct rdma_restrack_entry *res)
         */
        if (rdma_is_kernel_res(res))
                return task_active_pid_ns(current) == &init_pid_ns;
-       return task_active_pid_ns(current) == task_active_pid_ns(res->task);
+
+       /* PID 0 means that resource is not found in current namespace */
+       return task_pid_vnr(res->task);
 }
index 08da840ed7eebc151b67a61b15626d90578dea54..56553668256f5e9279de8676ce3f2d443391db30 100644 (file)
@@ -379,14 +379,9 @@ EXPORT_SYMBOL(ib_umem_release);
 
 int ib_umem_page_count(struct ib_umem *umem)
 {
-       int i;
-       int n;
+       int i, n = 0;
        struct scatterlist *sg;
 
-       if (umem->is_odp)
-               return ib_umem_num_pages(umem);
-
-       n = 0;
        for_each_sg(umem->sg_head.sgl, sg, umem->nmap, i)
                n += sg_dma_len(sg) >> PAGE_SHIFT;
 
index 2a75c6f8d8270e5ca07610684fbe9e5156f72708..c0e15db346808db3efc8222eddb14abc1212be05 100644 (file)
@@ -112,10 +112,6 @@ static int ib_umem_notifier_release_trampoline(struct ib_umem_odp *umem_odp,
         * prevent any further fault handling on this MR.
         */
        ib_umem_notifier_start_account(umem_odp);
-       umem_odp->dying = 1;
-       /* Make sure that the fact the umem is dying is out before we release
-        * all pending page faults. */
-       smp_wmb();
        complete_all(&umem_odp->notifier_completion);
        umem_odp->umem.context->invalidate_range(
                umem_odp, ib_umem_start(umem_odp), ib_umem_end(umem_odp));
index 9f8a48016b4152a248f781d69760ce4fa433897c..ffdeaf6e0b686881bfa563ec0af80fca5e5cb4d5 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/sched.h>
 #include <linux/semaphore.h>
 #include <linux/slab.h>
+#include <linux/nospec.h>
 
 #include <linux/uaccess.h>
 
@@ -884,11 +885,14 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
 
        if (get_user(id, arg))
                return -EFAULT;
+       if (id >= IB_UMAD_MAX_AGENTS)
+               return -EINVAL;
 
        mutex_lock(&file->port->file_mutex);
        mutex_lock(&file->mutex);
 
-       if (id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
+       id = array_index_nospec(id, IB_UMAD_MAX_AGENTS);
+       if (!__get_agent(file, id)) {
                ret = -EINVAL;
                goto out;
        }
index a91653aabf3899d9c7e3f5dc4be6ab8ff168ac6c..098ab883733eeef71243852940567788eca3cbc2 100644 (file)
@@ -308,6 +308,7 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
        struct bnxt_re_dev *rdev = to_bnxt_re_dev(attr->device, ibdev);
        struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl;
        struct bnxt_qplib_gid *gid_to_del;
+       u16 vlan_id = 0xFFFF;
 
        /* Delete the entry from the hardware */
        ctx = *context;
@@ -317,7 +318,8 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
        if (sgid_tbl && sgid_tbl->active) {
                if (ctx->idx >= sgid_tbl->max)
                        return -EINVAL;
-               gid_to_del = &sgid_tbl->tbl[ctx->idx];
+               gid_to_del = &sgid_tbl->tbl[ctx->idx].gid;
+               vlan_id = sgid_tbl->tbl[ctx->idx].vlan_id;
                /* 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
@@ -335,7 +337,8 @@ int bnxt_re_del_gid(const struct ib_gid_attr *attr, void **context)
                }
                ctx->refcnt--;
                if (!ctx->refcnt) {
-                       rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del, true);
+                       rc = bnxt_qplib_del_sgid(sgid_tbl, gid_to_del,
+                                                vlan_id,  true);
                        if (rc) {
                                dev_err(rdev_to_dev(rdev),
                                        "Failed to remove GID: %#x", rc);
index 48b04d2f175f908e984c12fda163237cf56876b5..60c8f76aab33d9d7307bb57391736ace8a782dbd 100644 (file)
@@ -136,6 +136,13 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
                spin_unlock_irqrestore(&cmdq->lock, flags);
                return -EBUSY;
        }
+
+       size = req->cmd_size;
+       /* change the cmd_size to the number of 16byte cmdq unit.
+        * req->cmd_size is modified here
+        */
+       bnxt_qplib_set_cmd_slots(req);
+
        memset(resp, 0, sizeof(*resp));
        crsqe->resp = (struct creq_qp_event *)resp;
        crsqe->resp->cookie = req->cookie;
@@ -150,7 +157,6 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
 
        cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
        preq = (u8 *)req;
-       size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
        do {
                /* Locate the next cmdq slot */
                sw_prod = HWQ_CMP(cmdq->prod, cmdq);
index 2138533bb64267e15e1efbea099ccdf084ce6ccd..dfeadc192e17401525de94f23080ba287ad21503 100644 (file)
@@ -55,9 +55,7 @@
        do {                                                            \
                memset(&(req), 0, sizeof((req)));                       \
                (req).opcode = CMDQ_BASE_OPCODE_##CMD;                  \
-               (req).cmd_size = (sizeof((req)) +                       \
-                               BNXT_QPLIB_CMDQE_UNITS - 1) /           \
-                               BNXT_QPLIB_CMDQE_UNITS;                 \
+               (req).cmd_size = sizeof((req));                         \
                (req).flags = cpu_to_le16(cmd_flags);                   \
        } while (0)
 
@@ -95,6 +93,13 @@ static inline u32 bnxt_qplib_cmdqe_cnt_per_pg(u32 depth)
                 BNXT_QPLIB_CMDQE_UNITS);
 }
 
+/* Set the cmd_size to a factor of CMDQE unit */
+static inline void bnxt_qplib_set_cmd_slots(struct cmdq_base *req)
+{
+       req->cmd_size = (req->cmd_size + BNXT_QPLIB_CMDQE_UNITS - 1) /
+                        BNXT_QPLIB_CMDQE_UNITS;
+}
+
 #define MAX_CMDQ_IDX(depth)            ((depth) - 1)
 
 static inline u32 bnxt_qplib_max_cmdq_idx_per_pg(u32 depth)
index 37928b1111dfc403221983607bab90d2e3326163..bdbde8e22420d39042a91770a36cd2f6c6399c60 100644 (file)
@@ -488,7 +488,7 @@ static int bnxt_qplib_alloc_sgid_tbl(struct bnxt_qplib_res *res,
                                     struct bnxt_qplib_sgid_tbl *sgid_tbl,
                                     u16 max)
 {
-       sgid_tbl->tbl = kcalloc(max, sizeof(struct bnxt_qplib_gid), GFP_KERNEL);
+       sgid_tbl->tbl = kcalloc(max, sizeof(*sgid_tbl->tbl), GFP_KERNEL);
        if (!sgid_tbl->tbl)
                return -ENOMEM;
 
@@ -526,9 +526,10 @@ static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res,
        for (i = 0; i < sgid_tbl->max; i++) {
                if (memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero,
                           sizeof(bnxt_qplib_gid_zero)))
-                       bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i], true);
+                       bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i].gid,
+                                           sgid_tbl->tbl[i].vlan_id, true);
        }
-       memset(sgid_tbl->tbl, 0, sizeof(struct bnxt_qplib_gid) * sgid_tbl->max);
+       memset(sgid_tbl->tbl, 0, sizeof(*sgid_tbl->tbl) * sgid_tbl->max);
        memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max);
        memset(sgid_tbl->vlan, 0, sizeof(u8) * sgid_tbl->max);
        sgid_tbl->active = 0;
@@ -537,7 +538,11 @@ static void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res,
 static void bnxt_qplib_init_sgid_tbl(struct bnxt_qplib_sgid_tbl *sgid_tbl,
                                     struct net_device *netdev)
 {
-       memset(sgid_tbl->tbl, 0, sizeof(struct bnxt_qplib_gid) * sgid_tbl->max);
+       u32 i;
+
+       for (i = 0; i < sgid_tbl->max; i++)
+               sgid_tbl->tbl[i].vlan_id = 0xffff;
+
        memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max);
 }
 
index 30c42c92fac72fc91752cb005015bcccdf48d4cf..fbda11a7ab1aa450a0a8099a7a4c1c7ed30ce81b 100644 (file)
@@ -111,7 +111,7 @@ struct bnxt_qplib_pd_tbl {
 };
 
 struct bnxt_qplib_sgid_tbl {
-       struct bnxt_qplib_gid           *tbl;
+       struct bnxt_qplib_gid_info      *tbl;
        u16                             *hw_id;
        u16                             max;
        u16                             active;
index 48793d3512ac4ef5ff6776c44cb20bf94275f097..40296b97d21e6c1534dbe82c4164e57ed78c9018 100644 (file)
@@ -213,12 +213,12 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
                        index, sgid_tbl->max);
                return -EINVAL;
        }
-       memcpy(gid, &sgid_tbl->tbl[index], sizeof(*gid));
+       memcpy(gid, &sgid_tbl->tbl[index].gid, sizeof(*gid));
        return 0;
 }
 
 int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
-                       struct bnxt_qplib_gid *gid, bool update)
+                       struct bnxt_qplib_gid *gid, u16 vlan_id, bool update)
 {
        struct bnxt_qplib_res *res = to_bnxt_qplib(sgid_tbl,
                                                   struct bnxt_qplib_res,
@@ -236,7 +236,8 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
                return -ENOMEM;
        }
        for (index = 0; index < sgid_tbl->max; index++) {
-               if (!memcmp(&sgid_tbl->tbl[index], gid, sizeof(*gid)))
+               if (!memcmp(&sgid_tbl->tbl[index].gid, gid, sizeof(*gid)) &&
+                   vlan_id == sgid_tbl->tbl[index].vlan_id)
                        break;
        }
        if (index == sgid_tbl->max) {
@@ -262,8 +263,9 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
                if (rc)
                        return rc;
        }
-       memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero,
+       memcpy(&sgid_tbl->tbl[index].gid, &bnxt_qplib_gid_zero,
               sizeof(bnxt_qplib_gid_zero));
+       sgid_tbl->tbl[index].vlan_id = 0xFFFF;
        sgid_tbl->vlan[index] = 0;
        sgid_tbl->active--;
        dev_dbg(&res->pdev->dev,
@@ -296,7 +298,8 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
        }
        free_idx = sgid_tbl->max;
        for (i = 0; i < sgid_tbl->max; i++) {
-               if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid))) {
+               if (!memcmp(&sgid_tbl->tbl[i], gid, sizeof(*gid)) &&
+                   sgid_tbl->tbl[i].vlan_id == vlan_id) {
                        dev_dbg(&res->pdev->dev,
                                "SGID entry already exist in entry %d!\n", i);
                        *index = i;
@@ -351,6 +354,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
        }
        /* Add GID to the sgid_tbl */
        memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
+       sgid_tbl->tbl[free_idx].vlan_id = vlan_id;
        sgid_tbl->active++;
        if (vlan_id != 0xFFFF)
                sgid_tbl->vlan[free_idx] = 1;
index 0ec3b12b0bcd4da3417e20daf706fa9e505e139c..13d9432d5ce2220e0f78bcfada846c9f74455ac0 100644 (file)
@@ -84,6 +84,11 @@ struct bnxt_qplib_gid {
        u8                              data[16];
 };
 
+struct bnxt_qplib_gid_info {
+       struct bnxt_qplib_gid gid;
+       u16 vlan_id;
+};
+
 struct bnxt_qplib_ah {
        struct bnxt_qplib_gid           dgid;
        struct bnxt_qplib_pd            *pd;
@@ -221,7 +226,7 @@ int bnxt_qplib_get_sgid(struct bnxt_qplib_res *res,
                        struct bnxt_qplib_sgid_tbl *sgid_tbl, int index,
                        struct bnxt_qplib_gid *gid);
 int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
-                       struct bnxt_qplib_gid *gid, bool update);
+                       struct bnxt_qplib_gid *gid, u16 vlan_id, bool update);
 int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
                        struct bnxt_qplib_gid *gid, u8 *mac, u16 vlan_id,
                        bool update, u32 *index);
index d5b643a1d9fd2e11365787a93eeace5cd35f3bc8..67052dc3100ce3e13b19ba48cfcd3c01dcc631b9 100644 (file)
@@ -14452,7 +14452,7 @@ void hfi1_deinit_vnic_rsm(struct hfi1_devdata *dd)
                clear_rcvctrl(dd, RCV_CTRL_RCV_RSM_ENABLE_SMASK);
 }
 
-static void init_rxe(struct hfi1_devdata *dd)
+static int init_rxe(struct hfi1_devdata *dd)
 {
        struct rsm_map_table *rmt;
        u64 val;
@@ -14461,6 +14461,9 @@ static void init_rxe(struct hfi1_devdata *dd)
        write_csr(dd, RCV_ERR_MASK, ~0ull);
 
        rmt = alloc_rsm_map_table(dd);
+       if (!rmt)
+               return -ENOMEM;
+
        /* set up QOS, including the QPN map table */
        init_qos(dd, rmt);
        init_fecn_handling(dd, rmt);
@@ -14487,6 +14490,7 @@ static void init_rxe(struct hfi1_devdata *dd)
        val |= ((4ull & RCV_BYPASS_HDR_SIZE_MASK) <<
                RCV_BYPASS_HDR_SIZE_SHIFT);
        write_csr(dd, RCV_BYPASS, val);
+       return 0;
 }
 
 static void init_other(struct hfi1_devdata *dd)
@@ -15024,7 +15028,10 @@ int hfi1_init_dd(struct hfi1_devdata *dd)
                goto bail_cleanup;
 
        /* set initial RXE CSRs */
-       init_rxe(dd);
+       ret = init_rxe(dd);
+       if (ret)
+               goto bail_cleanup;
+
        /* set initial TXE CSRs */
        init_txe(dd);
        /* set initial non-RXE, non-TXE CSRs */
index 93613e5def9b7bd4492e65494abd4d420fc5a6c1..986c12153e62ecbe03e99a421355188fbf08c47f 100644 (file)
@@ -141,12 +141,14 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
        if (!data)
                return -ENOMEM;
        copy = min(len, datalen - 1);
-       if (copy_from_user(data, buf, copy))
-               return -EFAULT;
+       if (copy_from_user(data, buf, copy)) {
+               ret = -EFAULT;
+               goto free_data;
+       }
 
        ret = debugfs_file_get(file->f_path.dentry);
        if (unlikely(ret))
-               return ret;
+               goto free_data;
        ptr = data;
        token = ptr;
        for (ptr = data; *ptr; ptr = end + 1, token = ptr) {
@@ -195,6 +197,7 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
        ret = len;
 
        debugfs_file_put(file->f_path.dentry);
+free_data:
        kfree(data);
        return ret;
 }
@@ -214,7 +217,7 @@ static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
                return -ENOMEM;
        ret = debugfs_file_get(file->f_path.dentry);
        if (unlikely(ret))
-               return ret;
+               goto free_data;
        bit = find_first_bit(fault->opcodes, bitsize);
        while (bit < bitsize) {
                zero = find_next_zero_bit(fault->opcodes, bitsize, bit);
@@ -232,6 +235,7 @@ static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
        data[size - 1] = '\n';
        data[size] = '\0';
        ret = simple_read_from_buffer(buf, len, pos, data, size);
+free_data:
        kfree(data);
        return ret;
 }
index 0477c14633ab8365849a8eecb24d2f0bcafb4feb..024a7c2b6124563cbd317b10cc3c0210b9de1b2e 100644 (file)
@@ -1835,7 +1835,6 @@ void hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_opa_header *opah)
                    cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)
                        break;
                trdma_clean_swqe(qp, wqe);
-               rvt_qp_wqe_unreserve(qp, wqe);
                trace_hfi1_qp_send_completion(qp, wqe, qp->s_last);
                rvt_qp_complete_swqe(qp,
                                     wqe,
@@ -1882,7 +1881,6 @@ struct rvt_swqe *do_rc_completion(struct rvt_qp *qp,
        if (cmp_psn(wqe->lpsn, qp->s_sending_psn) < 0 ||
            cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) > 0) {
                trdma_clean_swqe(qp, wqe);
-               rvt_qp_wqe_unreserve(qp, wqe);
                trace_hfi1_qp_send_completion(qp, wqe, qp->s_last);
                rvt_qp_complete_swqe(qp,
                                     wqe,
index 92acccaaaa86d66dd233cb8fee5ba8b8cf1537be..6141f4edc6bfa00423b757631fa22aeb43485cd1 100644 (file)
@@ -1620,6 +1620,7 @@ static int hfi1_kern_exp_rcv_alloc_flows(struct tid_rdma_request *req,
                flows[i].req = req;
                flows[i].npagesets = 0;
                flows[i].pagesets[0].mapped =  0;
+               flows[i].resync_npkts = 0;
        }
        req->flows = flows;
        return 0;
@@ -1673,34 +1674,6 @@ static struct tid_rdma_flow *find_flow_ib(struct tid_rdma_request *req,
        return NULL;
 }
 
-static struct tid_rdma_flow *
-__find_flow_ranged(struct tid_rdma_request *req, u16 head, u16 tail,
-                  u32 psn, u16 *fidx)
-{
-       for ( ; CIRC_CNT(head, tail, MAX_FLOWS);
-             tail = CIRC_NEXT(tail, MAX_FLOWS)) {
-               struct tid_rdma_flow *flow = &req->flows[tail];
-               u32 spsn, lpsn;
-
-               spsn = full_flow_psn(flow, flow->flow_state.spsn);
-               lpsn = full_flow_psn(flow, flow->flow_state.lpsn);
-
-               if (cmp_psn(psn, spsn) >= 0 && cmp_psn(psn, lpsn) <= 0) {
-                       if (fidx)
-                               *fidx = tail;
-                       return flow;
-               }
-       }
-       return NULL;
-}
-
-static struct tid_rdma_flow *find_flow(struct tid_rdma_request *req,
-                                      u32 psn, u16 *fidx)
-{
-       return __find_flow_ranged(req, req->setup_head, req->clear_tail, psn,
-                                 fidx);
-}
-
 /* TID RDMA READ functions */
 u32 hfi1_build_tid_rdma_read_packet(struct rvt_swqe *wqe,
                                    struct ib_other_headers *ohdr, u32 *bth1,
@@ -2601,18 +2574,9 @@ void hfi1_kern_read_tid_flow_free(struct rvt_qp *qp)
        hfi1_kern_clear_hw_flow(priv->rcd, qp);
 }
 
-static bool tid_rdma_tid_err(struct hfi1_ctxtdata *rcd,
-                            struct hfi1_packet *packet, u8 rcv_type,
-                            u8 opcode)
+static bool tid_rdma_tid_err(struct hfi1_packet *packet, u8 rcv_type)
 {
        struct rvt_qp *qp = packet->qp;
-       struct hfi1_qp_priv *qpriv = qp->priv;
-       u32 ipsn;
-       struct ib_other_headers *ohdr = packet->ohdr;
-       struct rvt_ack_entry *e;
-       struct tid_rdma_request *req;
-       struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
-       u32 i;
 
        if (rcv_type >= RHF_RCV_TYPE_IB)
                goto done;
@@ -2629,41 +2593,9 @@ static bool tid_rdma_tid_err(struct hfi1_ctxtdata *rcd,
        if (rcv_type == RHF_RCV_TYPE_EAGER) {
                hfi1_restart_rc(qp, qp->s_last_psn + 1, 1);
                hfi1_schedule_send(qp);
-               goto done_unlock;
-       }
-
-       /*
-        * For TID READ response, error out QP after freeing the tid
-        * resources.
-        */
-       if (opcode == TID_OP(READ_RESP)) {
-               ipsn = mask_psn(be32_to_cpu(ohdr->u.tid_rdma.r_rsp.verbs_psn));
-               if (cmp_psn(ipsn, qp->s_last_psn) > 0 &&
-                   cmp_psn(ipsn, qp->s_psn) < 0) {
-                       hfi1_kern_read_tid_flow_free(qp);
-                       spin_unlock(&qp->s_lock);
-                       rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
-                       goto done;
-               }
-               goto done_unlock;
        }
 
-       /*
-        * Error out the qp for TID RDMA WRITE
-        */
-       hfi1_kern_clear_hw_flow(qpriv->rcd, qp);
-       for (i = 0; i < rvt_max_atomic(rdi); i++) {
-               e = &qp->s_ack_queue[i];
-               if (e->opcode == TID_OP(WRITE_REQ)) {
-                       req = ack_to_tid_req(e);
-                       hfi1_kern_exp_rcv_clear_all(req);
-               }
-       }
-       spin_unlock(&qp->s_lock);
-       rvt_rc_error(qp, IB_WC_LOC_LEN_ERR);
-       goto done;
-
-done_unlock:
+       /* Since no payload is delivered, just drop the packet */
        spin_unlock(&qp->s_lock);
 done:
        return true;
@@ -2714,12 +2646,12 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
        u32 fpsn;
 
        lockdep_assert_held(&qp->r_lock);
+       spin_lock(&qp->s_lock);
        /* If the psn is out of valid range, drop the packet */
        if (cmp_psn(ibpsn, qp->s_last_psn) < 0 ||
            cmp_psn(ibpsn, qp->s_psn) > 0)
-               return ret;
+               goto s_unlock;
 
-       spin_lock(&qp->s_lock);
        /*
         * Note that NAKs implicitly ACK outstanding SEND and RDMA write
         * requests and implicitly NAK RDMA read and atomic requests issued
@@ -2767,9 +2699,12 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
 
                wqe = do_rc_completion(qp, wqe, ibp);
                if (qp->s_acked == qp->s_tail)
-                       break;
+                       goto s_unlock;
        }
 
+       if (qp->s_acked == qp->s_tail)
+               goto s_unlock;
+
        /* Handle the eflags for the request */
        if (wqe->wr.opcode != IB_WR_TID_RDMA_READ)
                goto s_unlock;
@@ -2788,19 +2723,7 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
                         * to prevent continuous Flow Sequence errors for any
                         * packets that could be still in the fabric.
                         */
-                       flow = find_flow(req, psn, NULL);
-                       if (!flow) {
-                               /*
-                                * We can't find the IB PSN matching the
-                                * received KDETH PSN. The only thing we can
-                                * do at this point is report the error to
-                                * the QP.
-                                */
-                               hfi1_kern_read_tid_flow_free(qp);
-                               spin_unlock(&qp->s_lock);
-                               rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
-                               return ret;
-                       }
+                       flow = &req->flows[req->clear_tail];
                        if (priv->s_flags & HFI1_R_TID_SW_PSN) {
                                diff = cmp_psn(psn,
                                               flow->flow_state.r_next_psn);
@@ -2961,7 +2884,7 @@ bool hfi1_handle_kdeth_eflags(struct hfi1_ctxtdata *rcd,
                if (lnh == HFI1_LRH_GRH)
                        goto r_unlock;
 
-               if (tid_rdma_tid_err(rcd, packet, rcv_type, opcode))
+               if (tid_rdma_tid_err(packet, rcv_type))
                        goto r_unlock;
        }
 
@@ -2981,8 +2904,15 @@ bool hfi1_handle_kdeth_eflags(struct hfi1_ctxtdata *rcd,
         */
        spin_lock(&qp->s_lock);
        qpriv = qp->priv;
+       if (qpriv->r_tid_tail == HFI1_QP_WQE_INVALID ||
+           qpriv->r_tid_tail == qpriv->r_tid_head)
+               goto unlock;
        e = &qp->s_ack_queue[qpriv->r_tid_tail];
+       if (e->opcode != TID_OP(WRITE_REQ))
+               goto unlock;
        req = ack_to_tid_req(e);
+       if (req->comp_seg == req->cur_seg)
+               goto unlock;
        flow = &req->flows[req->clear_tail];
        trace_hfi1_eflags_err_write(qp, rcv_type, rte, psn);
        trace_hfi1_rsp_handle_kdeth_eflags(qp, psn);
@@ -4548,7 +4478,7 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
        struct rvt_swqe *wqe;
        struct tid_rdma_request *req;
        struct tid_rdma_flow *flow;
-       u32 aeth, psn, req_psn, ack_psn, resync_psn, ack_kpsn;
+       u32 aeth, psn, req_psn, ack_psn, flpsn, resync_psn, ack_kpsn;
        unsigned long flags;
        u16 fidx;
 
@@ -4577,6 +4507,9 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
                ack_kpsn--;
        }
 
+       if (unlikely(qp->s_acked == qp->s_tail))
+               goto ack_op_err;
+
        wqe = rvt_get_swqe_ptr(qp, qp->s_acked);
 
        if (wqe->wr.opcode != IB_WR_TID_RDMA_WRITE)
@@ -4589,7 +4522,8 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
        trace_hfi1_tid_flow_rcv_tid_ack(qp, req->acked_tail, flow);
 
        /* Drop stale ACK/NAK */
-       if (cmp_psn(psn, full_flow_psn(flow, flow->flow_state.spsn)) < 0)
+       if (cmp_psn(psn, full_flow_psn(flow, flow->flow_state.spsn)) < 0 ||
+           cmp_psn(req_psn, flow->flow_state.resp_ib_psn) < 0)
                goto ack_op_err;
 
        while (cmp_psn(ack_kpsn,
@@ -4751,7 +4685,12 @@ done:
                switch ((aeth >> IB_AETH_CREDIT_SHIFT) &
                        IB_AETH_CREDIT_MASK) {
                case 0: /* PSN sequence error */
+                       if (!req->flows)
+                               break;
                        flow = &req->flows[req->acked_tail];
+                       flpsn = full_flow_psn(flow, flow->flow_state.lpsn);
+                       if (cmp_psn(psn, flpsn) > 0)
+                               break;
                        trace_hfi1_tid_flow_rcv_tid_ack(qp, req->acked_tail,
                                                        flow);
                        req->r_ack_psn = mask_psn(be32_to_cpu(ohdr->bth[2]));
index c4b243f50c76d660b18922035c4f51ec8b89e177..646f61545ed6be6b76998f0700d2185df22a81e5 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <rdma/opa_addr.h>
+#include <linux/nospec.h>
 
 #include "hfi.h"
 #include "common.h"
@@ -1536,6 +1537,7 @@ static int hfi1_check_ah(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr)
        sl = rdma_ah_get_sl(ah_attr);
        if (sl >= ARRAY_SIZE(ibp->sl_to_sc))
                return -EINVAL;
+       sl = array_index_nospec(sl, ARRAY_SIZE(ibp->sl_to_sc));
 
        sc5 = ibp->sl_to_sc[sl];
        if (sc_to_vlt(dd, sc5) > num_vls && sc_to_vlt(dd, sc5) != 0xf)
index 8bf847bcd8d3267d3581224d5a20d94126955d57..54782197c7172da17763fc5a2d747af31c4df4f5 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config INFINIBAND_HNS
-       tristate "HNS RoCE Driver"
+       bool "HNS RoCE Driver"
        depends on NET_VENDOR_HISILICON
        depends on ARM64 || (COMPILE_TEST && 64BIT)
        ---help---
@@ -11,7 +11,7 @@ config INFINIBAND_HNS
          To compile HIP06 or HIP08 driver as module, choose M here.
 
 config INFINIBAND_HNS_HIP06
-       bool "Hisilicon Hip06 Family RoCE support"
+       tristate "Hisilicon Hip06 Family RoCE support"
        depends on INFINIBAND_HNS && HNS && HNS_DSAF && HNS_ENET
        ---help---
          RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip06 and
@@ -21,7 +21,7 @@ config INFINIBAND_HNS_HIP06
          module will be called hns-roce-hw-v1
 
 config INFINIBAND_HNS_HIP08
-       bool "Hisilicon Hip08 Family RoCE support"
+       tristate "Hisilicon Hip08 Family RoCE support"
        depends on INFINIBAND_HNS && PCI && HNS3
        ---help---
          RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip08 SoC.
index e105945b94a11e4d1cd2e360e613335c846a3ea9..449a2d81319dd3ab4658eb19b8f6d03192356bb8 100644 (file)
@@ -9,12 +9,8 @@ hns-roce-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \
        hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
        hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o hns_roce_srq.o hns_roce_restrack.o
 
-ifdef CONFIG_INFINIBAND_HNS_HIP06
 hns-roce-hw-v1-objs := hns_roce_hw_v1.o $(hns-roce-objs)
-obj-$(CONFIG_INFINIBAND_HNS) += hns-roce-hw-v1.o
-endif
+obj-$(CONFIG_INFINIBAND_HNS_HIP06) += hns-roce-hw-v1.o
 
-ifdef CONFIG_INFINIBAND_HNS_HIP08
 hns-roce-hw-v2-objs := hns_roce_hw_v2.o hns_roce_hw_v2_dfx.o $(hns-roce-objs)
-obj-$(CONFIG_INFINIBAND_HNS) += hns-roce-hw-v2.o
-endif
+obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
index 627aa46ef683b8ec4467acc1404033f21822f627..c00714c2f16a60ca4c9a92c8148f73add6dddc56 100644 (file)
@@ -12,13 +12,15 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
                         struct ib_udata *udata, unsigned long virt,
                         struct hns_roce_db *db)
 {
+       unsigned long page_addr = virt & PAGE_MASK;
        struct hns_roce_user_db_page *page;
+       unsigned int offset;
        int ret = 0;
 
        mutex_lock(&context->page_mutex);
 
        list_for_each_entry(page, &context->page_list, list)
-               if (page->user_virt == (virt & PAGE_MASK))
+               if (page->user_virt == page_addr)
                        goto found;
 
        page = kmalloc(sizeof(*page), GFP_KERNEL);
@@ -28,8 +30,8 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
        }
 
        refcount_set(&page->refcount, 1);
-       page->user_virt = (virt & PAGE_MASK);
-       page->umem = ib_umem_get(udata, virt & PAGE_MASK, PAGE_SIZE, 0, 0);
+       page->user_virt = page_addr;
+       page->umem = ib_umem_get(udata, page_addr, PAGE_SIZE, 0, 0);
        if (IS_ERR(page->umem)) {
                ret = PTR_ERR(page->umem);
                kfree(page);
@@ -39,10 +41,9 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context,
        list_add(&page->list, &context->page_list);
 
 found:
-       db->dma = sg_dma_address(page->umem->sg_head.sgl) +
-                 (virt & ~PAGE_MASK);
-       page->umem->sg_head.sgl->offset = virt & ~PAGE_MASK;
-       db->virt_addr = sg_virt(page->umem->sg_head.sgl);
+       offset = virt - page_addr;
+       db->dma = sg_dma_address(page->umem->sg_head.sgl) + offset;
+       db->virt_addr = sg_virt(page->umem->sg_head.sgl) + offset;
        db->u.user_page = page;
        refcount_inc(&page->refcount);
 
index 81e6dedb1e022c81990ee7e01bc80a0a7b9ec3f9..c07e387a07a38b88a02d175e6ddd889e13ef00bf 100644 (file)
@@ -750,8 +750,10 @@ static int hns_roce_v1_rsv_lp_qp(struct hns_roce_dev *hr_dev)
        atomic_set(&free_mr->mr_free_cq->ib_cq.usecnt, 0);
 
        pd = rdma_zalloc_drv_obj(ibdev, ib_pd);
-       if (!pd)
+       if (!pd) {
+               ret = -ENOMEM;
                goto alloc_mem_failed;
+       }
 
        pd->device  = ibdev;
        ret = hns_roce_alloc_pd(pd, NULL);
index 68c951491a08af9d34ed6c88410fc6a440f1c01b..57079110af9b5fb95fb1aaf4d13d8ae8aebc34e1 100644 (file)
@@ -1677,8 +1677,6 @@ tx_err:
                                    tx_buf_size, DMA_TO_DEVICE);
                kfree(tun_qp->tx_ring[i].buf.addr);
        }
-       kfree(tun_qp->tx_ring);
-       tun_qp->tx_ring = NULL;
        i = MLX4_NUM_TUNNEL_BUFS;
 err:
        while (i > 0) {
@@ -1687,6 +1685,8 @@ err:
                                    rx_buf_size, DMA_FROM_DEVICE);
                kfree(tun_qp->ring[i].addr);
        }
+       kfree(tun_qp->tx_ring);
+       tun_qp->tx_ring = NULL;
        kfree(tun_qp->ring);
        tun_qp->ring = NULL;
        return -ENOMEM;
index ec4370f9938127f94d70533f2ebf8cc9f44b48a2..af5bbb35c0589364794ca131a1e741392cfe5931 100644 (file)
@@ -2026,7 +2026,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(
                        event_sub->eventfd =
                                eventfd_ctx_fdget(redirect_fd);
 
-                       if (IS_ERR(event_sub)) {
+                       if (IS_ERR(event_sub->eventfd)) {
                                err = PTR_ERR(event_sub->eventfd);
                                event_sub->eventfd = NULL;
                                goto err;
@@ -2644,12 +2644,13 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
        struct devx_async_event_file *ev_file = filp->private_data;
        struct devx_event_subscription *event_sub, *event_sub_tmp;
        struct devx_async_event_data *entry, *tmp;
+       struct mlx5_ib_dev *dev = ev_file->dev;
 
-       mutex_lock(&ev_file->dev->devx_event_table.event_xa_lock);
+       mutex_lock(&dev->devx_event_table.event_xa_lock);
        /* delete the subscriptions which are related to this FD */
        list_for_each_entry_safe(event_sub, event_sub_tmp,
                                 &ev_file->subscribed_events_list, file_list) {
-               devx_cleanup_subscription(ev_file->dev, event_sub);
+               devx_cleanup_subscription(dev, event_sub);
                if (event_sub->eventfd)
                        eventfd_ctx_put(event_sub->eventfd);
 
@@ -2658,7 +2659,7 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
                kfree_rcu(event_sub, rcu);
        }
 
-       mutex_unlock(&ev_file->dev->devx_event_table.event_xa_lock);
+       mutex_unlock(&dev->devx_event_table.event_xa_lock);
 
        /* free the pending events allocation */
        if (!ev_file->omit_data) {
@@ -2670,7 +2671,7 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
        }
 
        uverbs_close_fd(filp);
-       put_device(&ev_file->dev->ib_dev.dev);
+       put_device(&dev->ib_dev.dev);
        return 0;
 }
 
index c2a5780cb394e64b013fbeff00e78eb7e3361287..0569bcab02d4811d6d84ab986fa17c14b2e7a6da 100644 (file)
@@ -1023,7 +1023,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
        props->timestamp_mask = 0x7FFFFFFFFFFFFFFFULL;
 
        if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
-               if (MLX5_CAP_GEN(mdev, pg))
+               if (dev->odp_caps.general_caps & IB_ODP_SUPPORT)
                        props->device_cap_flags |= IB_DEVICE_ON_DEMAND_PAGING;
                props->odp_caps = dev->odp_caps;
        }
@@ -5802,13 +5802,12 @@ static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev,
                return;
        }
 
-       if (mpi->mdev_events.notifier_call)
-               mlx5_notifier_unregister(mpi->mdev, &mpi->mdev_events);
-       mpi->mdev_events.notifier_call = NULL;
-
        mpi->ibdev = NULL;
 
        spin_unlock(&port->mp.mpi_lock);
+       if (mpi->mdev_events.notifier_call)
+               mlx5_notifier_unregister(mpi->mdev, &mpi->mdev_events);
+       mpi->mdev_events.notifier_call = NULL;
        mlx5_remove_netdev_notifier(ibdev, port_num);
        spin_lock(&port->mp.mpi_lock);
 
@@ -6140,6 +6139,8 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
                dev->port[i].roce.last_port_state = IB_PORT_DOWN;
        }
 
+       mlx5_ib_internal_fill_odp_caps(dev);
+
        err = mlx5_ib_init_multiport_master(dev);
        if (err)
                return err;
@@ -6564,8 +6565,6 @@ static void mlx5_ib_stage_dev_res_cleanup(struct mlx5_ib_dev *dev)
 
 static int mlx5_ib_stage_odp_init(struct mlx5_ib_dev *dev)
 {
-       mlx5_ib_internal_fill_odp_caps(dev);
-
        return mlx5_ib_odp_init_one(dev);
 }
 
index fe1a76d8531cee8b5d7e347c54fdbc1c51caaac3..a40e0abf233809c9c168b0a58d9e7f2b6c076614 100644 (file)
@@ -57,9 +57,10 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
        int entry;
 
        if (umem->is_odp) {
-               unsigned int page_shift = to_ib_umem_odp(umem)->page_shift;
+               struct ib_umem_odp *odp = to_ib_umem_odp(umem);
+               unsigned int page_shift = odp->page_shift;
 
-               *ncont = ib_umem_page_count(umem);
+               *ncont = ib_umem_odp_num_pages(odp);
                *count = *ncont << (page_shift - PAGE_SHIFT);
                *shift = page_shift;
                if (order)
index c482f19958b39754555e8c74cb31906a95a1992a..9ae587b74b121ddc637ad22b697a141e25cf3878 100644 (file)
@@ -481,6 +481,7 @@ struct mlx5_umr_wr {
        u64                             length;
        int                             access_flags;
        u32                             mkey;
+       u8                              ignore_free_state:1;
 };
 
 static inline const struct mlx5_umr_wr *umr_wr(const struct ib_send_wr *wr)
@@ -1474,4 +1475,18 @@ int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
                        bool dyn_bfreg);
 
 int mlx5_ib_qp_set_counter(struct ib_qp *qp, struct rdma_counter *counter);
+
+static inline bool mlx5_ib_can_use_umr(struct mlx5_ib_dev *dev,
+                                      bool do_modify_atomic)
+{
+       if (MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
+               return false;
+
+       if (do_modify_atomic &&
+           MLX5_CAP_GEN(dev->mdev, atomic) &&
+           MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled))
+               return false;
+
+       return true;
+}
 #endif /* MLX5_IB_H */
index 20ece6e0b2fcc1527b4018886b81d9f06633f0d6..3401f5f6792e6bb79e472f6411eade5c2d1e2dab 100644 (file)
@@ -51,22 +51,12 @@ static void clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
 static void 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);
-static bool umr_can_modify_entity_size(struct mlx5_ib_dev *dev)
-{
-       return !MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled);
-}
 
 static bool umr_can_use_indirect_mkey(struct mlx5_ib_dev *dev)
 {
        return !MLX5_CAP_GEN(dev->mdev, umr_indirect_mkey_disabled);
 }
 
-static bool use_umr(struct mlx5_ib_dev *dev, int order)
-{
-       return order <= mr_cache_max_order(dev) &&
-               umr_can_modify_entity_size(dev);
-}
-
 static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
 {
        int err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
@@ -545,13 +535,16 @@ void mlx5_mr_cache_free(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
                return;
 
        c = order2idx(dev, mr->order);
-       if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) {
-               mlx5_ib_warn(dev, "order %d, cache index %d\n", mr->order, c);
-               return;
-       }
+       WARN_ON(c < 0 || c >= MAX_MR_CACHE_ENTRIES);
 
-       if (unreg_umr(dev, mr))
+       if (unreg_umr(dev, mr)) {
+               mr->allocated_from_cache = false;
+               destroy_mkey(dev, mr);
+               ent = &cache->ent[c];
+               if (ent->cur < ent->limit)
+                       queue_work(cache->wq, &ent->work);
                return;
+       }
 
        ent = &cache->ent[c];
        spin_lock_irq(&ent->lock);
@@ -1268,7 +1261,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 {
        struct mlx5_ib_dev *dev = to_mdev(pd->device);
        struct mlx5_ib_mr *mr = NULL;
-       bool populate_mtts = false;
+       bool use_umr;
        struct ib_umem *umem;
        int page_shift;
        int npages;
@@ -1300,29 +1293,28 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
        if (err < 0)
                return ERR_PTR(err);
 
-       if (use_umr(dev, order)) {
+       use_umr = mlx5_ib_can_use_umr(dev, true);
+
+       if (order <= mr_cache_max_order(dev) && use_umr) {
                mr = alloc_mr_from_cache(pd, umem, virt_addr, length, ncont,
                                         page_shift, order, access_flags);
                if (PTR_ERR(mr) == -EAGAIN) {
                        mlx5_ib_dbg(dev, "cache empty for order %d\n", order);
                        mr = NULL;
                }
-               populate_mtts = false;
        } else if (!MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset)) {
                if (access_flags & IB_ACCESS_ON_DEMAND) {
                        err = -EINVAL;
                        pr_err("Got MR registration for ODP MR > 512MB, not supported for Connect-IB\n");
                        goto error;
                }
-               populate_mtts = true;
+               use_umr = false;
        }
 
        if (!mr) {
-               if (!umr_can_modify_entity_size(dev))
-                       populate_mtts = true;
                mutex_lock(&dev->slow_path_mutex);
                mr = reg_create(NULL, pd, virt_addr, length, umem, ncont,
-                               page_shift, access_flags, populate_mtts);
+                               page_shift, access_flags, !use_umr);
                mutex_unlock(&dev->slow_path_mutex);
        }
 
@@ -1338,7 +1330,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 
        update_odp_mr(mr);
 
-       if (!populate_mtts) {
+       if (use_umr) {
                int update_xlt_flags = MLX5_IB_UPD_XLT_ENABLE;
 
                if (access_flags & IB_ACCESS_ON_DEMAND)
@@ -1373,9 +1365,11 @@ static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
                return 0;
 
        umrwr.wr.send_flags = MLX5_IB_SEND_UMR_DISABLE_MR |
-                             MLX5_IB_SEND_UMR_FAIL_IF_FREE;
+                             MLX5_IB_SEND_UMR_UPDATE_PD_ACCESS;
        umrwr.wr.opcode = MLX5_IB_WR_UMR;
+       umrwr.pd = dev->umrc.pd;
        umrwr.mkey = mr->mmkey.key;
+       umrwr.ignore_free_state = 1;
 
        return mlx5_ib_post_send_wait(dev, &umrwr);
 }
@@ -1452,7 +1446,8 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
                        goto err;
        }
 
-       if (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len)) {
+       if (!mlx5_ib_can_use_umr(dev, true) ||
+           (flags & IB_MR_REREG_TRANS && !use_umr_mtt_update(mr, addr, len))) {
                /*
                 * UMR can't be used - MKey needs to be replaced.
                 */
@@ -1577,10 +1572,10 @@ static void clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
                mr->sig = NULL;
        }
 
-       mlx5_free_priv_descs(mr);
-
-       if (!allocated_from_cache)
+       if (!allocated_from_cache) {
                destroy_mkey(dev, mr);
+               mlx5_free_priv_descs(mr);
+       }
 }
 
 static void dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
index 5b642d81e617dc61207f3a690df1e7b304203326..0a59912a4cef640067472319da83d7123f6eb5d1 100644 (file)
@@ -246,7 +246,7 @@ void mlx5_ib_invalidate_range(struct ib_umem_odp *umem_odp, unsigned long start,
         * overwrite the same MTTs.  Concurent invalidations might race us,
         * but they will write 0s as well, so no difference in the end result.
         */
-
+       mutex_lock(&umem_odp->umem_mutex);
        for (addr = start; addr < end; addr += BIT(umem_odp->page_shift)) {
                idx = (addr - ib_umem_start(umem_odp)) >> umem_odp->page_shift;
                /*
@@ -278,6 +278,7 @@ void mlx5_ib_invalidate_range(struct ib_umem_odp *umem_odp, unsigned long start,
                                   idx - blk_start_idx + 1, 0,
                                   MLX5_IB_UPD_XLT_ZAP |
                                   MLX5_IB_UPD_XLT_ATOMIC);
+       mutex_unlock(&umem_odp->umem_mutex);
        /*
         * We are now sure that the device will not access the
         * memory. We can safely unmap it, and mark it as dirty if
@@ -300,7 +301,8 @@ void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
 
        memset(caps, 0, sizeof(*caps));
 
-       if (!MLX5_CAP_GEN(dev->mdev, pg))
+       if (!MLX5_CAP_GEN(dev->mdev, pg) ||
+           !mlx5_ib_can_use_umr(dev, true))
                return;
 
        caps->general_caps = IB_ODP_SUPPORT;
@@ -354,7 +356,8 @@ void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev)
 
        if (MLX5_CAP_GEN(dev->mdev, fixed_buffer_size) &&
            MLX5_CAP_GEN(dev->mdev, null_mkey) &&
-           MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
+           MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset) &&
+           !MLX5_CAP_GEN(dev->mdev, umr_indirect_mkey_disabled))
                caps->general_caps |= IB_ODP_SUPPORT_IMPLICIT;
 
        return;
@@ -578,7 +581,6 @@ static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
                        u32 flags)
 {
        int npages = 0, current_seq, page_shift, ret, np;
-       bool implicit = false;
        struct ib_umem_odp *odp_mr = to_ib_umem_odp(mr->umem);
        bool downgrade = flags & MLX5_PF_FLAGS_DOWNGRADE;
        bool prefetch = flags & MLX5_PF_FLAGS_PREFETCH;
@@ -593,7 +595,6 @@ static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
                if (IS_ERR(odp))
                        return PTR_ERR(odp);
                mr = odp->private;
-               implicit = true;
        } else {
                odp = odp_mr;
        }
@@ -681,19 +682,15 @@ next_mr:
 
 out:
        if (ret == -EAGAIN) {
-               if (implicit || !odp->dying) {
-                       unsigned long timeout =
-                               msecs_to_jiffies(MMU_NOTIFIER_TIMEOUT);
-
-                       if (!wait_for_completion_timeout(
-                                       &odp->notifier_completion,
-                                       timeout)) {
-                               mlx5_ib_warn(dev, "timeout waiting for mmu notifier. seq %d against %d. notifiers_count=%d\n",
-                                            current_seq, odp->notifiers_seq, odp->notifiers_count);
-                       }
-               } else {
-                       /* The MR is being killed, kill the QP as well. */
-                       ret = -EFAULT;
+               unsigned long timeout = msecs_to_jiffies(MMU_NOTIFIER_TIMEOUT);
+
+               if (!wait_for_completion_timeout(&odp->notifier_completion,
+                                                timeout)) {
+                       mlx5_ib_warn(
+                               dev,
+                               "timeout waiting for mmu notifier. seq %d against %d. notifiers_count=%d\n",
+                               current_seq, odp->notifiers_seq,
+                               odp->notifiers_count);
                }
        }
 
@@ -1627,8 +1624,10 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
 {
        int ret = 0;
 
-       if (dev->odp_caps.general_caps & IB_ODP_SUPPORT)
-               ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_odp_ops);
+       if (!(dev->odp_caps.general_caps & IB_ODP_SUPPORT))
+               return ret;
+
+       ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_odp_ops);
 
        if (dev->odp_caps.general_caps & IB_ODP_SUPPORT_IMPLICIT) {
                ret = mlx5_cmd_null_mkey(dev->mdev, &dev->null_mkey);
@@ -1638,9 +1637,6 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
                }
        }
 
-       if (!MLX5_CAP_GEN(dev->mdev, pg))
-               return ret;
-
        ret = mlx5_ib_create_pf_eq(dev, &dev->odp_pf_eq);
 
        return ret;
@@ -1648,7 +1644,7 @@ int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
 
 void mlx5_ib_odp_cleanup_one(struct mlx5_ib_dev *dev)
 {
-       if (!MLX5_CAP_GEN(dev->mdev, pg))
+       if (!(dev->odp_caps.general_caps & IB_ODP_SUPPORT))
                return;
 
        mlx5_ib_destroy_pf_eq(dev, &dev->odp_pf_eq);
@@ -1771,7 +1767,7 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work)
 
        num_pending_prefetch_dec(to_mdev(w->pd->device), w->sg_list,
                                 w->num_sge, 0);
-       kfree(w);
+       kvfree(w);
 }
 
 int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
@@ -1813,7 +1809,7 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
        if (valid_req)
                queue_work(system_unbound_wq, &work->work);
        else
-               kfree(work);
+               kvfree(work);
 
        srcu_read_unlock(&dev->mr_srcu, srcu_key);
 
index 2a97619ed6034d13e4091659dfdd4cb7b844db46..72869ff4a33420d05a5d7265e0870abb6234fbec 100644 (file)
@@ -1713,7 +1713,6 @@ static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
                }
 
                MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_TOEPLITZ);
-               MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
                memcpy(rss_key, ucmd.rx_hash_key, len);
                break;
        }
@@ -4163,7 +4162,7 @@ static u64 get_xlt_octo(u64 bytes)
               MLX5_IB_UMR_OCTOWORD;
 }
 
-static __be64 frwr_mkey_mask(void)
+static __be64 frwr_mkey_mask(bool atomic)
 {
        u64 result;
 
@@ -4176,10 +4175,12 @@ static __be64 frwr_mkey_mask(void)
                MLX5_MKEY_MASK_LW               |
                MLX5_MKEY_MASK_RR               |
                MLX5_MKEY_MASK_RW               |
-               MLX5_MKEY_MASK_A                |
                MLX5_MKEY_MASK_SMALL_FENCE      |
                MLX5_MKEY_MASK_FREE;
 
+       if (atomic)
+               result |= MLX5_MKEY_MASK_A;
+
        return cpu_to_be64(result);
 }
 
@@ -4205,7 +4206,7 @@ static __be64 sig_mkey_mask(void)
 }
 
 static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
-                           struct mlx5_ib_mr *mr, u8 flags)
+                           struct mlx5_ib_mr *mr, u8 flags, bool atomic)
 {
        int size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size;
 
@@ -4213,7 +4214,7 @@ static void set_reg_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr,
 
        umr->flags = flags;
        umr->xlt_octowords = cpu_to_be16(get_xlt_octo(size));
-       umr->mkey_mask = frwr_mkey_mask();
+       umr->mkey_mask = frwr_mkey_mask(atomic);
 }
 
 static void set_linv_umr_seg(struct mlx5_wqe_umr_ctrl_seg *umr)
@@ -4295,10 +4296,14 @@ static int set_reg_umr_segment(struct mlx5_ib_dev *dev,
 
        memset(umr, 0, sizeof(*umr));
 
-       if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE)
-               umr->flags = MLX5_UMR_CHECK_FREE; /* fail if free */
-       else
-               umr->flags = MLX5_UMR_CHECK_NOT_FREE; /* fail if not free */
+       if (!umrwr->ignore_free_state) {
+               if (wr->send_flags & MLX5_IB_SEND_UMR_FAIL_IF_FREE)
+                        /* fail if free */
+                       umr->flags = MLX5_UMR_CHECK_FREE;
+               else
+                       /* fail if not free */
+                       umr->flags = MLX5_UMR_CHECK_NOT_FREE;
+       }
 
        umr->xlt_octowords = cpu_to_be16(get_xlt_octo(umrwr->xlt_size));
        if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_XLT) {
@@ -4808,10 +4813,22 @@ static int set_reg_wr(struct mlx5_ib_qp *qp,
 {
        struct mlx5_ib_mr *mr = to_mmr(wr->mr);
        struct mlx5_ib_pd *pd = to_mpd(qp->ibqp.pd);
+       struct mlx5_ib_dev *dev = to_mdev(pd->ibpd.device);
        int mr_list_size = (mr->ndescs + mr->meta_ndescs) * mr->desc_size;
        bool umr_inline = mr_list_size <= MLX5_IB_SQ_UMR_INLINE_THRESHOLD;
+       bool atomic = wr->access & IB_ACCESS_REMOTE_ATOMIC;
        u8 flags = 0;
 
+       if (!mlx5_ib_can_use_umr(dev, atomic)) {
+               mlx5_ib_warn(to_mdev(qp->ibqp.device),
+                            "Fast update of %s for MR is disabled\n",
+                            (MLX5_CAP_GEN(dev->mdev,
+                                          umr_modify_entity_size_disabled)) ?
+                                    "entity size" :
+                                    "atomic access");
+               return -EINVAL;
+       }
+
        if (unlikely(wr->wr.send_flags & IB_SEND_INLINE)) {
                mlx5_ib_warn(to_mdev(qp->ibqp.device),
                             "Invalid IB_SEND_INLINE send flag\n");
@@ -4823,7 +4840,7 @@ static int set_reg_wr(struct mlx5_ib_qp *qp,
        if (umr_inline)
                flags |= MLX5_UMR_INLINE;
 
-       set_reg_umr_seg(*seg, mr, flags);
+       set_reg_umr_seg(*seg, mr, flags, atomic);
        *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
        *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
        handle_post_send_edge(&qp->sq, seg, *size, cur_edge);
index 533157a2a3be09e754a8425650ae9d4f5d7bb9a0..f97b3d65b30cc7e9bfb4d7303537d4f65b04b50d 100644 (file)
@@ -125,14 +125,20 @@ static ssize_t hw_rev_show(struct device *device, struct device_attribute *attr,
        struct qedr_dev *dev =
                rdma_device_to_drv_device(device, struct qedr_dev, ibdev);
 
-       return scnprintf(buf, PAGE_SIZE, "0x%x\n", dev->pdev->vendor);
+       return scnprintf(buf, PAGE_SIZE, "0x%x\n", dev->attr.hw_ver);
 }
 static DEVICE_ATTR_RO(hw_rev);
 
 static ssize_t hca_type_show(struct device *device,
                             struct device_attribute *attr, char *buf)
 {
-       return scnprintf(buf, PAGE_SIZE, "%s\n", "HCA_TYPE_TO_SET");
+       struct qedr_dev *dev =
+               rdma_device_to_drv_device(device, struct qedr_dev, ibdev);
+
+       return scnprintf(buf, PAGE_SIZE, "FastLinQ QL%x %s\n",
+                        dev->pdev->device,
+                        rdma_protocol_iwarp(&dev->ibdev, 1) ?
+                        "iWARP" : "RoCE");
 }
 static DEVICE_ATTR_RO(hca_type);
 
index dace276aea1413baa46f292a7e522381c6f00250..b622fc62f2cd6d4699cb9a1ed6ead9e44cd6bee2 100644 (file)
@@ -1,6 +1,6 @@
 config RDMA_SIW
        tristate "Software RDMA over TCP/IP (iWARP) driver"
-       depends on INET && INFINIBAND && LIBCRC32C && 64BIT
+       depends on INET && INFINIBAND && LIBCRC32C
        select DMA_VIRT_OPS
        help
        This driver implements the iWARP RDMA transport over
index 03fd7b2f595f1f35c5a535e068a60913d5b879ed..dba4535494abdc28a5317e1b96ea3cb3b8e7a852 100644 (file)
@@ -138,9 +138,9 @@ struct siw_umem {
 };
 
 struct siw_pble {
-       u64 addr; /* Address of assigned user buffer */
-       u64 size; /* Size of this entry */
-       u64 pbl_off; /* Total offset from start of PBL */
+       dma_addr_t addr; /* Address of assigned buffer */
+       unsigned int size; /* Size of this entry */
+       unsigned long pbl_off; /* Total offset from start of PBL */
 };
 
 struct siw_pbl {
@@ -214,7 +214,7 @@ struct siw_wqe {
 struct siw_cq {
        struct ib_cq base_cq;
        spinlock_t lock;
-       u64 *notify;
+       struct siw_cq_ctrl *notify;
        struct siw_cqe *queue;
        u32 cq_put;
        u32 cq_get;
@@ -734,7 +734,7 @@ static inline void siw_crc_skb(struct siw_rx_stream *srx, unsigned int len)
                  "MEM[0x%08x] %s: " fmt, mem->stag, __func__, ##__VA_ARGS__)
 
 #define siw_dbg_cep(cep, fmt, ...)                                             \
-       ibdev_dbg(&cep->sdev->base_dev, "CEP[0x%p] %s: " fmt,                  \
+       ibdev_dbg(&cep->sdev->base_dev, "CEP[0x%pK] %s: " fmt,                  \
                  cep, __func__, ##__VA_ARGS__)
 
 void siw_cq_flush(struct siw_cq *cq);
index a7cde98e73e8c8616310f4d54e3523998953d2fc..8c1931a57f4a598532d19e2d373e5539371f5edf 100644 (file)
@@ -220,13 +220,12 @@ static void siw_put_work(struct siw_cm_work *work)
 static void siw_cep_set_inuse(struct siw_cep *cep)
 {
        unsigned long flags;
-       int rv;
 retry:
        spin_lock_irqsave(&cep->lock, flags);
 
        if (cep->in_use) {
                spin_unlock_irqrestore(&cep->lock, flags);
-               rv = wait_event_interruptible(cep->waitq, !cep->in_use);
+               wait_event_interruptible(cep->waitq, !cep->in_use);
                if (signal_pending(current))
                        flush_signals(current);
                goto retry;
@@ -356,8 +355,8 @@ static int siw_cm_upcall(struct siw_cep *cep, enum iw_cm_event_type reason,
                getname_local(cep->sock, &event.local_addr);
                getname_peer(cep->sock, &event.remote_addr);
        }
-       siw_dbg_cep(cep, "[QP %u]: id 0x%p, reason=%d, status=%d\n",
-                   cep->qp ? qp_id(cep->qp) : -1, id, reason, status);
+       siw_dbg_cep(cep, "[QP %u]: reason=%d, status=%d\n",
+                   cep->qp ? qp_id(cep->qp) : UINT_MAX, reason, status);
 
        return id->event_handler(id, &event);
 }
@@ -948,8 +947,6 @@ static void siw_accept_newconn(struct siw_cep *cep)
        siw_cep_get(new_cep);
        new_s->sk->sk_user_data = new_cep;
 
-       siw_dbg_cep(cep, "listen socket 0x%p, new 0x%p\n", s, new_s);
-
        if (siw_tcp_nagle == false) {
                int val = 1;
 
@@ -1012,7 +1009,8 @@ static void siw_cm_work_handler(struct work_struct *w)
        cep = work->cep;
 
        siw_dbg_cep(cep, "[QP %u]: work type: %d, state %d\n",
-                   cep->qp ? qp_id(cep->qp) : -1, work->type, cep->state);
+                   cep->qp ? qp_id(cep->qp) : UINT_MAX,
+                   work->type, cep->state);
 
        siw_cep_set_inuse(cep);
 
@@ -1146,9 +1144,9 @@ static void siw_cm_work_handler(struct work_struct *w)
        }
        if (release_cep) {
                siw_dbg_cep(cep,
-                           "release: timer=%s, QP[%u], id 0x%p\n",
+                           "release: timer=%s, QP[%u]\n",
                            cep->mpa_timer ? "y" : "n",
-                           cep->qp ? qp_id(cep->qp) : -1, cep->cm_id);
+                           cep->qp ? qp_id(cep->qp) : UINT_MAX);
 
                siw_cancel_mpatimer(cep);
 
@@ -1212,8 +1210,8 @@ int siw_cm_queue_work(struct siw_cep *cep, enum siw_work_type type)
                else
                        delay = MPAREP_TIMEOUT;
        }
-       siw_dbg_cep(cep, "[QP %u]: work type: %d, work 0x%p, timeout %lu\n",
-                   cep->qp ? qp_id(cep->qp) : -1, type, work, delay);
+       siw_dbg_cep(cep, "[QP %u]: work type: %d, timeout %lu\n",
+                   cep->qp ? qp_id(cep->qp) : -1, type, delay);
 
        queue_delayed_work(siw_cm_wq, &work->work, delay);
 
@@ -1377,16 +1375,16 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        }
        if (v4)
                siw_dbg_qp(qp,
-                          "id 0x%p, pd_len %d, laddr %pI4 %d, raddr %pI4 %d\n",
-                          id, pd_len,
+                          "pd_len %d, laddr %pI4 %d, raddr %pI4 %d\n",
+                          pd_len,
                           &((struct sockaddr_in *)(laddr))->sin_addr,
                           ntohs(((struct sockaddr_in *)(laddr))->sin_port),
                           &((struct sockaddr_in *)(raddr))->sin_addr,
                           ntohs(((struct sockaddr_in *)(raddr))->sin_port));
        else
                siw_dbg_qp(qp,
-                          "id 0x%p, pd_len %d, laddr %pI6 %d, raddr %pI6 %d\n",
-                          id, pd_len,
+                          "pd_len %d, laddr %pI6 %d, raddr %pI6 %d\n",
+                          pd_len,
                           &((struct sockaddr_in6 *)(laddr))->sin6_addr,
                           ntohs(((struct sockaddr_in6 *)(laddr))->sin6_port),
                           &((struct sockaddr_in6 *)(raddr))->sin6_addr,
@@ -1509,14 +1507,13 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        if (rv >= 0) {
                rv = siw_cm_queue_work(cep, SIW_CM_WORK_MPATIMEOUT);
                if (!rv) {
-                       siw_dbg_cep(cep, "id 0x%p, [QP %u]: exit\n", id,
-                                   qp_id(qp));
+                       siw_dbg_cep(cep, "[QP %u]: exit\n", qp_id(qp));
                        siw_cep_set_free(cep);
                        return 0;
                }
        }
 error:
-       siw_dbg_qp(qp, "failed: %d\n", rv);
+       siw_dbg(id->device, "failed: %d\n", rv);
 
        if (cep) {
                siw_socket_disassoc(s);
@@ -1541,7 +1538,8 @@ error:
        } else if (s) {
                sock_release(s);
        }
-       siw_qp_put(qp);
+       if (qp)
+               siw_qp_put(qp);
 
        return rv;
 }
@@ -1581,7 +1579,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        siw_cancel_mpatimer(cep);
 
        if (cep->state != SIW_EPSTATE_RECVD_MPAREQ) {
-               siw_dbg_cep(cep, "id 0x%p: out of state\n", id);
+               siw_dbg_cep(cep, "out of state\n");
 
                siw_cep_set_free(cep);
                siw_cep_put(cep);
@@ -1602,7 +1600,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
                up_write(&qp->state_lock);
                goto error;
        }
-       siw_dbg_cep(cep, "id 0x%p\n", id);
+       siw_dbg_cep(cep, "[QP %d]\n", params->qpn);
 
        if (try_gso && cep->mpa.hdr.params.bits & MPA_RR_FLAG_GSO_EXP) {
                siw_dbg_cep(cep, "peer allows GSO on TX\n");
@@ -1612,8 +1610,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
            params->ird > sdev->attrs.max_ird) {
                siw_dbg_cep(
                        cep,
-                       "id 0x%p, [QP %u]: ord %d (max %d), ird %d (max %d)\n",
-                       id, qp_id(qp), params->ord, sdev->attrs.max_ord,
+                       "[QP %u]: ord %d (max %d), ird %d (max %d)\n",
+                       qp_id(qp), params->ord, sdev->attrs.max_ord,
                        params->ird, sdev->attrs.max_ird);
                rv = -EINVAL;
                up_write(&qp->state_lock);
@@ -1625,8 +1623,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        if (params->private_data_len > max_priv_data) {
                siw_dbg_cep(
                        cep,
-                       "id 0x%p, [QP %u]: private data length: %d (max %d)\n",
-                       id, qp_id(qp), params->private_data_len, max_priv_data);
+                       "[QP %u]: private data length: %d (max %d)\n",
+                       qp_id(qp), params->private_data_len, max_priv_data);
                rv = -EINVAL;
                up_write(&qp->state_lock);
                goto error;
@@ -1680,7 +1678,7 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
                qp_attrs.flags = SIW_MPA_CRC;
        qp_attrs.state = SIW_QP_STATE_RTS;
 
-       siw_dbg_cep(cep, "id 0x%p, [QP%u]: moving to rts\n", id, qp_id(qp));
+       siw_dbg_cep(cep, "[QP%u]: moving to rts\n", qp_id(qp));
 
        /* Associate QP with CEP */
        siw_cep_get(cep);
@@ -1701,8 +1699,8 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
        if (rv)
                goto error;
 
-       siw_dbg_cep(cep, "id 0x%p, [QP %u]: send mpa reply, %d byte pdata\n",
-                   id, qp_id(qp), params->private_data_len);
+       siw_dbg_cep(cep, "[QP %u]: send mpa reply, %d byte pdata\n",
+                   qp_id(qp), params->private_data_len);
 
        rv = siw_send_mpareqrep(cep, params->private_data,
                                params->private_data_len);
@@ -1760,14 +1758,14 @@ int siw_reject(struct iw_cm_id *id, const void *pdata, u8 pd_len)
        siw_cancel_mpatimer(cep);
 
        if (cep->state != SIW_EPSTATE_RECVD_MPAREQ) {
-               siw_dbg_cep(cep, "id 0x%p: out of state\n", id);
+               siw_dbg_cep(cep, "out of state\n");
 
                siw_cep_set_free(cep);
                siw_cep_put(cep); /* put last reference */
 
                return -ECONNRESET;
        }
-       siw_dbg_cep(cep, "id 0x%p, cep->state %d, pd_len %d\n", id, cep->state,
+       siw_dbg_cep(cep, "cep->state %d, pd_len %d\n", cep->state,
                    pd_len);
 
        if (__mpa_rr_revision(cep->mpa.hdr.params.bits) >= MPA_REVISION_1) {
@@ -1805,14 +1803,14 @@ static int siw_listen_address(struct iw_cm_id *id, int backlog,
        rv = kernel_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&s_val,
                               sizeof(s_val));
        if (rv) {
-               siw_dbg(id->device, "id 0x%p: setsockopt error: %d\n", id, rv);
+               siw_dbg(id->device, "setsockopt error: %d\n", rv);
                goto error;
        }
        rv = s->ops->bind(s, laddr, addr_family == AF_INET ?
                                    sizeof(struct sockaddr_in) :
                                    sizeof(struct sockaddr_in6));
        if (rv) {
-               siw_dbg(id->device, "id 0x%p: socket bind error: %d\n", id, rv);
+               siw_dbg(id->device, "socket bind error: %d\n", rv);
                goto error;
        }
        cep = siw_cep_alloc(sdev);
@@ -1825,13 +1823,13 @@ static int siw_listen_address(struct iw_cm_id *id, int backlog,
        rv = siw_cm_alloc_work(cep, backlog);
        if (rv) {
                siw_dbg(id->device,
-                       "id 0x%p: alloc_work error %d, backlog %d\n", id,
+                       "alloc_work error %d, backlog %d\n",
                        rv, backlog);
                goto error;
        }
        rv = s->ops->listen(s, backlog);
        if (rv) {
-               siw_dbg(id->device, "id 0x%p: listen error %d\n", id, rv);
+               siw_dbg(id->device, "listen error %d\n", rv);
                goto error;
        }
        cep->cm_id = id;
@@ -1915,8 +1913,7 @@ static void siw_drop_listeners(struct iw_cm_id *id)
 
                list_del(p);
 
-               siw_dbg_cep(cep, "id 0x%p: drop cep, state %d\n", id,
-                           cep->state);
+               siw_dbg_cep(cep, "drop cep, state %d\n", cep->state);
 
                siw_cep_set_inuse(cep);
 
@@ -1953,7 +1950,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
        struct net_device *dev = to_siw_dev(id->device)->netdev;
        int rv = 0, listeners = 0;
 
-       siw_dbg(id->device, "id 0x%p: backlog %d\n", id, backlog);
+       siw_dbg(id->device, "backlog %d\n", backlog);
 
        /*
         * For each attached address of the interface, create a
@@ -1965,12 +1962,16 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
                struct sockaddr_in s_laddr, *s_raddr;
                const struct in_ifaddr *ifa;
 
+               if (!in_dev) {
+                       rv = -ENODEV;
+                       goto out;
+               }
                memcpy(&s_laddr, &id->local_addr, sizeof(s_laddr));
                s_raddr = (struct sockaddr_in *)&id->remote_addr;
 
                siw_dbg(id->device,
-                       "id 0x%p: laddr %pI4:%d, raddr %pI4:%d\n",
-                       id, &s_laddr.sin_addr, ntohs(s_laddr.sin_port),
+                       "laddr %pI4:%d, raddr %pI4:%d\n",
+                       &s_laddr.sin_addr, ntohs(s_laddr.sin_port),
                        &s_raddr->sin_addr, ntohs(s_raddr->sin_port));
 
                rtnl_lock();
@@ -1994,22 +1995,27 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
                struct sockaddr_in6 *s_laddr = &to_sockaddr_in6(id->local_addr),
                        *s_raddr = &to_sockaddr_in6(id->remote_addr);
 
+               if (!in6_dev) {
+                       rv = -ENODEV;
+                       goto out;
+               }
                siw_dbg(id->device,
-                       "id 0x%p: laddr %pI6:%d, raddr %pI6:%d\n",
-                       id, &s_laddr->sin6_addr, ntohs(s_laddr->sin6_port),
+                       "laddr %pI6:%d, raddr %pI6:%d\n",
+                       &s_laddr->sin6_addr, ntohs(s_laddr->sin6_port),
                        &s_raddr->sin6_addr, ntohs(s_raddr->sin6_port));
 
-               read_lock_bh(&in6_dev->lock);
+               rtnl_lock();
                list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
-                       struct sockaddr_in6 bind_addr;
-
+                       if (ifp->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
+                               continue;
                        if (ipv6_addr_any(&s_laddr->sin6_addr) ||
                            ipv6_addr_equal(&s_laddr->sin6_addr, &ifp->addr)) {
-                               bind_addr.sin6_family = AF_INET6;
-                               bind_addr.sin6_port = s_laddr->sin6_port;
-                               bind_addr.sin6_flowinfo = 0;
-                               bind_addr.sin6_addr = ifp->addr;
-                               bind_addr.sin6_scope_id = dev->ifindex;
+                               struct sockaddr_in6 bind_addr  = {
+                                       .sin6_family = AF_INET6,
+                                       .sin6_port = s_laddr->sin6_port,
+                                       .sin6_flowinfo = 0,
+                                       .sin6_addr = ifp->addr,
+                                       .sin6_scope_id = dev->ifindex };
 
                                rv = siw_listen_address(id, backlog,
                                                (struct sockaddr *)&bind_addr,
@@ -2018,28 +2024,26 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
                                        listeners++;
                        }
                }
-               read_unlock_bh(&in6_dev->lock);
-
+               rtnl_unlock();
                in6_dev_put(in6_dev);
        } else {
-               return -EAFNOSUPPORT;
+               rv = -EAFNOSUPPORT;
        }
+out:
        if (listeners)
                rv = 0;
        else if (!rv)
                rv = -EINVAL;
 
-       siw_dbg(id->device, "id 0x%p: %s\n", id, rv ? "FAIL" : "OK");
+       siw_dbg(id->device, "%s\n", rv ? "FAIL" : "OK");
 
        return rv;
 }
 
 int siw_destroy_listen(struct iw_cm_id *id)
 {
-       siw_dbg(id->device, "id 0x%p\n", id);
-
        if (!id->provider_data) {
-               siw_dbg(id->device, "id 0x%p: no cep(s)\n", id);
+               siw_dbg(id->device, "no cep(s)\n");
                return 0;
        }
        siw_drop_listeners(id);
index e381ae9b7d62498ed6b8ab8a9a4d04ea2f1f92eb..d8db3bee9da7f5015d133cfeef29af5e9e3cef42 100644 (file)
@@ -71,9 +71,10 @@ int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc)
                                wc->wc_flags = IB_WC_WITH_INVALIDATE;
                        }
                        wc->qp = cqe->base_qp;
-                       siw_dbg_cq(cq, "idx %u, type %d, flags %2x, id 0x%p\n",
+                       siw_dbg_cq(cq,
+                                  "idx %u, type %d, flags %2x, id 0x%pK\n",
                                   cq->cq_get % cq->num_cqe, cqe->opcode,
-                                  cqe->flags, (void *)cqe->id);
+                                  cqe->flags, (void *)(uintptr_t)cqe->id);
                }
                WRITE_ONCE(cqe->flags, 0);
                cq->cq_get++;
index f55c4e80aea409a60349005bfe8ff53ab2ca5b07..05a92f997f603bfbc64138ae2bdda31486baa36c 100644 (file)
@@ -160,10 +160,8 @@ static int siw_init_cpulist(void)
 
 out_err:
        siw_cpu_info.num_nodes = 0;
-       while (i) {
+       while (--i >= 0)
                kfree(siw_cpu_info.tx_valid_cpus[i]);
-               siw_cpu_info.tx_valid_cpus[i--] = NULL;
-       }
        kfree(siw_cpu_info.tx_valid_cpus);
        siw_cpu_info.tx_valid_cpus = NULL;
 
@@ -612,6 +610,7 @@ static __init int siw_init_module(void)
 
        if (!siw_create_tx_threads()) {
                pr_info("siw: Could not start any TX thread\n");
+               rv = -ENOMEM;
                goto out_error;
        }
        /*
index 67171c82b0c4f98ba7a8dbca4b5bb70ed8080115..87a56039f0ef11192fe3c73e6aaef19b660f417e 100644 (file)
@@ -197,12 +197,12 @@ int siw_check_mem(struct ib_pd *pd, struct siw_mem *mem, u64 addr,
         */
        if (addr < mem->va || addr + len > mem->va + mem->len) {
                siw_dbg_pd(pd, "MEM interval len %d\n", len);
-               siw_dbg_pd(pd, "[0x%016llx, 0x%016llx] out of bounds\n",
-                          (unsigned long long)addr,
-                          (unsigned long long)(addr + len));
-               siw_dbg_pd(pd, "[0x%016llx, 0x%016llx] STag=0x%08x\n",
-                          (unsigned long long)mem->va,
-                          (unsigned long long)(mem->va + mem->len),
+               siw_dbg_pd(pd, "[0x%pK, 0x%pK] out of bounds\n",
+                          (void *)(uintptr_t)addr,
+                          (void *)(uintptr_t)(addr + len));
+               siw_dbg_pd(pd, "[0x%pK, 0x%pK] STag=0x%08x\n",
+                          (void *)(uintptr_t)mem->va,
+                          (void *)(uintptr_t)(mem->va + mem->len),
                           mem->stag);
 
                return -E_BASE_BOUNDS;
@@ -330,7 +330,7 @@ out:
  * Optionally, provides remaining len within current element, and
  * current PBL index for later resume at same element.
  */
-u64 siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx)
+dma_addr_t siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx)
 {
        int i = idx ? *idx : 0;
 
index f43daf28089122ccc515c6ffae0ba73745a5e07d..db138c8423da547bd35e8737dfa15b04cfaa7c62 100644 (file)
@@ -9,7 +9,7 @@
 struct siw_umem *siw_umem_get(u64 start, u64 len, bool writable);
 void siw_umem_release(struct siw_umem *umem, bool dirty);
 struct siw_pbl *siw_pbl_alloc(u32 num_buf);
-u64 siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx);
+dma_addr_t siw_pbl_get_buffer(struct siw_pbl *pbl, u64 off, int *len, int *idx);
 struct siw_mem *siw_mem_id2obj(struct siw_device *sdev, int stag_index);
 int siw_mem_add(struct siw_device *sdev, struct siw_mem *m);
 int siw_invalidate_stag(struct ib_pd *pd, u32 stag);
index 11383d9f95ef169b6e75e27b3f1d922dee3dc41b..430314c8abd948c200d0eb1c203d5325c8230be1 100644 (file)
@@ -220,12 +220,14 @@ static int siw_qp_enable_crc(struct siw_qp *qp)
 {
        struct siw_rx_stream *c_rx = &qp->rx_stream;
        struct siw_iwarp_tx *c_tx = &qp->tx_ctx;
-       int size = crypto_shash_descsize(siw_crypto_shash) +
-                       sizeof(struct shash_desc);
+       int size;
 
        if (siw_crypto_shash == NULL)
                return -ENOENT;
 
+       size = crypto_shash_descsize(siw_crypto_shash) +
+               sizeof(struct shash_desc);
+
        c_tx->mpa_crc_hd = kzalloc(size, GFP_KERNEL);
        c_rx->mpa_crc_hd = kzalloc(size, GFP_KERNEL);
        if (!c_tx->mpa_crc_hd || !c_rx->mpa_crc_hd) {
@@ -947,7 +949,7 @@ skip_irq:
                                rv = -EINVAL;
                                goto out;
                        }
-                       wqe->sqe.sge[0].laddr = (u64)&wqe->sqe.sge[1];
+                       wqe->sqe.sge[0].laddr = (uintptr_t)&wqe->sqe.sge[1];
                        wqe->sqe.sge[0].lkey = 0;
                        wqe->sqe.num_sge = 1;
                }
@@ -1011,18 +1013,24 @@ out:
  */
 static bool siw_cq_notify_now(struct siw_cq *cq, u32 flags)
 {
-       u64 cq_notify;
+       u32 cq_notify;
 
        if (!cq->base_cq.comp_handler)
                return false;
 
-       cq_notify = READ_ONCE(*cq->notify);
+       /* Read application shared notification state */
+       cq_notify = READ_ONCE(cq->notify->flags);
 
        if ((cq_notify & SIW_NOTIFY_NEXT_COMPLETION) ||
            ((cq_notify & SIW_NOTIFY_SOLICITED) &&
             (flags & SIW_WQE_SOLICITED))) {
-               /* dis-arm CQ */
-               smp_store_mb(*cq->notify, SIW_NOTIFY_NOT);
+               /*
+                * CQ notification is one-shot: Since the
+                * current CQE causes user notification,
+                * the CQ gets dis-aremd and must be re-aremd
+                * by the user for a new notification.
+                */
+               WRITE_ONCE(cq->notify->flags, SIW_NOTIFY_NOT);
 
                return true;
        }
index f87657a11657223ee06f22b6bac91833fb7ab57b..c0a887240325854bb9af0de94d2e86ff6c9e0f4f 100644 (file)
@@ -38,9 +38,10 @@ static int siw_rx_umem(struct siw_rx_stream *srx, struct siw_umem *umem,
 
                p = siw_get_upage(umem, dest_addr);
                if (unlikely(!p)) {
-                       pr_warn("siw: %s: [QP %u]: bogus addr: %p, %p\n",
+                       pr_warn("siw: %s: [QP %u]: bogus addr: %pK, %pK\n",
                                __func__, qp_id(rx_qp(srx)),
-                               (void *)dest_addr, (void *)umem->fp_addr);
+                               (void *)(uintptr_t)dest_addr,
+                               (void *)(uintptr_t)umem->fp_addr);
                        /* siw internal error */
                        srx->skb_copied += copied;
                        srx->skb_new -= copied;
@@ -50,7 +51,7 @@ static int siw_rx_umem(struct siw_rx_stream *srx, struct siw_umem *umem,
                pg_off = dest_addr & ~PAGE_MASK;
                bytes = min(len, (int)PAGE_SIZE - pg_off);
 
-               siw_dbg_qp(rx_qp(srx), "page %p, bytes=%u\n", p, bytes);
+               siw_dbg_qp(rx_qp(srx), "page %pK, bytes=%u\n", p, bytes);
 
                dest = kmap_atomic(p);
                rv = skb_copy_bits(srx->skb, srx->skb_offset, dest + pg_off,
@@ -104,11 +105,11 @@ static int siw_rx_kva(struct siw_rx_stream *srx, void *kva, int len)
 {
        int rv;
 
-       siw_dbg_qp(rx_qp(srx), "kva: 0x%p, len: %u\n", kva, len);
+       siw_dbg_qp(rx_qp(srx), "kva: 0x%pK, len: %u\n", kva, len);
 
        rv = skb_copy_bits(srx->skb, srx->skb_offset, kva, len);
        if (unlikely(rv)) {
-               pr_warn("siw: [QP %u]: %s, len %d, kva 0x%p, rv %d\n",
+               pr_warn("siw: [QP %u]: %s, len %d, kva 0x%pK, rv %d\n",
                        qp_id(rx_qp(srx)), __func__, len, kva, rv);
 
                return rv;
@@ -132,7 +133,7 @@ static int siw_rx_pbl(struct siw_rx_stream *srx, int *pbl_idx,
 
        while (len) {
                int bytes;
-               u64 buf_addr =
+               dma_addr_t buf_addr =
                        siw_pbl_get_buffer(pbl, offset, &bytes, pbl_idx);
                if (!buf_addr)
                        break;
@@ -485,8 +486,8 @@ int siw_proc_send(struct siw_qp *qp)
                mem_p = *mem;
                if (mem_p->mem_obj == NULL)
                        rv = siw_rx_kva(srx,
-                                       (void *)(sge->laddr + frx->sge_off),
-                                       sge_bytes);
+                               (void *)(uintptr_t)(sge->laddr + frx->sge_off),
+                               sge_bytes);
                else if (!mem_p->is_pbl)
                        rv = siw_rx_umem(srx, mem_p->umem,
                                         sge->laddr + frx->sge_off, sge_bytes);
@@ -598,8 +599,8 @@ int siw_proc_write(struct siw_qp *qp)
 
        if (mem->mem_obj == NULL)
                rv = siw_rx_kva(srx,
-                               (void *)(srx->ddp_to + srx->fpdu_part_rcvd),
-                               bytes);
+                       (void *)(uintptr_t)(srx->ddp_to + srx->fpdu_part_rcvd),
+                       bytes);
        else if (!mem->is_pbl)
                rv = siw_rx_umem(srx, mem->umem,
                                 srx->ddp_to + srx->fpdu_part_rcvd, bytes);
@@ -841,8 +842,9 @@ int siw_proc_rresp(struct siw_qp *qp)
        bytes = min(srx->fpdu_part_rem, srx->skb_new);
 
        if (mem_p->mem_obj == NULL)
-               rv = siw_rx_kva(srx, (void *)(sge->laddr + wqe->processed),
-                               bytes);
+               rv = siw_rx_kva(srx,
+                       (void *)(uintptr_t)(sge->laddr + wqe->processed),
+                       bytes);
        else if (!mem_p->is_pbl)
                rv = siw_rx_umem(srx, mem_p->umem, sge->laddr + wqe->processed,
                                 bytes);
index 43020d2040fc3394ce3ee18e0369986693f58b26..438a2917a47c20e3cb5b1cdb130632fd045c42c1 100644 (file)
@@ -26,7 +26,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
 {
        struct siw_pbl *pbl = mem->pbl;
        u64 offset = addr - mem->va;
-       u64 paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
+       dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
 
        if (paddr)
                return virt_to_page(paddr);
@@ -37,7 +37,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
 /*
  * Copy short payload at provided destination payload address
  */
-static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
+static int siw_try_1seg(struct siw_iwarp_tx *c_tx, void *paddr)
 {
        struct siw_wqe *wqe = &c_tx->wqe_active;
        struct siw_sge *sge = &wqe->sqe.sge[0];
@@ -50,16 +50,16 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
                return 0;
 
        if (tx_flags(wqe) & SIW_WQE_INLINE) {
-               memcpy((void *)paddr, &wqe->sqe.sge[1], bytes);
+               memcpy(paddr, &wqe->sqe.sge[1], bytes);
        } else {
                struct siw_mem *mem = wqe->mem[0];
 
                if (!mem->mem_obj) {
                        /* Kernel client using kva */
-                       memcpy((void *)paddr, (void *)sge->laddr, bytes);
+                       memcpy(paddr,
+                              (const void *)(uintptr_t)sge->laddr, bytes);
                } else if (c_tx->in_syscall) {
-                       if (copy_from_user((void *)paddr,
-                                          (const void __user *)sge->laddr,
+                       if (copy_from_user(paddr, u64_to_user_ptr(sge->laddr),
                                           bytes))
                                return -EFAULT;
                } else {
@@ -79,12 +79,12 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
                        buffer = kmap_atomic(p);
 
                        if (likely(PAGE_SIZE - off >= bytes)) {
-                               memcpy((void *)paddr, buffer + off, bytes);
+                               memcpy(paddr, buffer + off, bytes);
                                kunmap_atomic(buffer);
                        } else {
                                unsigned long part = bytes - (PAGE_SIZE - off);
 
-                               memcpy((void *)paddr, buffer + off, part);
+                               memcpy(paddr, buffer + off, part);
                                kunmap_atomic(buffer);
 
                                if (!mem->is_pbl)
@@ -98,7 +98,7 @@ static int siw_try_1seg(struct siw_iwarp_tx *c_tx, u64 paddr)
                                        return -EFAULT;
 
                                buffer = kmap_atomic(p);
-                               memcpy((void *)(paddr + part), buffer,
+                               memcpy(paddr + part, buffer,
                                       bytes - part);
                                kunmap_atomic(buffer);
                        }
@@ -166,7 +166,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
                c_tx->ctrl_len = sizeof(struct iwarp_send);
 
                crc = (char *)&c_tx->pkt.send_pkt.crc;
-               data = siw_try_1seg(c_tx, (u64)crc);
+               data = siw_try_1seg(c_tx, crc);
                break;
 
        case SIW_OP_SEND_REMOTE_INV:
@@ -189,7 +189,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
                c_tx->ctrl_len = sizeof(struct iwarp_send_inv);
 
                crc = (char *)&c_tx->pkt.send_pkt.crc;
-               data = siw_try_1seg(c_tx, (u64)crc);
+               data = siw_try_1seg(c_tx, crc);
                break;
 
        case SIW_OP_WRITE:
@@ -201,7 +201,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
                c_tx->ctrl_len = sizeof(struct iwarp_rdma_write);
 
                crc = (char *)&c_tx->pkt.write_pkt.crc;
-               data = siw_try_1seg(c_tx, (u64)crc);
+               data = siw_try_1seg(c_tx, crc);
                break;
 
        case SIW_OP_READ_RESPONSE:
@@ -216,7 +216,7 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
                c_tx->ctrl_len = sizeof(struct iwarp_rdma_rresp);
 
                crc = (char *)&c_tx->pkt.write_pkt.crc;
-               data = siw_try_1seg(c_tx, (u64)crc);
+               data = siw_try_1seg(c_tx, crc);
                break;
 
        default:
@@ -398,15 +398,13 @@ static int siw_0copy_tx(struct socket *s, struct page **page,
 
 #define MAX_TRAILER (MPA_CRC_SIZE + 4)
 
-static void siw_unmap_pages(struct page **pages, int hdr_len, int num_maps)
+static void siw_unmap_pages(struct page **pp, unsigned long kmap_mask)
 {
-       if (hdr_len) {
-               ++pages;
-               --num_maps;
-       }
-       while (num_maps-- > 0) {
-               kunmap(*pages);
-               pages++;
+       while (kmap_mask) {
+               if (kmap_mask & BIT(0))
+                       kunmap(*pp);
+               pp++;
+               kmap_mask >>= 1;
        }
 }
 
@@ -437,6 +435,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
        unsigned int data_len = c_tx->bytes_unsent, hdr_len = 0, trl_len = 0,
                     sge_off = c_tx->sge_off, sge_idx = c_tx->sge_idx,
                     pbl_idx = c_tx->pbl_idx;
+       unsigned long kmap_mask = 0L;
 
        if (c_tx->state == SIW_SEND_HDR) {
                if (c_tx->use_sendpage) {
@@ -463,8 +462,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
 
                if (!(tx_flags(wqe) & SIW_WQE_INLINE)) {
                        mem = wqe->mem[sge_idx];
-                       if (!mem->mem_obj)
-                               is_kva = 1;
+                       is_kva = mem->mem_obj == NULL ? 1 : 0;
                } else {
                        is_kva = 1;
                }
@@ -473,7 +471,8 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                         * tx from kernel virtual address: either inline data
                         * or memory region with assigned kernel buffer
                         */
-                       iov[seg].iov_base = (void *)(sge->laddr + sge_off);
+                       iov[seg].iov_base =
+                               (void *)(uintptr_t)(sge->laddr + sge_off);
                        iov[seg].iov_len = sge_len;
 
                        if (do_crc)
@@ -500,12 +499,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                                        p = siw_get_upage(mem->umem,
                                                          sge->laddr + sge_off);
                                if (unlikely(!p)) {
-                                       if (hdr_len)
-                                               seg--;
-                                       if (!c_tx->use_sendpage && seg) {
-                                               siw_unmap_pages(page_array,
-                                                               hdr_len, seg);
-                                       }
+                                       siw_unmap_pages(page_array, kmap_mask);
                                        wqe->processed -= c_tx->bytes_unsent;
                                        rv = -EFAULT;
                                        goto done_crc;
@@ -515,6 +509,10 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                                if (!c_tx->use_sendpage) {
                                        iov[seg].iov_base = kmap(p) + fp_off;
                                        iov[seg].iov_len = plen;
+
+                                       /* Remember for later kunmap() */
+                                       kmap_mask |= BIT(seg);
+
                                        if (do_crc)
                                                crypto_shash_update(
                                                        c_tx->mpa_crc_hd,
@@ -526,13 +524,13 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                                                page_address(p) + fp_off,
                                                plen);
                        } else {
-                               u64 pa = ((sge->laddr + sge_off) & PAGE_MASK);
+                               u64 va = sge->laddr + sge_off;
 
-                               page_array[seg] = virt_to_page(pa);
+                               page_array[seg] = virt_to_page(va & PAGE_MASK);
                                if (do_crc)
                                        crypto_shash_update(
                                                c_tx->mpa_crc_hd,
-                                               (void *)(sge->laddr + sge_off),
+                                               (void *)(uintptr_t)va,
                                                plen);
                        }
 
@@ -543,10 +541,7 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
 
                        if (++seg > (int)MAX_ARRAY) {
                                siw_dbg_qp(tx_qp(c_tx), "to many fragments\n");
-                               if (!is_kva && !c_tx->use_sendpage) {
-                                       siw_unmap_pages(page_array, hdr_len,
-                                                       seg - 1);
-                               }
+                               siw_unmap_pages(page_array, kmap_mask);
                                wqe->processed -= c_tx->bytes_unsent;
                                rv = -EMSGSIZE;
                                goto done_crc;
@@ -597,8 +592,7 @@ sge_done:
        } else {
                rv = kernel_sendmsg(s, &msg, iov, seg + 1,
                                    hdr_len + data_len + trl_len);
-               if (!is_kva)
-                       siw_unmap_pages(page_array, hdr_len, seg);
+               siw_unmap_pages(page_array, kmap_mask);
        }
        if (rv < (int)hdr_len) {
                /* Not even complete hdr pushed or negative rv */
@@ -829,7 +823,8 @@ static int siw_qp_sq_proc_tx(struct siw_qp *qp, struct siw_wqe *wqe)
                                        rv = -EINVAL;
                                        goto tx_error;
                                }
-                               wqe->sqe.sge[0].laddr = (u64)&wqe->sqe.sge[1];
+                               wqe->sqe.sge[0].laddr =
+                                       (u64)(uintptr_t)&wqe->sqe.sge[1];
                        }
                }
                wqe->wr_status = SIW_WR_INPROGRESS;
@@ -924,7 +919,7 @@ tx_error:
 
 static int siw_fastreg_mr(struct ib_pd *pd, struct siw_sqe *sqe)
 {
-       struct ib_mr *base_mr = (struct ib_mr *)sqe->base_mr;
+       struct ib_mr *base_mr = (struct ib_mr *)(uintptr_t)sqe->base_mr;
        struct siw_device *sdev = to_siw_dev(pd->device);
        struct siw_mem *mem = siw_mem_id2obj(sdev, sqe->rkey  >> 8);
        int rv = 0;
@@ -954,8 +949,7 @@ static int siw_fastreg_mr(struct ib_pd *pd, struct siw_sqe *sqe)
        mem->stag = sqe->rkey;
        mem->perms = sqe->access;
 
-       siw_dbg_mem(mem, "STag now valid, MR va: 0x%016llx -> 0x%016llx\n",
-                   mem->va, base_mr->iova);
+       siw_dbg_mem(mem, "STag 0x%08x now valid\n", sqe->rkey);
        mem->va = base_mr->iova;
        mem->stag_valid = 1;
 out:
index 32dc79d0e8981770ddf2069f69b286adc5116b3d..da52c90e06d48edf8d4dab77680c42aee324621d 100644 (file)
@@ -424,8 +424,7 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
                 */
                qp->srq = to_siw_srq(attrs->srq);
                qp->attrs.rq_size = 0;
-               siw_dbg(base_dev, "QP [%u]: [SRQ 0x%p] attached\n",
-                       qp->qp_num, qp->srq);
+               siw_dbg(base_dev, "QP [%u]: SRQ attached\n", qp->qp_num);
        } else if (num_rqe) {
                if (qp->kernel_verbs)
                        qp->recvq = vzalloc(num_rqe * sizeof(struct siw_rqe));
@@ -610,7 +609,7 @@ int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata)
                                          base_ucontext);
        struct siw_qp_attrs qp_attrs;
 
-       siw_dbg_qp(qp, "state %d, cep 0x%p\n", qp->attrs.state, qp->cep);
+       siw_dbg_qp(qp, "state %d\n", qp->attrs.state);
 
        /*
         * Mark QP as in process of destruction to prevent from
@@ -662,7 +661,7 @@ static int siw_copy_inline_sgl(const struct ib_send_wr *core_wr,
        void *kbuf = &sqe->sge[1];
        int num_sge = core_wr->num_sge, bytes = 0;
 
-       sqe->sge[0].laddr = (u64)kbuf;
+       sqe->sge[0].laddr = (uintptr_t)kbuf;
        sqe->sge[0].lkey = 0;
 
        while (num_sge--) {
@@ -825,7 +824,7 @@ int siw_post_send(struct ib_qp *base_qp, const struct ib_send_wr *wr,
                        break;
 
                case IB_WR_REG_MR:
-                       sqe->base_mr = (uint64_t)reg_wr(wr)->mr;
+                       sqe->base_mr = (uintptr_t)reg_wr(wr)->mr;
                        sqe->rkey = reg_wr(wr)->key;
                        sqe->access = reg_wr(wr)->access & IWARP_ACCESS_MASK;
                        sqe->opcode = SIW_OP_REG_MR;
@@ -842,8 +841,9 @@ int siw_post_send(struct ib_qp *base_qp, const struct ib_send_wr *wr,
                        rv = -EINVAL;
                        break;
                }
-               siw_dbg_qp(qp, "opcode %d, flags 0x%x, wr_id 0x%p\n",
-                          sqe->opcode, sqe->flags, (void *)sqe->id);
+               siw_dbg_qp(qp, "opcode %d, flags 0x%x, wr_id 0x%pK\n",
+                          sqe->opcode, sqe->flags,
+                          (void *)(uintptr_t)sqe->id);
 
                if (unlikely(rv < 0))
                        break;
@@ -1049,7 +1049,7 @@ int siw_create_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr *attr,
 
        spin_lock_init(&cq->lock);
 
-       cq->notify = &((struct siw_cq_ctrl *)&cq->queue[size])->notify;
+       cq->notify = (struct siw_cq_ctrl *)&cq->queue[size];
 
        if (udata) {
                struct siw_uresp_create_cq uresp = {};
@@ -1141,11 +1141,17 @@ int siw_req_notify_cq(struct ib_cq *base_cq, enum ib_cq_notify_flags flags)
        siw_dbg_cq(cq, "flags: 0x%02x\n", flags);
 
        if ((flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED)
-               /* CQ event for next solicited completion */
-               smp_store_mb(*cq->notify, SIW_NOTIFY_SOLICITED);
+               /*
+                * Enable CQ event for next solicited completion.
+                * and make it visible to all associated producers.
+                */
+               smp_store_mb(cq->notify->flags, SIW_NOTIFY_SOLICITED);
        else
-               /* CQ event for any signalled completion */
-               smp_store_mb(*cq->notify, SIW_NOTIFY_ALL);
+               /*
+                * Enable CQ event for any signalled completion.
+                * and make it visible to all associated producers.
+                */
+               smp_store_mb(cq->notify->flags, SIW_NOTIFY_ALL);
 
        if (flags & IB_CQ_REPORT_MISSED_EVENTS)
                return cq->cq_put - cq->cq_get;
@@ -1199,8 +1205,8 @@ struct ib_mr *siw_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
        unsigned long mem_limit = rlimit(RLIMIT_MEMLOCK);
        int rv;
 
-       siw_dbg_pd(pd, "start: 0x%016llx, va: 0x%016llx, len: %llu\n",
-                  (unsigned long long)start, (unsigned long long)rnic_va,
+       siw_dbg_pd(pd, "start: 0x%pK, va: 0x%pK, len: %llu\n",
+                  (void *)(uintptr_t)start, (void *)(uintptr_t)rnic_va,
                   (unsigned long long)len);
 
        if (atomic_inc_return(&sdev->num_mr) > SIW_MAX_MR) {
@@ -1357,7 +1363,7 @@ int siw_map_mr_sg(struct ib_mr *base_mr, struct scatterlist *sl, int num_sle,
        struct siw_mem *mem = mr->mem;
        struct siw_pbl *pbl = mem->pbl;
        struct siw_pble *pble;
-       u64 pbl_size;
+       unsigned long pbl_size;
        int i, rv;
 
        if (!pbl) {
@@ -1396,16 +1402,18 @@ int siw_map_mr_sg(struct ib_mr *base_mr, struct scatterlist *sl, int num_sle,
                        pbl_size += sg_dma_len(slp);
                }
                siw_dbg_mem(mem,
-                       "sge[%d], size %llu, addr 0x%016llx, total %llu\n",
-                       i, pble->size, pble->addr, pbl_size);
+                       "sge[%d], size %u, addr 0x%p, total %lu\n",
+                       i, pble->size, (void *)(uintptr_t)pble->addr,
+                       pbl_size);
        }
        rv = ib_sg_to_pages(base_mr, sl, num_sle, sg_off, siw_set_pbl_page);
        if (rv > 0) {
                mem->len = base_mr->length;
                mem->va = base_mr->iova;
                siw_dbg_mem(mem,
-                       "%llu bytes, start 0x%016llx, %u SLE to %u entries\n",
-                       mem->len, mem->va, num_sle, pbl->num_buf);
+                       "%llu bytes, start 0x%pK, %u SLE to %u entries\n",
+                       mem->len, (void *)(uintptr_t)mem->va, num_sle,
+                       pbl->num_buf);
        }
        return rv;
 }
@@ -1523,7 +1531,7 @@ int siw_create_srq(struct ib_srq *base_srq,
        }
        spin_lock_init(&srq->lock);
 
-       siw_dbg_pd(base_srq->pd, "[SRQ 0x%p]: success\n", srq);
+       siw_dbg_pd(base_srq->pd, "[SRQ]: success\n");
 
        return 0;
 
@@ -1644,8 +1652,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
 
        if (unlikely(!srq->kernel_verbs)) {
                siw_dbg_pd(base_srq->pd,
-                          "[SRQ 0x%p]: no kernel post_recv for mapped srq\n",
-                          srq);
+                          "[SRQ]: no kernel post_recv for mapped srq\n");
                rv = -EINVAL;
                goto out;
        }
@@ -1667,8 +1674,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
                }
                if (unlikely(wr->num_sge > srq->max_sge)) {
                        siw_dbg_pd(base_srq->pd,
-                                  "[SRQ 0x%p]: too many sge's: %d\n", srq,
-                                  wr->num_sge);
+                                  "[SRQ]: too many sge's: %d\n", wr->num_sge);
                        rv = -EINVAL;
                        break;
                }
@@ -1687,7 +1693,7 @@ int siw_post_srq_recv(struct ib_srq *base_srq, const struct ib_recv_wr *wr,
        spin_unlock_irqrestore(&srq->lock, flags);
 out:
        if (unlikely(rv < 0)) {
-               siw_dbg_pd(base_srq->pd, "[SRQ 0x%p]: error %d\n", srq, rv);
+               siw_dbg_pd(base_srq->pd, "[SRQ]: error %d\n", rv);
                *bad_wr = wr;
        }
        return rv;
index 29abfeeef9a5f58e9e3840f42ee7a10ab78df210..6c554c11a7ac3f35a33b318f7f6bef589a8c6b81 100644 (file)
@@ -201,7 +201,12 @@ static int iforce_usb_probe(struct usb_interface *intf,
                return -ENODEV;
 
        epirq = &interface->endpoint[0].desc;
+       if (!usb_endpoint_is_int_in(epirq))
+               return -ENODEV;
+
        epout = &interface->endpoint[1].desc;
+       if (!usb_endpoint_is_int_out(epout))
+               return -ENODEV;
 
        iforce_usb = kzalloc(sizeof(*iforce_usb), GFP_KERNEL);
        if (!iforce_usb)
index 8e9c3ea9d5e799c2873d165db109a850cff7e868..90e8a7f2f07c863196762633930bc46a5c659319 100644 (file)
@@ -76,6 +76,8 @@ config KEYBOARD_APPLESPI
        depends on ACPI && EFI
        depends on SPI
        depends on X86 || COMPILE_TEST
+       depends on LEDS_CLASS
+       select CRC16
        help
          Say Y here if you are running Linux on any Apple MacBook8,1 or later,
          or any MacBookPro13,* or MacBookPro14,*.
index 548737e7aedaec459bddd261609d774dc6b1d52c..584289b67fb3cbccc20f9a26200c624fea468ef9 100644 (file)
@@ -134,10 +134,10 @@ struct keyboard_protocol {
  * struct tp_finger - single trackpad finger structure, le16-aligned
  *
  * @origin:            zero when switching track finger
- * @abs_x:             absolute x coodinate
- * @abs_y:             absolute y coodinate
- * @rel_x:             relative x coodinate
- * @rel_y:             relative y coodinate
+ * @abs_x:             absolute x coordinate
+ * @abs_y:             absolute y coordinate
+ * @rel_x:             relative x coordinate
+ * @rel_y:             relative y coordinate
  * @tool_major:                tool area, major axis
  * @tool_minor:                tool area, minor axis
  * @orientation:       16384 when point, else 15 bit angle
@@ -944,10 +944,14 @@ static inline int le16_to_int(__le16 x)
 static void applespi_debug_update_dimensions(struct applespi_data *applespi,
                                             const struct tp_finger *f)
 {
-       applespi->tp_dim_min_x = min_t(int, applespi->tp_dim_min_x, f->abs_x);
-       applespi->tp_dim_max_x = max_t(int, applespi->tp_dim_max_x, f->abs_x);
-       applespi->tp_dim_min_y = min_t(int, applespi->tp_dim_min_y, f->abs_y);
-       applespi->tp_dim_max_y = max_t(int, applespi->tp_dim_max_y, f->abs_y);
+       applespi->tp_dim_min_x = min(applespi->tp_dim_min_x,
+                                    le16_to_int(f->abs_x));
+       applespi->tp_dim_max_x = max(applespi->tp_dim_max_x,
+                                    le16_to_int(f->abs_x));
+       applespi->tp_dim_min_y = min(applespi->tp_dim_min_y,
+                                    le16_to_int(f->abs_y));
+       applespi->tp_dim_max_y = max(applespi->tp_dim_max_y,
+                                    le16_to_int(f->abs_y));
 }
 
 static int applespi_tp_dim_open(struct inode *inode, struct file *file)
@@ -1490,8 +1494,7 @@ static void applespi_got_data(struct applespi_data *applespi)
                size_t tp_len;
 
                tp = &message->touchpad;
-               tp_len = sizeof(*tp) +
-                        tp->number_of_fingers * sizeof(tp->fingers[0]);
+               tp_len = struct_size(tp, fingers, tp->number_of_fingers);
 
                if (le16_to_cpu(message->length) + 2 != tp_len) {
                        dev_warn_ratelimited(&applespi->spi->dev,
@@ -1611,8 +1614,8 @@ static void applespi_save_bl_level(struct applespi_data *applespi,
        efi_attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
                   EFI_VARIABLE_RUNTIME_ACCESS;
 
-       sts = efivar_entry_set_safe(EFI_BL_LEVEL_NAME, efi_guid, efi_attr, true,
-                                   efi_data_len, &efi_data);
+       sts = efivar_entry_set_safe((efi_char16_t *)EFI_BL_LEVEL_NAME, efi_guid,
+                                   efi_attr, true, efi_data_len, &efi_data);
        if (sts)
                dev_warn(&applespi->spi->dev,
                         "Error saving backlight level to EFI vars: %d\n", sts);
@@ -1953,7 +1956,7 @@ static const struct acpi_device_id applespi_acpi_match[] = {
 };
 MODULE_DEVICE_TABLE(acpi, applespi_acpi_match);
 
-const struct dev_pm_ops applespi_pm_ops = {
+static const struct dev_pm_ops applespi_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(applespi_suspend, applespi_resume)
        .poweroff_late  = applespi_poweroff_late,
 };
index 2d8434b7b62381a85abdb28daba2391fdd117e40..04fe43440a3c8740d58ee1cb944fc3b7099aa981 100644 (file)
@@ -1827,6 +1827,31 @@ static int elantech_create_smbus(struct psmouse *psmouse,
                                  leave_breadcrumbs);
 }
 
+static bool elantech_use_host_notify(struct psmouse *psmouse,
+                                    struct elantech_device_info *info)
+{
+       if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+               return true;
+
+       switch (info->bus) {
+       case ETP_BUS_PS2_ONLY:
+               /* expected case */
+               break;
+       case ETP_BUS_SMB_HST_NTFY_ONLY:
+       case ETP_BUS_PS2_SMB_HST_NTFY:
+               /* SMbus implementation is stable since 2018 */
+               if (dmi_get_bios_year() >= 2018)
+                       return true;
+               /* fall through */
+       default:
+               psmouse_dbg(psmouse,
+                           "Ignoring SMBus bus provider %d\n", info->bus);
+               break;
+       }
+
+       return false;
+}
+
 /**
  * elantech_setup_smbus - called once the PS/2 devices are enumerated
  * and decides to instantiate a SMBus InterTouch device.
@@ -1846,7 +1871,7 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
                 * i2c_blacklist_pnp_ids.
                 * Old ICs are up to the user to decide.
                 */
-               if (!ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version) ||
+               if (!elantech_use_host_notify(psmouse, info) ||
                    psmouse_matches_pnp_id(psmouse, i2c_blacklist_pnp_ids))
                        return -ENXIO;
        }
@@ -1866,34 +1891,6 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
        return 0;
 }
 
-static bool elantech_use_host_notify(struct psmouse *psmouse,
-                                    struct elantech_device_info *info)
-{
-       if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
-               return true;
-
-       switch (info->bus) {
-       case ETP_BUS_PS2_ONLY:
-               /* expected case */
-               break;
-       case ETP_BUS_SMB_ALERT_ONLY:
-               /* fall-through  */
-       case ETP_BUS_PS2_SMB_ALERT:
-               psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n");
-               break;
-       case ETP_BUS_SMB_HST_NTFY_ONLY:
-               /* fall-through  */
-       case ETP_BUS_PS2_SMB_HST_NTFY:
-               return true;
-       default:
-               psmouse_dbg(psmouse,
-                           "Ignoring SMBus bus provider %d.\n",
-                           info->bus);
-       }
-
-       return false;
-}
-
 int elantech_init_smbus(struct psmouse *psmouse)
 {
        struct elantech_device_info info;
index b1956ed4c0ddeaf35b1f3cf65c0773e851a7c07d..46bbe99d651135b093ba6b3de6473243103e5493 100644 (file)
@@ -182,6 +182,7 @@ static const char * const smbus_pnp_ids[] = {
        "LEN2055", /* E580 */
        "SYN3052", /* HP EliteBook 840 G4 */
        "SYN3221", /* HP 15-ay000 */
+       "SYN323d", /* HP Spectre X360 13-w013dx */
        NULL
 };
 
index 88ae7c2ac3c817ce983b9fc801a8cacd2aa7b52f..e486a8a74c40c710de93a6de132e15089043d3a3 100644 (file)
@@ -237,40 +237,17 @@ static void hv_kbd_handle_received_packet(struct hv_device *hv_dev,
 
 static void hv_kbd_on_channel_callback(void *context)
 {
+       struct vmpacket_descriptor *desc;
        struct hv_device *hv_dev = context;
-       void *buffer;
-       int bufferlen = 0x100; /* Start with sensible size */
        u32 bytes_recvd;
        u64 req_id;
-       int error;
 
-       buffer = kmalloc(bufferlen, GFP_ATOMIC);
-       if (!buffer)
-               return;
-
-       while (1) {
-               error = vmbus_recvpacket_raw(hv_dev->channel, buffer, bufferlen,
-                                            &bytes_recvd, &req_id);
-               switch (error) {
-               case 0:
-                       if (bytes_recvd == 0) {
-                               kfree(buffer);
-                               return;
-                       }
-
-                       hv_kbd_handle_received_packet(hv_dev, buffer,
-                                                     bytes_recvd, req_id);
-                       break;
+       foreach_vmbus_pkt(desc, hv_dev->channel) {
+               bytes_recvd = desc->len8 * 8;
+               req_id = desc->trans_id;
 
-               case -ENOBUFS:
-                       kfree(buffer);
-                       /* Handle large packet */
-                       bufferlen = bytes_recvd;
-                       buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
-                       if (!buffer)
-                               return;
-                       break;
-               }
+               hv_kbd_handle_received_packet(hv_dev, desc, bytes_recvd,
+                                             req_id);
        }
 }
 
index 04b85571f41e3c03b0767ee335c96853c236b4e4..aa577898e952b48c495f3214abd690a80106df99 100644 (file)
@@ -117,6 +117,10 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
        if (intf->cur_altsetting->desc.bNumEndpoints < 1)
                return -ENODEV;
 
+       endpoint = &intf->cur_altsetting->endpoint[0].desc;
+       if (!usb_endpoint_is_int_in(endpoint))
+               return -ENODEV;
+
        kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!kbtab || !input_dev)
@@ -155,8 +159,6 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
        input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0);
        input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0);
 
-       endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
        usb_fill_int_urb(kbtab->irq, dev,
                         usb_rcvintpipe(dev, endpoint->bEndpointAddress),
                         kbtab->data, 8,
index a2cec6cacf576e4a387d8f4aa2bc5ca953a66a22..16d70201de4a3334fc4dd49dc3d205ce4d96bc52 100644 (file)
@@ -1659,6 +1659,8 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (!usbtouch || !input_dev)
                goto out_free;
 
+       mutex_init(&usbtouch->pm_mutex);
+
        type = &usbtouch_dev_info[id->driver_info];
        usbtouch->type = type;
        if (!type->process_pkt)
index b607a92791d3f8b48a9c1caeaea48986753ead64..61de81965c44ed95b52ef857b4f31a4cb8519a28 100644 (file)
@@ -1143,6 +1143,17 @@ static void amd_iommu_flush_tlb_all(struct amd_iommu *iommu)
        iommu_completion_wait(iommu);
 }
 
+static void amd_iommu_flush_tlb_domid(struct amd_iommu *iommu, u32 dom_id)
+{
+       struct iommu_cmd cmd;
+
+       build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+                             dom_id, 1);
+       iommu_queue_command(iommu, &cmd);
+
+       iommu_completion_wait(iommu);
+}
+
 static void amd_iommu_flush_all(struct amd_iommu *iommu)
 {
        struct iommu_cmd cmd;
@@ -1424,18 +1435,21 @@ static void free_pagetable(struct protection_domain *domain)
  * another level increases the size of the address space by 9 bits to a size up
  * to 64 bits.
  */
-static bool increase_address_space(struct protection_domain *domain,
+static void increase_address_space(struct protection_domain *domain,
                                   gfp_t gfp)
 {
+       unsigned long flags;
        u64 *pte;
 
-       if (domain->mode == PAGE_MODE_6_LEVEL)
+       spin_lock_irqsave(&domain->lock, flags);
+
+       if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
                /* address space already 64 bit large */
-               return false;
+               goto out;
 
        pte = (void *)get_zeroed_page(gfp);
        if (!pte)
-               return false;
+               goto out;
 
        *pte             = PM_LEVEL_PDE(domain->mode,
                                        iommu_virt_to_phys(domain->pt_root));
@@ -1443,7 +1457,10 @@ static bool increase_address_space(struct protection_domain *domain,
        domain->mode    += 1;
        domain->updated  = true;
 
-       return true;
+out:
+       spin_unlock_irqrestore(&domain->lock, flags);
+
+       return;
 }
 
 static u64 *alloc_pte(struct protection_domain *domain,
@@ -1873,6 +1890,7 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain,
 {
        u64 pte_root = 0;
        u64 flags = 0;
+       u32 old_domid;
 
        if (domain->mode != PAGE_MODE_NONE)
                pte_root = iommu_virt_to_phys(domain->pt_root);
@@ -1922,8 +1940,20 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain,
        flags &= ~DEV_DOMID_MASK;
        flags |= domain->id;
 
+       old_domid = amd_iommu_dev_table[devid].data[1] & DEV_DOMID_MASK;
        amd_iommu_dev_table[devid].data[1]  = flags;
        amd_iommu_dev_table[devid].data[0]  = pte_root;
+
+       /*
+        * A kdump kernel might be replacing a domain ID that was copied from
+        * the previous kernel--if so, it needs to flush the translation cache
+        * entries for the old domain ID that is being overwritten
+        */
+       if (old_domid) {
+               struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+               amd_iommu_flush_tlb_domid(iommu, old_domid);
+       }
 }
 
 static void clear_dte_entry(u16 devid)
index eb104c719629e6de64328079563d94dde8fee740..4413aa67000e576a43a7c8d0e8fd79ee2cc0574a 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/mem_encrypt.h>
 #include <asm/pci-direct.h>
 #include <asm/iommu.h>
+#include <asm/apic.h>
+#include <asm/msidef.h>
 #include <asm/gart.h>
 #include <asm/x86_init.h>
 #include <asm/iommu_table.h>
@@ -1920,6 +1922,90 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
        return 0;
 }
 
+#define XT_INT_DEST_MODE(x)    (((x) & 0x1ULL) << 2)
+#define XT_INT_DEST_LO(x)      (((x) & 0xFFFFFFULL) << 8)
+#define XT_INT_VEC(x)          (((x) & 0xFFULL) << 32)
+#define XT_INT_DEST_HI(x)      ((((x) >> 24) & 0xFFULL) << 56)
+
+/**
+ * Setup the IntCapXT registers with interrupt routing information
+ * based on the PCI MSI capability block registers, accessed via
+ * MMIO MSI address low/hi and MSI data registers.
+ */
+static void iommu_update_intcapxt(struct amd_iommu *iommu)
+{
+       u64 val;
+       u32 addr_lo = readl(iommu->mmio_base + MMIO_MSI_ADDR_LO_OFFSET);
+       u32 addr_hi = readl(iommu->mmio_base + MMIO_MSI_ADDR_HI_OFFSET);
+       u32 data    = readl(iommu->mmio_base + MMIO_MSI_DATA_OFFSET);
+       bool dm     = (addr_lo >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
+       u32 dest    = ((addr_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xFF);
+
+       if (x2apic_enabled())
+               dest |= MSI_ADDR_EXT_DEST_ID(addr_hi);
+
+       val = XT_INT_VEC(data & 0xFF) |
+             XT_INT_DEST_MODE(dm) |
+             XT_INT_DEST_LO(dest) |
+             XT_INT_DEST_HI(dest);
+
+       /**
+        * Current IOMMU implemtation uses the same IRQ for all
+        * 3 IOMMU interrupts.
+        */
+       writeq(val, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET);
+       writeq(val, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET);
+       writeq(val, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET);
+}
+
+static void _irq_notifier_notify(struct irq_affinity_notify *notify,
+                                const cpumask_t *mask)
+{
+       struct amd_iommu *iommu;
+
+       for_each_iommu(iommu) {
+               if (iommu->dev->irq == notify->irq) {
+                       iommu_update_intcapxt(iommu);
+                       break;
+               }
+       }
+}
+
+static void _irq_notifier_release(struct kref *ref)
+{
+}
+
+static int iommu_init_intcapxt(struct amd_iommu *iommu)
+{
+       int ret;
+       struct irq_affinity_notify *notify = &iommu->intcapxt_notify;
+
+       /**
+        * IntCapXT requires XTSup=1, which can be inferred
+        * amd_iommu_xt_mode.
+        */
+       if (amd_iommu_xt_mode != IRQ_REMAP_X2APIC_MODE)
+               return 0;
+
+       /**
+        * Also, we need to setup notifier to update the IntCapXT registers
+        * whenever the irq affinity is changed from user-space.
+        */
+       notify->irq = iommu->dev->irq;
+       notify->notify = _irq_notifier_notify,
+       notify->release = _irq_notifier_release,
+       ret = irq_set_affinity_notifier(iommu->dev->irq, notify);
+       if (ret) {
+               pr_err("Failed to register irq affinity notifier (devid=%#x, irq %d)\n",
+                      iommu->devid, iommu->dev->irq);
+               return ret;
+       }
+
+       iommu_update_intcapxt(iommu);
+       iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN);
+       return ret;
+}
+
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
        int ret;
@@ -1936,6 +2022,10 @@ static int iommu_init_msi(struct amd_iommu *iommu)
                return ret;
 
 enable_faults:
+       ret = iommu_init_intcapxt(iommu);
+       if (ret)
+               return ret;
+
        iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
 
        if (iommu->ppr_log != NULL)
index 52c35d557fade3c3b201df38d4a1dba69235f901..64edd5a9694cc06400f70692a654f5c006956ddd 100644 (file)
 #define MMIO_PPR_LOG_OFFSET    0x0038
 #define MMIO_GA_LOG_BASE_OFFSET        0x00e0
 #define MMIO_GA_LOG_TAIL_OFFSET        0x00e8
+#define MMIO_MSI_ADDR_LO_OFFSET        0x015C
+#define MMIO_MSI_ADDR_HI_OFFSET        0x0160
+#define MMIO_MSI_DATA_OFFSET   0x0164
+#define MMIO_INTCAPXT_EVT_OFFSET       0x0170
+#define MMIO_INTCAPXT_PPR_OFFSET       0x0178
+#define MMIO_INTCAPXT_GALOG_OFFSET     0x0180
 #define MMIO_CMD_HEAD_OFFSET   0x2000
 #define MMIO_CMD_TAIL_OFFSET   0x2008
 #define MMIO_EVT_HEAD_OFFSET   0x2010
 #define CONTROL_GALOG_EN        0x1CULL
 #define CONTROL_GAINT_EN        0x1DULL
 #define CONTROL_XT_EN           0x32ULL
+#define CONTROL_INTCAPXT_EN     0x33ULL
 
 #define CTRL_INV_TO_MASK       (7 << CONTROL_INV_TIMEOUT)
 #define CTRL_INV_TO_NONE       0
@@ -592,6 +599,8 @@ struct amd_iommu {
        /* DebugFS Info */
        struct dentry *debugfs;
 #endif
+       /* IRQ notifier for IntCapXT interrupt */
+       struct irq_affinity_notify intcapxt_notify;
 };
 
 static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev)
index a9a9fabd396804a26b77039d0fe804cea3dc56dc..c5c93e48b4dbdf7409ca3b8008a24a4ab3214a49 100644 (file)
@@ -1186,8 +1186,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
                        ste_live = true;
                        break;
                case STRTAB_STE_0_CFG_ABORT:
-                       if (disable_bypass)
-                               break;
+                       BUG_ON(!disable_bypass);
+                       break;
                default:
                        BUG(); /* STE corruption */
                }
index a7f9c3edbcb299f83f8d4c6093c274a0bc5b3387..f68a62c3c32b55e1414ee5eff0cc34a452f38489 100644 (file)
@@ -459,13 +459,11 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
 {
        struct iommu_domain *domain = iommu_get_dma_domain(dev);
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
-       size_t iova_off = 0;
+       struct iova_domain *iovad = &cookie->iovad;
+       size_t iova_off = iova_offset(iovad, phys);
        dma_addr_t iova;
 
-       if (cookie->type == IOMMU_DMA_IOVA_COOKIE) {
-               iova_off = iova_offset(&cookie->iovad, phys);
-               size = iova_align(&cookie->iovad, size + iova_off);
-       }
+       size = iova_align(iovad, size + iova_off);
 
        iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
        if (!iova)
@@ -574,7 +572,7 @@ static void *iommu_dma_alloc_remap(struct device *dev, size_t size,
        struct iova_domain *iovad = &cookie->iovad;
        bool coherent = dev_is_dma_coherent(dev);
        int ioprot = dma_info_to_prot(DMA_BIDIRECTIONAL, coherent, attrs);
-       pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
+       pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
        unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap;
        struct page **pages;
        struct sg_table sgt;
@@ -764,7 +762,7 @@ static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents,
                 * - and wouldn't make the resulting output segment too long
                 */
                if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
-                   (cur_len + s_length <= max_len)) {
+                   (max_len - cur_len >= s_length)) {
                        /* ...then concatenate it with the previous one */
                        cur_len += s_length;
                } else {
@@ -967,15 +965,18 @@ static void *iommu_dma_alloc_pages(struct device *dev, size_t size,
 {
        bool coherent = dev_is_dma_coherent(dev);
        size_t alloc_size = PAGE_ALIGN(size);
+       int node = dev_to_node(dev);
        struct page *page = NULL;
        void *cpu_addr;
 
        page = dma_alloc_contiguous(dev, alloc_size, gfp);
+       if (!page)
+               page = alloc_pages_node(node, gfp, get_order(alloc_size));
        if (!page)
                return NULL;
 
        if (IS_ENABLED(CONFIG_DMA_REMAP) && (!coherent || PageHighMem(page))) {
-               pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
+               pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
 
                cpu_addr = dma_common_contiguous_remap(page, alloc_size,
                                VM_USERMAP, prot, __builtin_return_address(0));
@@ -1035,7 +1036,7 @@ static int iommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
        unsigned long pfn, off = vma->vm_pgoff;
        int ret;
 
-       vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs);
+       vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);
 
        if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
                return ret;
@@ -1147,16 +1148,21 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
        if (!msi_page)
                return NULL;
 
-       iova = __iommu_dma_map(dev, msi_addr, size, prot);
-       if (iova == DMA_MAPPING_ERROR)
+       iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
+       if (!iova)
                goto out_free_page;
 
+       if (iommu_map(domain, iova, msi_addr, size, prot))
+               goto out_free_iova;
+
        INIT_LIST_HEAD(&msi_page->list);
        msi_page->phys = msi_addr;
        msi_page->iova = iova;
        list_add(&msi_page->list, &cookie->msi_page_list);
        return msi_page;
 
+out_free_iova:
+       iommu_dma_free_iova(cookie, iova, size);
 out_free_page:
        kfree(msi_page);
        return NULL;
index 73a552914455284edfb1d8bae30b6fbb7e668104..471f05d452e0198f3d2837f2a83e13d0984e1a12 100644 (file)
@@ -162,9 +162,9 @@ static inline void print_tbl_walk(struct seq_file *m)
                           (u64)0, (u64)0, (u64)0);
        else
                seq_printf(m, "%-6d\t0x%016llx:0x%016llx:0x%016llx\n",
-                          tbl_wlk->pasid, tbl_wlk->pasid_tbl_entry->val[0],
+                          tbl_wlk->pasid, tbl_wlk->pasid_tbl_entry->val[2],
                           tbl_wlk->pasid_tbl_entry->val[1],
-                          tbl_wlk->pasid_tbl_entry->val[2]);
+                          tbl_wlk->pasid_tbl_entry->val[0]);
 }
 
 static void pasid_tbl_walk(struct seq_file *m, struct pasid_entry *tbl_entry,
@@ -235,7 +235,7 @@ static void ctx_tbl_walk(struct seq_file *m, struct intel_iommu *iommu, u16 bus)
                tbl_wlk.ctx_entry = context;
                m->private = &tbl_wlk;
 
-               if (pasid_supported(iommu) && is_pasid_enabled(context)) {
+               if (dmar_readq(iommu->reg + DMAR_RTADDR_REG) & DMA_RTADDR_SMT) {
                        pasid_dir_ptr = context->lo & VTD_PAGE_MASK;
                        pasid_dir_size = get_pasid_dir_size(context);
                        pasid_dir_walk(m, pasid_dir_ptr, pasid_dir_size);
index ac4172c0224487b69cfbee8c6e292d7755eb55e9..c4e0e4a9ee9ec5c2f5632176591badb3161031fa 100644 (file)
@@ -1833,9 +1833,65 @@ static inline int guestwidth_to_adjustwidth(int gaw)
        return agaw;
 }
 
+static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
+                      int guest_width)
+{
+       int adjust_width, agaw;
+       unsigned long sagaw;
+       int err;
+
+       init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
+
+       err = init_iova_flush_queue(&domain->iovad,
+                                   iommu_flush_iova, iova_entry_free);
+       if (err)
+               return err;
+
+       domain_reserve_special_ranges(domain);
+
+       /* calculate AGAW */
+       if (guest_width > cap_mgaw(iommu->cap))
+               guest_width = cap_mgaw(iommu->cap);
+       domain->gaw = guest_width;
+       adjust_width = guestwidth_to_adjustwidth(guest_width);
+       agaw = width_to_agaw(adjust_width);
+       sagaw = cap_sagaw(iommu->cap);
+       if (!test_bit(agaw, &sagaw)) {
+               /* hardware doesn't support it, choose a bigger one */
+               pr_debug("Hardware doesn't support agaw %d\n", agaw);
+               agaw = find_next_bit(&sagaw, 5, agaw);
+               if (agaw >= 5)
+                       return -ENODEV;
+       }
+       domain->agaw = agaw;
+
+       if (ecap_coherent(iommu->ecap))
+               domain->iommu_coherency = 1;
+       else
+               domain->iommu_coherency = 0;
+
+       if (ecap_sc_support(iommu->ecap))
+               domain->iommu_snooping = 1;
+       else
+               domain->iommu_snooping = 0;
+
+       if (intel_iommu_superpage)
+               domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
+       else
+               domain->iommu_superpage = 0;
+
+       domain->nid = iommu->node;
+
+       /* always allocate the top pgd */
+       domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
+       if (!domain->pgd)
+               return -ENOMEM;
+       __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
+       return 0;
+}
+
 static void domain_exit(struct dmar_domain *domain)
 {
-       struct page *freelist;
 
        /* Remove associated devices and clear attached or cached domains */
        domain_remove_dev_info(domain);
@@ -1843,9 +1899,12 @@ static void domain_exit(struct dmar_domain *domain)
        /* destroy iovas */
        put_iova_domain(&domain->iovad);
 
-       freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+       if (domain->pgd) {
+               struct page *freelist;
 
-       dma_free_pagelist(freelist);
+               freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+               dma_free_pagelist(freelist);
+       }
 
        free_domain_mem(domain);
 }
@@ -2513,31 +2572,6 @@ static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
        return 0;
 }
 
-static int domain_init(struct dmar_domain *domain, int guest_width)
-{
-       int adjust_width;
-
-       init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
-       domain_reserve_special_ranges(domain);
-
-       /* calculate AGAW */
-       domain->gaw = guest_width;
-       adjust_width = guestwidth_to_adjustwidth(guest_width);
-       domain->agaw = width_to_agaw(adjust_width);
-
-       domain->iommu_coherency = 0;
-       domain->iommu_snooping = 0;
-       domain->iommu_superpage = 0;
-       domain->max_addr = 0;
-
-       /* always allocate the top pgd */
-       domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
-       if (!domain->pgd)
-               return -ENOMEM;
-       domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
-       return 0;
-}
-
 static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
 {
        struct device_domain_info *info;
@@ -2575,19 +2609,11 @@ static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
        domain = alloc_domain(0);
        if (!domain)
                return NULL;
-
-       if (domain_init(domain, gaw)) {
+       if (domain_init(domain, iommu, gaw)) {
                domain_exit(domain);
                return NULL;
        }
 
-       if (init_iova_flush_queue(&domain->iovad,
-                                 iommu_flush_iova,
-                                 iova_entry_free)) {
-               pr_warn("iova flush queue initialization failed\n");
-               intel_iommu_strict = 1;
-       }
-
 out:
        return domain;
 }
@@ -2692,6 +2718,8 @@ static int domain_prepare_identity_map(struct device *dev,
        return iommu_domain_identity_map(domain, start, end);
 }
 
+static int md_domain_init(struct dmar_domain *domain, int guest_width);
+
 static int __init si_domain_init(int hw)
 {
        struct dmar_rmrr_unit *rmrr;
@@ -2702,7 +2730,7 @@ static int __init si_domain_init(int hw)
        if (!si_domain)
                return -EFAULT;
 
-       if (domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+       if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
                domain_exit(si_domain);
                return -EFAULT;
        }
@@ -3450,6 +3478,7 @@ static bool iommu_need_mapping(struct device *dev)
                                dmar_domain = to_dmar_domain(domain);
                                dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
                        }
+                       dmar_remove_one_dev_info(dev);
                        get_private_domain_for_dev(dev);
                }
 
@@ -3564,7 +3593,8 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
 
        freelist = domain_unmap(domain, start_pfn, last_pfn);
 
-       if (intel_iommu_strict || (pdev && pdev->untrusted)) {
+       if (intel_iommu_strict || (pdev && pdev->untrusted) ||
+                       !has_iova_flush_queue(&domain->iovad)) {
                iommu_flush_iotlb_psi(iommu, domain, start_pfn,
                                      nrpages, !freelist, 0);
                /* free iova */
@@ -4812,7 +4842,8 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
 
        /* free the private domain */
        if (domain->flags & DOMAIN_FLAG_LOSE_CHILDREN &&
-           !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY))
+           !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+           list_empty(&domain->devices))
                domain_exit(info->domain);
 
        free_devinfo_mem(info);
@@ -4825,10 +4856,36 @@ static void dmar_remove_one_dev_info(struct device *dev)
 
        spin_lock_irqsave(&device_domain_lock, flags);
        info = dev->archdata.iommu;
-       __dmar_remove_one_dev_info(info);
+       if (info)
+               __dmar_remove_one_dev_info(info);
        spin_unlock_irqrestore(&device_domain_lock, flags);
 }
 
+static int md_domain_init(struct dmar_domain *domain, int guest_width)
+{
+       int adjust_width;
+
+       init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
+       domain_reserve_special_ranges(domain);
+
+       /* calculate AGAW */
+       domain->gaw = guest_width;
+       adjust_width = guestwidth_to_adjustwidth(guest_width);
+       domain->agaw = width_to_agaw(adjust_width);
+
+       domain->iommu_coherency = 0;
+       domain->iommu_snooping = 0;
+       domain->iommu_superpage = 0;
+       domain->max_addr = 0;
+
+       /* always allocate the top pgd */
+       domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
+       if (!domain->pgd)
+               return -ENOMEM;
+       domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
+       return 0;
+}
+
 static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
 {
        struct dmar_domain *dmar_domain;
@@ -4843,7 +4900,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
                        pr_err("Can't allocate dmar_domain\n");
                        return NULL;
                }
-               if (domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+               if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
                        pr_err("Domain initialization failed\n");
                        domain_exit(dmar_domain);
                        return NULL;
@@ -5278,6 +5335,7 @@ static int intel_iommu_add_device(struct device *dev)
                if (device_def_domain_type(dev) == IOMMU_DOMAIN_IDENTITY) {
                        ret = iommu_request_dm_for_dev(dev);
                        if (ret) {
+                               dmar_remove_one_dev_info(dev);
                                dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
                                domain_add_dev_info(si_domain, dev);
                                dev_info(dev,
@@ -5288,6 +5346,7 @@ static int intel_iommu_add_device(struct device *dev)
                if (device_def_domain_type(dev) == IOMMU_DOMAIN_DMA) {
                        ret = iommu_request_dma_domain_for_dev(dev);
                        if (ret) {
+                               dmar_remove_one_dev_info(dev);
                                dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
                                if (!get_private_domain_for_dev(dev)) {
                                        dev_warn(dev,
@@ -5313,6 +5372,8 @@ static void intel_iommu_remove_device(struct device *dev)
        if (!iommu)
                return;
 
+       dmar_remove_one_dev_info(dev);
+
        iommu_group_remove_device(dev);
 
        iommu_device_unlink(&iommu->iommu, dev);
index 780de0caafe845cb1b2c031010fcc25402decf31..9b159132405dc750111432bb5435abcae11040af 100644 (file)
@@ -100,24 +100,19 @@ int intel_svm_finish_prq(struct intel_iommu *iommu)
 }
 
 static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_dev *sdev,
-                                      unsigned long address, unsigned long pages, int ih, int gl)
+                               unsigned long address, unsigned long pages, int ih)
 {
        struct qi_desc desc;
 
-       if (pages == -1) {
-               /* For global kernel pages we have to flush them in *all* PASIDs
-                * because that's the only option the hardware gives us. Despite
-                * the fact that they are actually only accessible through one. */
-               if (gl)
-                       desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
-                                       QI_EIOTLB_DID(sdev->did) |
-                                       QI_EIOTLB_GRAN(QI_GRAN_ALL_ALL) |
-                                       QI_EIOTLB_TYPE;
-               else
-                       desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
-                                       QI_EIOTLB_DID(sdev->did) |
-                                       QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
-                                       QI_EIOTLB_TYPE;
+       /*
+        * Do PASID granu IOTLB invalidation if page selective capability is
+        * not available.
+        */
+       if (pages == -1 || !cap_pgsel_inv(svm->iommu->cap)) {
+               desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
+                       QI_EIOTLB_DID(sdev->did) |
+                       QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
+                       QI_EIOTLB_TYPE;
                desc.qw1 = 0;
        } else {
                int mask = ilog2(__roundup_pow_of_two(pages));
@@ -127,7 +122,6 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d
                                QI_EIOTLB_GRAN(QI_GRAN_PSI_PASID) |
                                QI_EIOTLB_TYPE;
                desc.qw1 = QI_EIOTLB_ADDR(address) |
-                               QI_EIOTLB_GL(gl) |
                                QI_EIOTLB_IH(ih) |
                                QI_EIOTLB_AM(mask);
        }
@@ -162,13 +156,13 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d
 }
 
 static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address,
-                                 unsigned long pages, int ih, int gl)
+                               unsigned long pages, int ih)
 {
        struct intel_svm_dev *sdev;
 
        rcu_read_lock();
        list_for_each_entry_rcu(sdev, &svm->devs, list)
-               intel_flush_svm_range_dev(svm, sdev, address, pages, ih, gl);
+               intel_flush_svm_range_dev(svm, sdev, address, pages, ih);
        rcu_read_unlock();
 }
 
@@ -180,7 +174,7 @@ static void intel_invalidate_range(struct mmu_notifier *mn,
        struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
 
        intel_flush_svm_range(svm, start,
-                             (end - start + PAGE_SIZE - 1) >> VTD_PAGE_SHIFT, 0, 0);
+                             (end - start + PAGE_SIZE - 1) >> VTD_PAGE_SHIFT, 0);
 }
 
 static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
@@ -203,7 +197,7 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
        rcu_read_lock();
        list_for_each_entry_rcu(sdev, &svm->devs, list) {
                intel_pasid_tear_down_entry(svm->iommu, sdev->dev, svm->pasid);
-               intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
+               intel_flush_svm_range_dev(svm, sdev, 0, -1, 0);
        }
        rcu_read_unlock();
 
@@ -425,7 +419,7 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
                                 * large and has to be physically contiguous. So it's
                                 * hard to be as defensive as we might like. */
                                intel_pasid_tear_down_entry(iommu, dev, svm->pasid);
-                               intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
+                               intel_flush_svm_range_dev(svm, sdev, 0, -1, 0);
                                kfree_rcu(sdev, rcu);
 
                                if (list_empty(&svm->devs)) {
index d499b26212399bf4e69ccc4d67c991b5afba6207..3e1a8a6755723a927a7942a7429ab7e6c19a0027 100644 (file)
@@ -54,9 +54,14 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 }
 EXPORT_SYMBOL_GPL(init_iova_domain);
 
+bool has_iova_flush_queue(struct iova_domain *iovad)
+{
+       return !!iovad->fq;
+}
+
 static void free_iova_flush_queue(struct iova_domain *iovad)
 {
-       if (!iovad->fq)
+       if (!has_iova_flush_queue(iovad))
                return;
 
        if (timer_pending(&iovad->fq_timer))
@@ -74,13 +79,14 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
 int init_iova_flush_queue(struct iova_domain *iovad,
                          iova_flush_cb flush_cb, iova_entry_dtor entry_dtor)
 {
+       struct iova_fq __percpu *queue;
        int cpu;
 
        atomic64_set(&iovad->fq_flush_start_cnt,  0);
        atomic64_set(&iovad->fq_flush_finish_cnt, 0);
 
-       iovad->fq = alloc_percpu(struct iova_fq);
-       if (!iovad->fq)
+       queue = alloc_percpu(struct iova_fq);
+       if (!queue)
                return -ENOMEM;
 
        iovad->flush_cb   = flush_cb;
@@ -89,13 +95,17 @@ int init_iova_flush_queue(struct iova_domain *iovad,
        for_each_possible_cpu(cpu) {
                struct iova_fq *fq;
 
-               fq = per_cpu_ptr(iovad->fq, cpu);
+               fq = per_cpu_ptr(queue, cpu);
                fq->head = 0;
                fq->tail = 0;
 
                spin_lock_init(&fq->lock);
        }
 
+       smp_wmb();
+
+       iovad->fq = queue;
+
        timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
        atomic_set(&iovad->fq_timer_on, 0);
 
@@ -127,8 +137,9 @@ __cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
        struct iova *cached_iova;
 
        cached_iova = rb_entry(iovad->cached32_node, struct iova, node);
-       if (free->pfn_hi < iovad->dma_32bit_pfn &&
-           free->pfn_lo >= cached_iova->pfn_lo) {
+       if (free == cached_iova ||
+           (free->pfn_hi < iovad->dma_32bit_pfn &&
+            free->pfn_lo >= cached_iova->pfn_lo)) {
                iovad->cached32_node = rb_next(&free->node);
                iovad->max32_alloc_size = iovad->dma_32bit_pfn;
        }
index 433f4d2ee9565be632c1e780e7cdedcdf4254e1d..80a740df0737a638e6170f35c0b8b2a52cce37a0 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Virtio driver for the paravirtualized IOMMU
  *
- * Copyright (C) 2018 Arm Limited
+ * Copyright (C) 2019 Arm Limited
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -47,7 +47,10 @@ struct viommu_dev {
        /* Device configuration */
        struct iommu_domain_geometry    geometry;
        u64                             pgsize_bitmap;
-       u8                              domain_bits;
+       u32                             first_domain;
+       u32                             last_domain;
+       /* Supported MAP flags */
+       u32                             map_flags;
        u32                             probe_size;
 };
 
@@ -62,6 +65,7 @@ struct viommu_domain {
        struct viommu_dev               *viommu;
        struct mutex                    mutex; /* protects viommu pointer */
        unsigned int                    id;
+       u32                             map_flags;
 
        spinlock_t                      mappings_lock;
        struct rb_root_cached           mappings;
@@ -113,6 +117,8 @@ static int viommu_get_req_errno(void *buf, size_t len)
                return -ENOENT;
        case VIRTIO_IOMMU_S_FAULT:
                return -EFAULT;
+       case VIRTIO_IOMMU_S_NOMEM:
+               return -ENOMEM;
        case VIRTIO_IOMMU_S_IOERR:
        case VIRTIO_IOMMU_S_DEVERR:
        default:
@@ -607,15 +613,15 @@ static int viommu_domain_finalise(struct viommu_dev *viommu,
 {
        int ret;
        struct viommu_domain *vdomain = to_viommu_domain(domain);
-       unsigned int max_domain = viommu->domain_bits > 31 ? ~0 :
-                                 (1U << viommu->domain_bits) - 1;
 
        vdomain->viommu         = viommu;
+       vdomain->map_flags      = viommu->map_flags;
 
        domain->pgsize_bitmap   = viommu->pgsize_bitmap;
        domain->geometry        = viommu->geometry;
 
-       ret = ida_alloc_max(&viommu->domain_ids, max_domain, GFP_KERNEL);
+       ret = ida_alloc_range(&viommu->domain_ids, viommu->first_domain,
+                             viommu->last_domain, GFP_KERNEL);
        if (ret >= 0)
                vdomain->id = (unsigned int)ret;
 
@@ -710,7 +716,7 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
                      phys_addr_t paddr, size_t size, int prot)
 {
        int ret;
-       int flags;
+       u32 flags;
        struct virtio_iommu_req_map map;
        struct viommu_domain *vdomain = to_viommu_domain(domain);
 
@@ -718,6 +724,9 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova,
                (prot & IOMMU_WRITE ? VIRTIO_IOMMU_MAP_F_WRITE : 0) |
                (prot & IOMMU_MMIO ? VIRTIO_IOMMU_MAP_F_MMIO : 0);
 
+       if (flags & ~vdomain->map_flags)
+               return -EINVAL;
+
        ret = viommu_add_mapping(vdomain, iova, paddr, size, flags);
        if (ret)
                return ret;
@@ -1027,7 +1036,8 @@ static int viommu_probe(struct virtio_device *vdev)
                goto err_free_vqs;
        }
 
-       viommu->domain_bits = 32;
+       viommu->map_flags = VIRTIO_IOMMU_MAP_F_READ | VIRTIO_IOMMU_MAP_F_WRITE;
+       viommu->last_domain = ~0U;
 
        /* Optional features */
        virtio_cread_feature(vdev, VIRTIO_IOMMU_F_INPUT_RANGE,
@@ -1038,9 +1048,13 @@ static int viommu_probe(struct virtio_device *vdev)
                             struct virtio_iommu_config, input_range.end,
                             &input_end);
 
-       virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_BITS,
-                            struct virtio_iommu_config, domain_bits,
-                            &viommu->domain_bits);
+       virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_RANGE,
+                            struct virtio_iommu_config, domain_range.start,
+                            &viommu->first_domain);
+
+       virtio_cread_feature(vdev, VIRTIO_IOMMU_F_DOMAIN_RANGE,
+                            struct virtio_iommu_config, domain_range.end,
+                            &viommu->last_domain);
 
        virtio_cread_feature(vdev, VIRTIO_IOMMU_F_PROBE,
                             struct virtio_iommu_config, probe_size,
@@ -1052,6 +1066,9 @@ static int viommu_probe(struct virtio_device *vdev)
                .force_aperture = true,
        };
 
+       if (virtio_has_feature(vdev, VIRTIO_IOMMU_F_MMIO))
+               viommu->map_flags |= VIRTIO_IOMMU_MAP_F_MMIO;
+
        viommu_ops.pgsize_bitmap = viommu->pgsize_bitmap;
 
        virtio_device_ready(vdev);
@@ -1130,9 +1147,10 @@ static void viommu_config_changed(struct virtio_device *vdev)
 
 static unsigned int features[] = {
        VIRTIO_IOMMU_F_MAP_UNMAP,
-       VIRTIO_IOMMU_F_DOMAIN_BITS,
        VIRTIO_IOMMU_F_INPUT_RANGE,
+       VIRTIO_IOMMU_F_DOMAIN_RANGE,
        VIRTIO_IOMMU_F_PROBE,
+       VIRTIO_IOMMU_F_MMIO,
 };
 
 static struct virtio_device_id id_table[] = {
index 730fbe0e2a9dfa788b3698cbdcb10b682fe22888..1b5c3672aea277925b57d0e5e9162d7f31dde386 100644 (file)
@@ -3010,7 +3010,7 @@ static int its_vpe_init(struct its_vpe *vpe)
 
        if (!its_alloc_vpe_table(vpe_id)) {
                its_vpe_id_free(vpe_id);
-               its_free_pending_table(vpe->vpt_page);
+               its_free_pending_table(vpt_page);
                return -ENOMEM;
        }
 
index 9bca4896fa6fe4a0e14973354483655f75cf742a..96d927f0f91ad4fa7029130cb9462aa84be7cdf7 100644 (file)
@@ -771,8 +771,10 @@ static void gic_cpu_sys_reg_init(void)
                case 7:
                        write_gicreg(0, ICC_AP0R3_EL1);
                        write_gicreg(0, ICC_AP0R2_EL1);
+               /* Fall through */
                case 6:
                        write_gicreg(0, ICC_AP0R1_EL1);
+               /* Fall through */
                case 5:
                case 4:
                        write_gicreg(0, ICC_AP0R0_EL1);
@@ -786,8 +788,10 @@ static void gic_cpu_sys_reg_init(void)
        case 7:
                write_gicreg(0, ICC_AP1R3_EL1);
                write_gicreg(0, ICC_AP1R2_EL1);
+               /* Fall through */
        case 6:
                write_gicreg(0, ICC_AP1R1_EL1);
+               /* Fall through */
        case 5:
        case 4:
                write_gicreg(0, ICC_AP1R0_EL1);
index bf2237ac5d091cfb48534d3c36197982a41072fe..4f74c15c475557ab2c2c6dd88634df077109e7d6 100644 (file)
@@ -131,6 +131,7 @@ static struct irq_chip gpcv2_irqchip_data_chip = {
        .irq_unmask             = imx_gpcv2_irq_unmask,
        .irq_set_wake           = imx_gpcv2_irq_set_wake,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
+       .irq_set_type           = irq_chip_set_type_parent,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = irq_chip_set_affinity_parent,
 #endif
index 3dd28382d5f5dcefc063281fa9be1a03a7e3efd3..3f09f658e8e29e483f18074052b8a64559e97c1c 100644 (file)
@@ -241,12 +241,15 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
 
                parent = platform_bus_type.dev_root;
                child = of_platform_device_create(np, NULL, parent);
-               if (!child)
+               if (!child) {
+                       of_node_put(np);
                        return -ENOMEM;
+               }
 
                if (of_property_read_u32(child->dev.of_node, "num-pins",
                                         &num_pins) < 0) {
                        dev_err(&pdev->dev, "No num-pins property\n");
+                       of_node_put(np);
                        return -EINVAL;
                }
 
@@ -254,8 +257,10 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
                                                           mbigen_write_msg,
                                                           &mbigen_domain_ops,
                                                           mgn_chip);
-               if (!domain)
+               if (!domain) {
+                       of_node_put(np);
                        return -ENOMEM;
+               }
        }
 
        return 0;
index 3c3ad42f22bfd29da879255593fe3cb7a21e1b3e..c92b405b7646cfbceaed3b6544fb71d145c9bb42 100644 (file)
@@ -688,6 +688,9 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos
        if (!cdev->ap.applid)
                return -ENODEV;
 
+       if (count < CAPIMSG_BASELEN)
+               return -EINVAL;
+
        skb = alloc_skb(count, GFP_USER);
        if (!skb)
                return -ENOMEM;
@@ -698,7 +701,8 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos
        }
        mlen = CAPIMSG_LEN(skb->data);
        if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
-               if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
+               if (count < CAPI_DATA_B3_REQ_LEN ||
+                   (size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
                        kfree_skb(skb);
                        return -EINVAL;
                }
@@ -711,6 +715,10 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos
        CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);
 
        if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {
+               if (count < CAPI_DISCONNECT_B3_RESP_LEN) {
+                       kfree_skb(skb);
+                       return -EINVAL;
+               }
                mutex_lock(&cdev->lock);
                capincci_free(cdev, CAPIMSG_NCCI(skb->data));
                mutex_unlock(&cdev->lock);
index 0e224232f74644e1a1b620ca9c3d1067891e34d9..008a74a1ed444720a29537f037dedfac821d46d1 100644 (file)
@@ -1394,6 +1394,7 @@ start_isoc_chain(struct usb_fifo *fifo, int num_packets_per_urb,
                                printk(KERN_DEBUG
                                       "%s: %s: alloc urb for fifo %i failed",
                                       hw->name, __func__, fifo->fifonum);
+                               continue;
                        }
                        fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
                        fifo->iso[i].indx = i;
@@ -1692,13 +1693,23 @@ hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel)
 static int
 setup_hfcsusb(struct hfcsusb *hw)
 {
+       void *dmabuf = kmalloc(sizeof(u_char), GFP_KERNEL);
        u_char b;
+       int ret;
 
        if (debug & DBG_HFC_CALL_TRACE)
                printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
 
+       if (!dmabuf)
+               return -ENOMEM;
+
+       ret = read_reg_atomic(hw, HFCUSB_CHIP_ID, dmabuf);
+
+       memcpy(&b, dmabuf, sizeof(u_char));
+       kfree(dmabuf);
+
        /* check the chip id */
-       if (read_reg_atomic(hw, HFCUSB_CHIP_ID, &b) != 1) {
+       if (ret != 1) {
                printk(KERN_DEBUG "%s: %s: cannot read chip id\n",
                       hw->name, __func__);
                return 1;
index 276065c888bcdd31b16070f1f78a7695a9c71790..23f1f41c86029092a01d662c1a362552cffa3e04 100644 (file)
@@ -852,6 +852,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd)
                break;
        case SMU_I2C_TRANSFER_COMBINED:
                cmd->info.devaddr &= 0xfe;
+               /* fall through */
        case SMU_I2C_TRANSFER_STDSUB:
                if (cmd->info.sublen > 3)
                        return -EINVAL;
index 26e374fbf57c7873d626e3a84b052a7a8c9d2353..20ed838e9413bf532e47ee6e70f60c56b3499010 100644 (file)
@@ -931,6 +931,9 @@ int bch_cached_dev_run(struct cached_dev *dc)
        if (dc->io_disable) {
                pr_err("I/O disabled on cached dev %s",
                       dc->backing_dev_name);
+               kfree(env[1]);
+               kfree(env[2]);
+               kfree(buf);
                return -EIO;
        }
 
index 9f0826712845050ab6ee3d54abe69980eb8d9216..e2059af9079181e9193795757b2ed5b448741f48 100644 (file)
@@ -23,24 +23,28 @@ static const char * const bch_cache_modes[] = {
        "writethrough",
        "writeback",
        "writearound",
-       "none"
+       "none",
+       NULL
 };
 
 /* Default is 0 ("auto") */
 static const char * const bch_stop_on_failure_modes[] = {
        "auto",
-       "always"
+       "always",
+       NULL
 };
 
 static const char * const cache_replacement_policies[] = {
        "lru",
        "fifo",
-       "random"
+       "random",
+       NULL
 };
 
 static const char * const error_actions[] = {
        "unregister",
-       "panic"
+       "panic",
+       NULL
 };
 
 write_attribute(attach);
@@ -338,7 +342,7 @@ STORE(__cached_dev)
        }
 
        if (attr == &sysfs_cache_mode) {
-               v = sysfs_match_string(bch_cache_modes, buf);
+               v = __sysfs_match_string(bch_cache_modes, -1, buf);
                if (v < 0)
                        return v;
 
@@ -349,7 +353,7 @@ STORE(__cached_dev)
        }
 
        if (attr == &sysfs_stop_when_cache_set_failed) {
-               v = sysfs_match_string(bch_stop_on_failure_modes, buf);
+               v = __sysfs_match_string(bch_stop_on_failure_modes, -1, buf);
                if (v < 0)
                        return v;
 
@@ -816,7 +820,7 @@ STORE(__bch_cache_set)
                            0, UINT_MAX);
 
        if (attr == &sysfs_errors) {
-               v = sysfs_match_string(error_actions, buf);
+               v = __sysfs_match_string(error_actions, -1, buf);
                if (v < 0)
                        return v;
 
@@ -1088,7 +1092,7 @@ STORE(__bch_cache)
        }
 
        if (attr == &sysfs_cache_replacement_policy) {
-               v = sysfs_match_string(cache_replacement_policies, buf);
+               v = __sysfs_match_string(cache_replacement_policies, -1, buf);
                if (v < 0)
                        return v;
 
index b6b5acc92ca2da725de6a7b0f867c7c83b77d464..2a48ea3f1b30d4adfc6581dff3d1cfe1a088b86a 100644 (file)
@@ -1599,7 +1599,9 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
        unsigned long freed;
 
        c = container_of(shrink, struct dm_bufio_client, shrinker);
-       if (!dm_bufio_trylock(c))
+       if (sc->gfp_mask & __GFP_FS)
+               dm_bufio_lock(c);
+       else if (!dm_bufio_trylock(c))
                return SHRINK_STOP;
 
        freed  = __scan(c, sc->nr_to_scan, sc->gfp_mask);
index 845f376a72d9c63f0adced15704e8d7ab979715e..8288887b7f948c31a471358f5de813af00735070 100644 (file)
@@ -25,6 +25,7 @@ struct dust_device {
        unsigned long long badblock_count;
        spinlock_t dust_lock;
        unsigned int blksz;
+       int sect_per_block_shift;
        unsigned int sect_per_block;
        sector_t start;
        bool fail_read_on_bb:1;
@@ -79,7 +80,7 @@ static int dust_remove_block(struct dust_device *dd, unsigned long long block)
        unsigned long flags;
 
        spin_lock_irqsave(&dd->dust_lock, flags);
-       bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
+       bblock = dust_rb_search(&dd->badblocklist, block);
 
        if (bblock == NULL) {
                if (!dd->quiet_mode) {
@@ -113,7 +114,7 @@ static int dust_add_block(struct dust_device *dd, unsigned long long block)
        }
 
        spin_lock_irqsave(&dd->dust_lock, flags);
-       bblock->bb = block * dd->sect_per_block;
+       bblock->bb = block;
        if (!dust_rb_insert(&dd->badblocklist, bblock)) {
                if (!dd->quiet_mode) {
                        DMERR("%s: block %llu already in badblocklist",
@@ -138,7 +139,7 @@ static int dust_query_block(struct dust_device *dd, unsigned long long block)
        unsigned long flags;
 
        spin_lock_irqsave(&dd->dust_lock, flags);
-       bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block);
+       bblock = dust_rb_search(&dd->badblocklist, block);
        if (bblock != NULL)
                DMINFO("%s: block %llu found in badblocklist", __func__, block);
        else
@@ -165,6 +166,7 @@ static int dust_map_read(struct dust_device *dd, sector_t thisblock,
        int ret = DM_MAPIO_REMAPPED;
 
        if (fail_read_on_bb) {
+               thisblock >>= dd->sect_per_block_shift;
                spin_lock_irqsave(&dd->dust_lock, flags);
                ret = __dust_map_read(dd, thisblock);
                spin_unlock_irqrestore(&dd->dust_lock, flags);
@@ -195,6 +197,7 @@ static int dust_map_write(struct dust_device *dd, sector_t thisblock,
        unsigned long flags;
 
        if (fail_read_on_bb) {
+               thisblock >>= dd->sect_per_block_shift;
                spin_lock_irqsave(&dd->dust_lock, flags);
                __dust_map_write(dd, thisblock);
                spin_unlock_irqrestore(&dd->dust_lock, flags);
@@ -331,6 +334,8 @@ static int dust_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        dd->blksz = blksz;
        dd->start = tmp;
 
+       dd->sect_per_block_shift = __ffs(sect_per_block);
+
        /*
         * Whether to fail a read on a "bad" block.
         * Defaults to false; enabled later by message.
index b1b0de402dfc36eb937cc1967dcf4a341057b576..9118ab85cb3ad96414805059f7ec2b96df1a29b3 100644 (file)
@@ -1943,7 +1943,22 @@ offload_to_thread:
                        queue_work(ic->wait_wq, &dio->work);
                        return;
                }
+               if (journal_read_pos != NOT_FOUND)
+                       dio->range.n_sectors = ic->sectors_per_block;
                wait_and_add_new_range(ic, &dio->range);
+               /*
+                * wait_and_add_new_range drops the spinlock, so the journal
+                * may have been changed arbitrarily. We need to recheck.
+                * To simplify the code, we restrict I/O size to just one block.
+                */
+               if (journal_read_pos != NOT_FOUND) {
+                       sector_t next_sector;
+                       unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector);
+                       if (unlikely(new_pos != journal_read_pos)) {
+                               remove_range_unlocked(ic, &dio->range);
+                               goto retry;
+                       }
+               }
        }
        spin_unlock_irq(&ic->endio_wait.lock);
 
index df2011de7be268131211025e227fc5d989334161..1bbe4a34ef4ca62ff59984051ca30be2421c4c6c 100644 (file)
@@ -566,8 +566,10 @@ static int run_io_job(struct kcopyd_job *job)
         * no point in continuing.
         */
        if (test_bit(DM_KCOPYD_WRITE_SEQ, &job->flags) &&
-           job->master_job->write_err)
+           job->master_job->write_err) {
+               job->write_err = job->master_job->write_err;
                return -EIO;
+       }
 
        io_job_start(job->kc->throttle);
 
@@ -619,6 +621,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
                        else
                                job->read_err = 1;
                        push(&kc->complete_jobs, job);
+                       wake(kc);
                        break;
                }
 
index 8a60a4a070ac99669e947e5a68a9e3cf1ad8346e..1f933dd197cdf82e14fc242290e5a3268f478b5f 100644 (file)
@@ -3194,7 +3194,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                          */
                        r = rs_prepare_reshape(rs);
                        if (r)
-                               return r;
+                               goto bad;
 
                        /* Reshaping ain't recovery, so disable recovery */
                        rs_setup_recovery(rs, MaxSector);
index caaee8032afef3705c70862be7458d0d2453f249..8820931ec7d2d70cf90d1c1f65fbdb8881fd559a 100644 (file)
@@ -882,23 +882,23 @@ EXPORT_SYMBOL_GPL(dm_table_set_type);
 
 /* validate the dax capability of the target device span */
 int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
-                                      sector_t start, sector_t len, void *data)
+                       sector_t start, sector_t len, void *data)
 {
        int blocksize = *(int *) data;
 
        return generic_fsdax_supported(dev->dax_dev, dev->bdev, blocksize,
-                       start, len);
+                                      start, len);
 }
 
 /* Check devices support synchronous DAX */
-static int device_synchronous(struct dm_target *ti, struct dm_dev *dev,
-                                      sector_t start, sector_t len, void *data)
+static int device_dax_synchronous(struct dm_target *ti, struct dm_dev *dev,
+                                 sector_t start, sector_t len, void *data)
 {
-       return dax_synchronous(dev->dax_dev);
+       return dev->dax_dev && dax_synchronous(dev->dax_dev);
 }
 
 bool dm_table_supports_dax(struct dm_table *t,
-                         iterate_devices_callout_fn iterate_fn, int *blocksize)
+                          iterate_devices_callout_fn iterate_fn, int *blocksize)
 {
        struct dm_target *ti;
        unsigned i;
@@ -911,7 +911,7 @@ bool dm_table_supports_dax(struct dm_table *t,
                        return false;
 
                if (!ti->type->iterate_devices ||
-                       !ti->type->iterate_devices(ti, iterate_fn, blocksize))
+                   !ti->type->iterate_devices(ti, iterate_fn, blocksize))
                        return false;
        }
 
@@ -1342,7 +1342,7 @@ void dm_table_event(struct dm_table *t)
 }
 EXPORT_SYMBOL(dm_table_event);
 
-sector_t dm_table_get_size(struct dm_table *t)
+inline sector_t dm_table_get_size(struct dm_table *t)
 {
        return t->num_targets ? (t->highs[t->num_targets - 1] + 1) : 0;
 }
@@ -1367,6 +1367,9 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
        unsigned int l, n = 0, k = 0;
        sector_t *node;
 
+       if (unlikely(sector >= dm_table_get_size(t)))
+               return &t->targets[t->num_targets];
+
        for (l = 0; l < t->depth; l++) {
                n = get_child(n, k);
                node = get_node(t, l, n);
@@ -1921,7 +1924,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 
        if (dm_table_supports_dax(t, device_supports_dax, &page_size)) {
                blk_queue_flag_set(QUEUE_FLAG_DAX, q);
-               if (dm_table_supports_dax(t, device_synchronous, NULL))
+               if (dm_table_supports_dax(t, device_dax_synchronous, NULL))
                        set_dax_synchronous(t->md->dax_dev);
        }
        else
index 8545dcee9fd0498d1334656881a02fac426276f5..595a73110e1731efbabd33e14c0f4ec2401da4d8 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
  *
@@ -34,7 +35,7 @@
  *    (1) Super block (1 block)
  *    (2) Chunk mapping table (nr_map_blocks)
  *    (3) Bitmap blocks (nr_bitmap_blocks)
- * All metadata blocks are stored in conventional zones, starting from the
+ * All metadata blocks are stored in conventional zones, starting from
  * the first conventional zone found on disk.
  */
 struct dmz_super {
@@ -233,7 +234,7 @@ void dmz_unlock_map(struct dmz_metadata *zmd)
  * Lock/unlock metadata access. This is a "read" lock on a semaphore
  * that prevents metadata flush from running while metadata are being
  * modified. The actual metadata write mutual exclusion is achieved with
- * the map lock and zone styate management (active and reclaim state are
+ * the map lock and zone state management (active and reclaim state are
  * mutually exclusive).
  */
 void dmz_lock_metadata(struct dmz_metadata *zmd)
@@ -402,15 +403,18 @@ static struct dmz_mblock *dmz_get_mblock_slow(struct dmz_metadata *zmd,
        sector_t block = zmd->sb[zmd->mblk_primary].block + mblk_no;
        struct bio *bio;
 
+       if (dmz_bdev_is_dying(zmd->dev))
+               return ERR_PTR(-EIO);
+
        /* Get a new block and a BIO to read it */
        mblk = dmz_alloc_mblock(zmd, mblk_no);
        if (!mblk)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        bio = bio_alloc(GFP_NOIO, 1);
        if (!bio) {
                dmz_free_mblock(zmd, mblk);
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        spin_lock(&zmd->mblk_lock);
@@ -541,8 +545,8 @@ static struct dmz_mblock *dmz_get_mblock(struct dmz_metadata *zmd,
        if (!mblk) {
                /* Cache miss: read the block from disk */
                mblk = dmz_get_mblock_slow(zmd, mblk_no);
-               if (!mblk)
-                       return ERR_PTR(-ENOMEM);
+               if (IS_ERR(mblk))
+                       return mblk;
        }
 
        /* Wait for on-going read I/O and check for error */
@@ -570,16 +574,19 @@ static void dmz_dirty_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk)
 /*
  * Issue a metadata block write BIO.
  */
-static void dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
-                            unsigned int set)
+static int dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
+                           unsigned int set)
 {
        sector_t block = zmd->sb[set].block + mblk->no;
        struct bio *bio;
 
+       if (dmz_bdev_is_dying(zmd->dev))
+               return -EIO;
+
        bio = bio_alloc(GFP_NOIO, 1);
        if (!bio) {
                set_bit(DMZ_META_ERROR, &mblk->state);
-               return;
+               return -ENOMEM;
        }
 
        set_bit(DMZ_META_WRITING, &mblk->state);
@@ -591,6 +598,8 @@ static void dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk,
        bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_META | REQ_PRIO);
        bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0);
        submit_bio(bio);
+
+       return 0;
 }
 
 /*
@@ -602,6 +611,9 @@ static int dmz_rdwr_block(struct dmz_metadata *zmd, int op, sector_t block,
        struct bio *bio;
        int ret;
 
+       if (dmz_bdev_is_dying(zmd->dev))
+               return -EIO;
+
        bio = bio_alloc(GFP_NOIO, 1);
        if (!bio)
                return -ENOMEM;
@@ -659,22 +671,29 @@ static int dmz_write_dirty_mblocks(struct dmz_metadata *zmd,
 {
        struct dmz_mblock *mblk;
        struct blk_plug plug;
-       int ret = 0;
+       int ret = 0, nr_mblks_submitted = 0;
 
        /* Issue writes */
        blk_start_plug(&plug);
-       list_for_each_entry(mblk, write_list, link)
-               dmz_write_mblock(zmd, mblk, set);
+       list_for_each_entry(mblk, write_list, link) {
+               ret = dmz_write_mblock(zmd, mblk, set);
+               if (ret)
+                       break;
+               nr_mblks_submitted++;
+       }
        blk_finish_plug(&plug);
 
        /* Wait for completion */
        list_for_each_entry(mblk, write_list, link) {
+               if (!nr_mblks_submitted)
+                       break;
                wait_on_bit_io(&mblk->state, DMZ_META_WRITING,
                               TASK_UNINTERRUPTIBLE);
                if (test_bit(DMZ_META_ERROR, &mblk->state)) {
                        clear_bit(DMZ_META_ERROR, &mblk->state);
                        ret = -EIO;
                }
+               nr_mblks_submitted--;
        }
 
        /* Flush drive cache (this will also sync data) */
@@ -736,6 +755,11 @@ int dmz_flush_metadata(struct dmz_metadata *zmd)
         */
        dmz_lock_flush(zmd);
 
+       if (dmz_bdev_is_dying(zmd->dev)) {
+               ret = -EIO;
+               goto out;
+       }
+
        /* Get dirty blocks */
        spin_lock(&zmd->mblk_lock);
        list_splice_init(&zmd->mblk_dirty_list, &write_list);
@@ -1542,7 +1566,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd)
        struct dm_zone *zone;
 
        if (list_empty(&zmd->map_rnd_list))
-               return NULL;
+               return ERR_PTR(-EBUSY);
 
        list_for_each_entry(zone, &zmd->map_rnd_list, link) {
                if (dmz_is_buf(zone))
@@ -1553,7 +1577,7 @@ static struct dm_zone *dmz_get_rnd_zone_for_reclaim(struct dmz_metadata *zmd)
                        return dzone;
        }
 
-       return NULL;
+       return ERR_PTR(-EBUSY);
 }
 
 /*
@@ -1564,7 +1588,7 @@ static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd)
        struct dm_zone *zone;
 
        if (list_empty(&zmd->map_seq_list))
-               return NULL;
+               return ERR_PTR(-EBUSY);
 
        list_for_each_entry(zone, &zmd->map_seq_list, link) {
                if (!zone->bzone)
@@ -1573,7 +1597,7 @@ static struct dm_zone *dmz_get_seq_zone_for_reclaim(struct dmz_metadata *zmd)
                        return zone;
        }
 
-       return NULL;
+       return ERR_PTR(-EBUSY);
 }
 
 /*
@@ -1628,9 +1652,13 @@ again:
                if (op != REQ_OP_WRITE)
                        goto out;
 
-               /* Alloate a random zone */
+               /* Allocate a random zone */
                dzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND);
                if (!dzone) {
+                       if (dmz_bdev_is_dying(zmd->dev)) {
+                               dzone = ERR_PTR(-EIO);
+                               goto out;
+                       }
                        dmz_wait_for_free_zones(zmd);
                        goto again;
                }
@@ -1725,9 +1753,13 @@ again:
        if (bzone)
                goto out;
 
-       /* Alloate a random zone */
+       /* Allocate a random zone */
        bzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND);
        if (!bzone) {
+               if (dmz_bdev_is_dying(zmd->dev)) {
+                       bzone = ERR_PTR(-EIO);
+                       goto out;
+               }
                dmz_wait_for_free_zones(zmd);
                goto again;
        }
index edf4b95eb0750dc6485513d49c240b2982017114..d240d7ca8a8ae6f35cc23f63c69070a931bb327a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
  *
@@ -37,7 +38,7 @@ enum {
 /*
  * Number of seconds of target BIO inactivity to consider the target idle.
  */
-#define DMZ_IDLE_PERIOD                (10UL * HZ)
+#define DMZ_IDLE_PERIOD                        (10UL * HZ)
 
 /*
  * Percentage of unmapped (free) random zones below which reclaim starts
@@ -134,6 +135,9 @@ static int dmz_reclaim_copy(struct dmz_reclaim *zrc,
                set_bit(DM_KCOPYD_WRITE_SEQ, &flags);
 
        while (block < end_block) {
+               if (dev->flags & DMZ_BDEV_DYING)
+                       return -EIO;
+
                /* Get a valid region from the source zone */
                ret = dmz_first_valid_block(zmd, src_zone, &block);
                if (ret <= 0)
@@ -215,7 +219,7 @@ static int dmz_reclaim_buf(struct dmz_reclaim *zrc, struct dm_zone *dzone)
 
        dmz_unlock_flush(zmd);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -259,7 +263,7 @@ static int dmz_reclaim_seq_data(struct dmz_reclaim *zrc, struct dm_zone *dzone)
 
        dmz_unlock_flush(zmd);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -312,7 +316,7 @@ static int dmz_reclaim_rnd_data(struct dmz_reclaim *zrc, struct dm_zone *dzone)
 
        dmz_unlock_flush(zmd);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -334,7 +338,7 @@ static void dmz_reclaim_empty(struct dmz_reclaim *zrc, struct dm_zone *dzone)
 /*
  * Find a candidate zone for reclaim and process it.
  */
-static void dmz_reclaim(struct dmz_reclaim *zrc)
+static int dmz_do_reclaim(struct dmz_reclaim *zrc)
 {
        struct dmz_metadata *zmd = zrc->metadata;
        struct dm_zone *dzone;
@@ -344,8 +348,8 @@ static void dmz_reclaim(struct dmz_reclaim *zrc)
 
        /* Get a data zone */
        dzone = dmz_get_zone_for_reclaim(zmd);
-       if (!dzone)
-               return;
+       if (IS_ERR(dzone))
+               return PTR_ERR(dzone);
 
        start = jiffies;
 
@@ -391,13 +395,20 @@ static void dmz_reclaim(struct dmz_reclaim *zrc)
 out:
        if (ret) {
                dmz_unlock_zone_reclaim(dzone);
-               return;
+               return ret;
        }
 
-       (void) dmz_flush_metadata(zrc->metadata);
+       ret = dmz_flush_metadata(zrc->metadata);
+       if (ret) {
+               dmz_dev_debug(zrc->dev,
+                             "Metadata flush for zone %u failed, err %d\n",
+                             dmz_id(zmd, rzone), ret);
+               return ret;
+       }
 
        dmz_dev_debug(zrc->dev, "Reclaimed zone %u in %u ms",
                      dmz_id(zmd, rzone), jiffies_to_msecs(jiffies - start));
+       return 0;
 }
 
 /*
@@ -427,7 +438,7 @@ static bool dmz_should_reclaim(struct dmz_reclaim *zrc)
                return false;
 
        /*
-        * If the percentage of unmappped random zones is low,
+        * If the percentage of unmapped random zones is low,
         * reclaim even if the target is busy.
         */
        return p_unmap_rnd <= DMZ_RECLAIM_LOW_UNMAP_RND;
@@ -442,6 +453,10 @@ static void dmz_reclaim_work(struct work_struct *work)
        struct dmz_metadata *zmd = zrc->metadata;
        unsigned int nr_rnd, nr_unmap_rnd;
        unsigned int p_unmap_rnd;
+       int ret;
+
+       if (dmz_bdev_is_dying(zrc->dev))
+               return;
 
        if (!dmz_should_reclaim(zrc)) {
                mod_delayed_work(zrc->wq, &zrc->work, DMZ_IDLE_PERIOD);
@@ -471,7 +486,17 @@ static void dmz_reclaim_work(struct work_struct *work)
                      (dmz_target_idle(zrc) ? "Idle" : "Busy"),
                      p_unmap_rnd, nr_unmap_rnd, nr_rnd);
 
-       dmz_reclaim(zrc);
+       ret = dmz_do_reclaim(zrc);
+       if (ret) {
+               dmz_dev_debug(zrc->dev, "Reclaim error %d\n", ret);
+               if (ret == -EIO)
+                       /*
+                        * LLD might be performing some error handling sequence
+                        * at the underlying device. To not interfere, do not
+                        * attempt to schedule the next reclaim run immediately.
+                        */
+                       return;
+       }
 
        dmz_schedule_reclaim(zrc);
 }
index 51d029bbb740c4f032ea63005611b194fcc5cee8..31478fef6032daf0c84eb8db29263816f91117b3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
  *
@@ -133,6 +134,8 @@ static int dmz_submit_bio(struct dmz_target *dmz, struct dm_zone *zone,
 
        refcount_inc(&bioctx->ref);
        generic_make_request(clone);
+       if (clone->bi_status == BLK_STS_IOERR)
+               return -EIO;
 
        if (bio_op(bio) == REQ_OP_WRITE && dmz_is_seq(zone))
                zone->wp_block += nr_blocks;
@@ -277,8 +280,8 @@ static int dmz_handle_buffered_write(struct dmz_target *dmz,
 
        /* Get the buffer zone. One will be allocated if needed */
        bzone = dmz_get_chunk_buffer(zmd, zone);
-       if (!bzone)
-               return -ENOSPC;
+       if (IS_ERR(bzone))
+               return PTR_ERR(bzone);
 
        if (dmz_is_readonly(bzone))
                return -EROFS;
@@ -389,6 +392,11 @@ static void dmz_handle_bio(struct dmz_target *dmz, struct dm_chunk_work *cw,
 
        dmz_lock_metadata(zmd);
 
+       if (dmz->dev->flags & DMZ_BDEV_DYING) {
+               ret = -EIO;
+               goto out;
+       }
+
        /*
         * Get the data zone mapping the chunk. There may be no
         * mapping for read and discard. If a mapping is obtained,
@@ -493,6 +501,8 @@ static void dmz_flush_work(struct work_struct *work)
 
        /* Flush dirty metadata blocks */
        ret = dmz_flush_metadata(dmz->metadata);
+       if (ret)
+               dmz_dev_debug(dmz->dev, "Metadata flush failed, rc=%d\n", ret);
 
        /* Process queued flush requests */
        while (1) {
@@ -513,22 +523,24 @@ static void dmz_flush_work(struct work_struct *work)
  * Get a chunk work and start it to process a new BIO.
  * If the BIO chunk has no work yet, create one.
  */
-static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
+static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
 {
        unsigned int chunk = dmz_bio_chunk(dmz->dev, bio);
        struct dm_chunk_work *cw;
+       int ret = 0;
 
        mutex_lock(&dmz->chunk_lock);
 
        /* Get the BIO chunk work. If one is not active yet, create one */
        cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk);
        if (!cw) {
-               int ret;
 
                /* Create a new chunk work */
                cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO);
-               if (!cw)
+               if (unlikely(!cw)) {
+                       ret = -ENOMEM;
                        goto out;
+               }
 
                INIT_WORK(&cw->work, dmz_chunk_work);
                refcount_set(&cw->refcount, 0);
@@ -539,7 +551,6 @@ static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
                ret = radix_tree_insert(&dmz->chunk_rxtree, chunk, cw);
                if (unlikely(ret)) {
                        kfree(cw);
-                       cw = NULL;
                        goto out;
                }
        }
@@ -547,10 +558,38 @@ static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
        bio_list_add(&cw->bio_list, bio);
        dmz_get_chunk_work(cw);
 
+       dmz_reclaim_bio_acc(dmz->reclaim);
        if (queue_work(dmz->chunk_wq, &cw->work))
                dmz_get_chunk_work(cw);
 out:
        mutex_unlock(&dmz->chunk_lock);
+       return ret;
+}
+
+/*
+ * Check the backing device availability. If it's on the way out,
+ * start failing I/O. Reclaim and metadata components also call this
+ * function to cleanly abort operation in the event of such failure.
+ */
+bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev)
+{
+       struct gendisk *disk;
+
+       if (!(dmz_dev->flags & DMZ_BDEV_DYING)) {
+               disk = dmz_dev->bdev->bd_disk;
+               if (blk_queue_dying(bdev_get_queue(dmz_dev->bdev))) {
+                       dmz_dev_warn(dmz_dev, "Backing device queue dying");
+                       dmz_dev->flags |= DMZ_BDEV_DYING;
+               } else if (disk->fops->check_events) {
+                       if (disk->fops->check_events(disk, 0) &
+                                       DISK_EVENT_MEDIA_CHANGE) {
+                               dmz_dev_warn(dmz_dev, "Backing device offline");
+                               dmz_dev->flags |= DMZ_BDEV_DYING;
+                       }
+               }
+       }
+
+       return dmz_dev->flags & DMZ_BDEV_DYING;
 }
 
 /*
@@ -564,6 +603,10 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
        sector_t sector = bio->bi_iter.bi_sector;
        unsigned int nr_sectors = bio_sectors(bio);
        sector_t chunk_sector;
+       int ret;
+
+       if (dmz_bdev_is_dying(dmz->dev))
+               return DM_MAPIO_KILL;
 
        dmz_dev_debug(dev, "BIO op %d sector %llu + %u => chunk %llu, block %llu, %u blocks",
                      bio_op(bio), (unsigned long long)sector, nr_sectors,
@@ -601,8 +644,14 @@ static int dmz_map(struct dm_target *ti, struct bio *bio)
                dm_accept_partial_bio(bio, dev->zone_nr_sectors - chunk_sector);
 
        /* Now ready to handle this BIO */
-       dmz_reclaim_bio_acc(dmz->reclaim);
-       dmz_queue_chunk_work(dmz, bio);
+       ret = dmz_queue_chunk_work(dmz, bio);
+       if (ret) {
+               dmz_dev_debug(dmz->dev,
+                             "BIO op %d, can't process chunk %llu, err %i\n",
+                             bio_op(bio), (u64)dmz_bio_chunk(dmz->dev, bio),
+                             ret);
+               return DM_MAPIO_REQUEUE;
+       }
 
        return DM_MAPIO_SUBMITTED;
 }
@@ -855,6 +904,9 @@ static int dmz_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
 {
        struct dmz_target *dmz = ti->private;
 
+       if (dmz_bdev_is_dying(dmz->dev))
+               return -ENODEV;
+
        *bdev = dmz->dev->bdev;
 
        return 0;
index ed8de49c9a08263e8ca25ff2979abb2958b4cde0..d8e70b0ade354c7ea6b3e4a262aaac1bc788f43b 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
  *
@@ -56,6 +57,8 @@ struct dmz_dev {
 
        unsigned int            nr_zones;
 
+       unsigned int            flags;
+
        sector_t                zone_nr_sectors;
        unsigned int            zone_nr_sectors_shift;
 
@@ -67,6 +70,9 @@ struct dmz_dev {
                                 (dev)->zone_nr_sectors_shift)
 #define dmz_chunk_block(dev, b)        ((b) & ((dev)->zone_nr_blocks - 1))
 
+/* Device flags. */
+#define DMZ_BDEV_DYING         (1 << 0)
+
 /*
  * Zone descriptor.
  */
@@ -245,4 +251,9 @@ void dmz_resume_reclaim(struct dmz_reclaim *zrc);
 void dmz_reclaim_bio_acc(struct dmz_reclaim *zrc);
 void dmz_schedule_reclaim(struct dmz_reclaim *zrc);
 
+/*
+ * Functions defined in dm-zoned-target.c
+ */
+bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev);
+
 #endif /* DM_ZONED_H */
index 58b319757b1e5a1c274bd98681d6ce229bbbabbe..8aae0624a2971e939fa79acd656f98035049460d 100644 (file)
@@ -628,39 +628,40 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
 
        new_parent = shadow_current(s);
 
+       pn = dm_block_data(new_parent);
+       size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
+               sizeof(__le64) : s->info->value_type.size;
+
+       /* create & init the left block */
        r = new_block(s->info, &left);
        if (r < 0)
                return r;
 
+       ln = dm_block_data(left);
+       nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
+
+       ln->header.flags = pn->header.flags;
+       ln->header.nr_entries = cpu_to_le32(nr_left);
+       ln->header.max_entries = pn->header.max_entries;
+       ln->header.value_size = pn->header.value_size;
+       memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
+       memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size);
+
+       /* create & init the right block */
        r = new_block(s->info, &right);
        if (r < 0) {
                unlock_block(s->info, left);
                return r;
        }
 
-       pn = dm_block_data(new_parent);
-       ln = dm_block_data(left);
        rn = dm_block_data(right);
-
-       nr_left = le32_to_cpu(pn->header.nr_entries) / 2;
        nr_right = le32_to_cpu(pn->header.nr_entries) - nr_left;
 
-       ln->header.flags = pn->header.flags;
-       ln->header.nr_entries = cpu_to_le32(nr_left);
-       ln->header.max_entries = pn->header.max_entries;
-       ln->header.value_size = pn->header.value_size;
-
        rn->header.flags = pn->header.flags;
        rn->header.nr_entries = cpu_to_le32(nr_right);
        rn->header.max_entries = pn->header.max_entries;
        rn->header.value_size = pn->header.value_size;
-
-       memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0]));
        memcpy(rn->keys, pn->keys + nr_left, nr_right * sizeof(pn->keys[0]));
-
-       size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ?
-               sizeof(__le64) : s->info->value_type.size;
-       memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size);
        memcpy(value_ptr(rn, 0), value_ptr(pn, nr_left),
               nr_right * size);
 
index aec44924396622729f64e84abda381d24606e14a..25328582cc4820dc29d0e79a8012eeeb8a7fb2f4 100644 (file)
@@ -249,7 +249,7 @@ static int out(struct sm_metadata *smm)
        }
 
        if (smm->recursion_count == 1)
-               apply_bops(smm);
+               r = apply_bops(smm);
 
        smm->recursion_count--;
 
index 29e3f5da59c1ff61137f66d93b75b865521ed5e1..11ec048929e80109e6702249aea0b345e79378d3 100644 (file)
@@ -253,8 +253,7 @@ int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
         */
 
        pixsize = vout->bpp * vout->vrfb_bpp;
-       dst_icg = ((MAX_PIXELS_PER_LINE * pixsize) -
-                 (vout->pix.width * vout->bpp)) + 1;
+       dst_icg = MAX_PIXELS_PER_LINE * pixsize - vout->pix.width * vout->bpp;
 
        xt->src_start = vout->buf_phy_addr[vb->i];
        xt->dst_start = vout->vrfb_context[vb->i].paddr[0];
index bc2a176937a447d3ebd3b3e67bbaec038c7a993f..d535aac68ce168c37fb8542cbfa2599a056b3686 100644 (file)
@@ -1099,6 +1099,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 
        /* start creating the vb2 queues */
        if (dev->has_vid_cap) {
+               snprintf(dev->vid_cap_dev.name, sizeof(dev->vid_cap_dev.name),
+                        "vivid-%03d-vid-cap", inst);
                /* initialize vid_cap queue */
                q = &dev->vb_vid_cap_q;
                q->type = dev->multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
@@ -1122,6 +1124,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
        }
 
        if (dev->has_vid_out) {
+               snprintf(dev->vid_out_dev.name, sizeof(dev->vid_out_dev.name),
+                        "vivid-%03d-vid-out", inst);
                /* initialize vid_out queue */
                q = &dev->vb_vid_out_q;
                q->type = dev->multiplanar ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
@@ -1265,8 +1269,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
        /* finally start creating the device nodes */
        if (dev->has_vid_cap) {
                vfd = &dev->vid_cap_dev;
-               snprintf(vfd->name, sizeof(vfd->name),
-                        "vivid-%03d-vid-cap", inst);
                vfd->fops = &vivid_fops;
                vfd->ioctl_ops = &vivid_ioctl_ops;
                vfd->device_caps = dev->vid_cap_caps;
@@ -1312,8 +1314,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 
        if (dev->has_vid_out) {
                vfd = &dev->vid_out_dev;
-               snprintf(vfd->name, sizeof(vfd->name),
-                        "vivid-%03d-vid-out", inst);
                vfd->vfl_dir = VFL_DIR_TX;
                vfd->fops = &vivid_fops;
                vfd->ioctl_ops = &vivid_ioctl_ops;
index 21fb90d66bfc319b4e27ad073f3126fe496a98b8..25c73c13cc7ef830b72b70de39015bd8e48190d7 100644 (file)
@@ -124,7 +124,7 @@ static inline int check_which(__u32 which)
 static inline int check_pad(struct v4l2_subdev *sd, __u32 pad)
 {
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (sd->entity.graph_obj.mdev) {
+       if (sd->entity.num_pads) {
                if (pad >= sd->entity.num_pads)
                        return -EINVAL;
                return 0;
index 3f21e26b8d36e7c906603dc65f4b64aa1301dfe2..90e0f21bc49c55045bb03ff7582200b403b320a7 100644 (file)
@@ -1590,8 +1590,10 @@ static unsigned long dsiclk_rate(u8 n)
        switch (divsel) {
        case PRCM_DSI_PLLOUT_SEL_PHI_4:
                div *= 2;
+               /* Fall through */
        case PRCM_DSI_PLLOUT_SEL_PHI_2:
                div *= 2;
+               /* Fall through */
        case PRCM_DSI_PLLOUT_SEL_PHI:
                return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
                        PLL_RAW) / div;
index 792b855a9104311f62b980e81a9aa3ab5500e0a5..4798d9f3f9d50bbbb50a6c4443421378704565f2 100644 (file)
@@ -308,7 +308,7 @@ static int usbhs_runtime_resume(struct device *dev)
                                         i, r);
                                }
                        }
-               /* Fall through as HSIC mode needs utmi_clk */
+               /* Fall through as HSIC mode needs utmi_clk */
 
                case OMAP_EHCI_PORT_MODE_TLL:
                        if (!IS_ERR(omap->utmi_clk[i])) {
@@ -344,7 +344,7 @@ static int usbhs_runtime_suspend(struct device *dev)
 
                        if (!IS_ERR(omap->hsic480m_clk[i]))
                                clk_disable_unprepare(omap->hsic480m_clk[i]);
-               /* Fall through as utmi_clks were used in HSIC mode */
+               /* Fall through as utmi_clks were used in HSIC mode */
 
                case OMAP_EHCI_PORT_MODE_TLL:
                        if (!IS_ERR(omap->utmi_clk[i]))
index 601cefb5c9d8eb2b24e6f2c194cf446a3477b680..050478cabc95d045f3a42880353954e2a296a861 100644 (file)
@@ -729,7 +729,7 @@ static int rk808_remove(struct i2c_client *client)
        return 0;
 }
 
-static int rk8xx_suspend(struct device *dev)
+static int __maybe_unused rk8xx_suspend(struct device *dev)
 {
        struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
        int ret = 0;
@@ -749,7 +749,7 @@ static int rk8xx_suspend(struct device *dev)
        return ret;
 }
 
-static int rk8xx_resume(struct device *dev)
+static int __maybe_unused rk8xx_resume(struct device *dev)
 {
        struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
        int ret = 0;
@@ -768,7 +768,7 @@ static int rk8xx_resume(struct device *dev)
 
        return ret;
 }
-SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume);
+static SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume);
 
 static struct i2c_driver rk808_i2c_driver = {
        .driver = {
index 6abfc8e92fcc14b2584cc7baa7e2d4be77cb5243..16900357afc25a7d65a9a717c14de156b6fe7c28 100644 (file)
@@ -465,6 +465,7 @@ config PCI_ENDPOINT_TEST
 
 config XILINX_SDFEC
        tristate "Xilinx SDFEC 16"
+       depends on HAS_IOMEM
        help
          This option enables support for the Xilinx SDFEC (Soft Decision
          Forward Error Correction) driver. This enables a char driver
index f88094719552b04a78db3d6d3b30f5daf09e171b..f2abe27010eff1333730901538bc9710bb0c0a7b 100644 (file)
@@ -5,6 +5,7 @@ config EEPROM_AT24
        tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
        depends on I2C && SYSFS
        select NVMEM
+       select NVMEM_SYSFS
        select REGMAP_I2C
        help
          Enable this driver to get read/write support to most I2C EEPROMs
@@ -34,6 +35,7 @@ config EEPROM_AT25
        tristate "SPI EEPROMs from most vendors"
        depends on SPI && SYSFS
        select NVMEM
+       select NVMEM_SYSFS
        help
          Enable this driver to get read/write support to most SPI EEPROMs,
          after you configure the board init code to know about each eeprom
@@ -80,6 +82,7 @@ config EEPROM_93XX46
        depends on SPI && SYSFS
        select REGMAP
        select NVMEM
+       select NVMEM_SYSFS
        help
          Driver for the microwire EEPROM chipsets 93xx46x. The driver
          supports both read and write commands and also the command to
index 35bf2477693d31a375469f13dd1800e98f3f5c0b..518945b2f73740c2a3f15dde2c73fcaace8cceb8 100644 (file)
@@ -685,7 +685,7 @@ static int at24_probe(struct i2c_client *client)
        nvmem_config.name = dev_name(dev);
        nvmem_config.dev = dev;
        nvmem_config.read_only = !writable;
-       nvmem_config.root_only = true;
+       nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO);
        nvmem_config.owner = THIS_MODULE;
        nvmem_config.compat = true;
        nvmem_config.base_dev = dev;
index 6ad83d5ef4b006759351962d54795b724e0dc590..f00d1c32f6d6f83a3e523abc0d8301057d6cadc5 100644 (file)
@@ -683,7 +683,7 @@ int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data)
 
                rc = hl_poll_timeout_memory(hdev,
                        &ctx->thread_ctx_switch_wait_token, tmp, (tmp == 1),
-                       100, jiffies_to_usecs(hdev->timeout_jiffies));
+                       100, jiffies_to_usecs(hdev->timeout_jiffies), false);
 
                if (rc == -ETIMEDOUT) {
                        dev_err(hdev->dev,
index 0c4894dd9c02a9e8c5e8ac648d3052715a6c17aa..7a8f9d0b71b54a81b4cce20fcbad3734c0369db9 100644 (file)
@@ -970,7 +970,8 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
        rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
        if (rc) {
                dev_err(hdev->dev, "failed to initialize kernel context\n");
-               goto free_ctx;
+               kfree(hdev->kernel_ctx);
+               goto mmu_fini;
        }
 
        rc = hl_cb_pool_init(hdev);
@@ -1053,8 +1054,6 @@ release_ctx:
        if (hl_ctx_put(hdev->kernel_ctx) != 1)
                dev_err(hdev->dev,
                        "kernel ctx is still alive on initialization failure\n");
-free_ctx:
-       kfree(hdev->kernel_ctx);
 mmu_fini:
        hl_mmu_fini(hdev);
 eq_fini:
index cc8168bacb24b3b90d2c8b7cf196246e8f1df7fe..ea2ca67fbfbfaf9fc01f8160b539a57149bd8e0f 100644 (file)
@@ -24,7 +24,7 @@ int hl_fw_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
 {
        const struct firmware *fw;
        const u64 *fw_data;
-       size_t fw_size, i;
+       size_t fw_size;
        int rc;
 
        rc = request_firmware(&fw, fw_name, hdev->dev);
@@ -45,22 +45,7 @@ int hl_fw_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
 
        fw_data = (const u64 *) fw->data;
 
-       if ((fw->size % 8) != 0)
-               fw_size -= 8;
-
-       for (i = 0 ; i < fw_size ; i += 8, fw_data++, dst += 8) {
-               if (!(i & (0x80000 - 1))) {
-                       dev_dbg(hdev->dev,
-                               "copied so far %zu out of %zu for %s firmware",
-                               i, fw_size, fw_name);
-                       usleep_range(20, 100);
-               }
-
-               writeq(*fw_data, dst);
-       }
-
-       if ((fw->size % 8) != 0)
-               writel(*(const u32 *) fw_data, dst);
+       memcpy_toio(dst, fw_data, fw_size);
 
 out:
        release_firmware(fw);
@@ -112,7 +97,8 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg,
        }
 
        rc = hl_poll_timeout_memory(hdev, &pkt->fence, tmp,
-                               (tmp == ARMCP_PACKET_FENCE_VAL), 1000, timeout);
+                               (tmp == ARMCP_PACKET_FENCE_VAL), 1000,
+                               timeout, true);
 
        hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id);
 
index 75294ec652577f9939b35fd90e6a78c37ba6cf99..271c5c8f53b4e72887b21c887c0920879512d79b 100644 (file)
@@ -695,8 +695,8 @@ static int goya_sw_init(struct hl_device *hdev)
                goto free_dma_pool;
        }
 
-       dev_dbg(hdev->dev, "cpu accessible memory at bus address 0x%llx\n",
-               hdev->cpu_accessible_dma_address);
+       dev_dbg(hdev->dev, "cpu accessible memory at bus address %pad\n",
+               &hdev->cpu_accessible_dma_address);
 
        hdev->cpu_accessible_dma_pool = gen_pool_create(ilog2(32), -1);
        if (!hdev->cpu_accessible_dma_pool) {
@@ -2729,9 +2729,10 @@ void goya_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi)
                                GOYA_ASYNC_EVENT_ID_PI_UPDATE);
 }
 
-void goya_flush_pq_write(struct hl_device *hdev, u64 *pq, u64 exp_val)
+void goya_pqe_write(struct hl_device *hdev, __le64 *pqe, struct hl_bd *bd)
 {
-       /* Not needed in Goya */
+       /* The QMANs are on the SRAM so need to copy to IO space */
+       memcpy_toio((void __iomem *) pqe, bd, sizeof(struct hl_bd));
 }
 
 static void *goya_dma_alloc_coherent(struct hl_device *hdev, size_t size,
@@ -2864,7 +2865,8 @@ static int goya_send_job_on_qman0(struct hl_device *hdev, struct hl_cs_job *job)
        }
 
        rc = hl_poll_timeout_memory(hdev, fence_ptr, tmp,
-                               (tmp == GOYA_QMAN0_FENCE_VAL), 1000, timeout);
+                               (tmp == GOYA_QMAN0_FENCE_VAL), 1000,
+                               timeout, true);
 
        hl_hw_queue_inc_ci_kernel(hdev, GOYA_QUEUE_ID_DMA_0);
 
@@ -2945,7 +2947,7 @@ int goya_test_queue(struct hl_device *hdev, u32 hw_queue_id)
        }
 
        rc = hl_poll_timeout_memory(hdev, fence_ptr, tmp, (tmp == fence_val),
-                                       1000, GOYA_TEST_QUEUE_WAIT_USEC);
+                                       1000, GOYA_TEST_QUEUE_WAIT_USEC, true);
 
        hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id);
 
@@ -3312,9 +3314,11 @@ static int goya_validate_dma_pkt_no_mmu(struct hl_device *hdev,
        int rc;
 
        dev_dbg(hdev->dev, "DMA packet details:\n");
-       dev_dbg(hdev->dev, "source == 0x%llx\n", user_dma_pkt->src_addr);
-       dev_dbg(hdev->dev, "destination == 0x%llx\n", user_dma_pkt->dst_addr);
-       dev_dbg(hdev->dev, "size == %u\n", user_dma_pkt->tsize);
+       dev_dbg(hdev->dev, "source == 0x%llx\n",
+               le64_to_cpu(user_dma_pkt->src_addr));
+       dev_dbg(hdev->dev, "destination == 0x%llx\n",
+               le64_to_cpu(user_dma_pkt->dst_addr));
+       dev_dbg(hdev->dev, "size == %u\n", le32_to_cpu(user_dma_pkt->tsize));
 
        ctl = le32_to_cpu(user_dma_pkt->ctl);
        user_dir = (ctl & GOYA_PKT_LIN_DMA_CTL_DMA_DIR_MASK) >>
@@ -3343,9 +3347,11 @@ static int goya_validate_dma_pkt_mmu(struct hl_device *hdev,
                                struct packet_lin_dma *user_dma_pkt)
 {
        dev_dbg(hdev->dev, "DMA packet details:\n");
-       dev_dbg(hdev->dev, "source == 0x%llx\n", user_dma_pkt->src_addr);
-       dev_dbg(hdev->dev, "destination == 0x%llx\n", user_dma_pkt->dst_addr);
-       dev_dbg(hdev->dev, "size == %u\n", user_dma_pkt->tsize);
+       dev_dbg(hdev->dev, "source == 0x%llx\n",
+               le64_to_cpu(user_dma_pkt->src_addr));
+       dev_dbg(hdev->dev, "destination == 0x%llx\n",
+               le64_to_cpu(user_dma_pkt->dst_addr));
+       dev_dbg(hdev->dev, "size == %u\n", le32_to_cpu(user_dma_pkt->tsize));
 
        /*
         * WA for HW-23.
@@ -3385,7 +3391,8 @@ static int goya_validate_wreg32(struct hl_device *hdev,
 
        dev_dbg(hdev->dev, "WREG32 packet details:\n");
        dev_dbg(hdev->dev, "reg_offset == 0x%x\n", reg_offset);
-       dev_dbg(hdev->dev, "value      == 0x%x\n", wreg_pkt->value);
+       dev_dbg(hdev->dev, "value      == 0x%x\n",
+               le32_to_cpu(wreg_pkt->value));
 
        if (reg_offset != (mmDMA_CH_0_WR_COMP_ADDR_LO & 0x1FFF)) {
                dev_err(hdev->dev, "WREG32 packet with illegal address 0x%x\n",
@@ -3427,12 +3434,13 @@ static int goya_validate_cb(struct hl_device *hdev,
        while (cb_parsed_length < parser->user_cb_size) {
                enum packet_id pkt_id;
                u16 pkt_size;
-               void *user_pkt;
+               struct goya_packet *user_pkt;
 
-               user_pkt = (void *) (uintptr_t)
+               user_pkt = (struct goya_packet *) (uintptr_t)
                        (parser->user_cb->kernel_address + cb_parsed_length);
 
-               pkt_id = (enum packet_id) (((*(u64 *) user_pkt) &
+               pkt_id = (enum packet_id) (
+                               (le64_to_cpu(user_pkt->header) &
                                PACKET_HEADER_PACKET_ID_MASK) >>
                                        PACKET_HEADER_PACKET_ID_SHIFT);
 
@@ -3452,7 +3460,8 @@ static int goya_validate_cb(struct hl_device *hdev,
                         * need to validate here as well because patch_cb() is
                         * not called in MMU path while this function is called
                         */
-                       rc = goya_validate_wreg32(hdev, parser, user_pkt);
+                       rc = goya_validate_wreg32(hdev,
+                               parser, (struct packet_wreg32 *) user_pkt);
                        break;
 
                case PACKET_WREG_BULK:
@@ -3480,10 +3489,10 @@ static int goya_validate_cb(struct hl_device *hdev,
                case PACKET_LIN_DMA:
                        if (is_mmu)
                                rc = goya_validate_dma_pkt_mmu(hdev, parser,
-                                               user_pkt);
+                                       (struct packet_lin_dma *) user_pkt);
                        else
                                rc = goya_validate_dma_pkt_no_mmu(hdev, parser,
-                                               user_pkt);
+                                       (struct packet_lin_dma *) user_pkt);
                        break;
 
                case PACKET_MSG_LONG:
@@ -3656,15 +3665,16 @@ static int goya_patch_cb(struct hl_device *hdev,
                enum packet_id pkt_id;
                u16 pkt_size;
                u32 new_pkt_size = 0;
-               void *user_pkt, *kernel_pkt;
+               struct goya_packet *user_pkt, *kernel_pkt;
 
-               user_pkt = (void *) (uintptr_t)
+               user_pkt = (struct goya_packet *) (uintptr_t)
                        (parser->user_cb->kernel_address + cb_parsed_length);
-               kernel_pkt = (void *) (uintptr_t)
+               kernel_pkt = (struct goya_packet *) (uintptr_t)
                        (parser->patched_cb->kernel_address +
                                        cb_patched_cur_length);
 
-               pkt_id = (enum packet_id) (((*(u64 *) user_pkt) &
+               pkt_id = (enum packet_id) (
+                               (le64_to_cpu(user_pkt->header) &
                                PACKET_HEADER_PACKET_ID_MASK) >>
                                        PACKET_HEADER_PACKET_ID_SHIFT);
 
@@ -3679,15 +3689,18 @@ static int goya_patch_cb(struct hl_device *hdev,
 
                switch (pkt_id) {
                case PACKET_LIN_DMA:
-                       rc = goya_patch_dma_packet(hdev, parser, user_pkt,
-                                               kernel_pkt, &new_pkt_size);
+                       rc = goya_patch_dma_packet(hdev, parser,
+                                       (struct packet_lin_dma *) user_pkt,
+                                       (struct packet_lin_dma *) kernel_pkt,
+                                       &new_pkt_size);
                        cb_patched_cur_length += new_pkt_size;
                        break;
 
                case PACKET_WREG_32:
                        memcpy(kernel_pkt, user_pkt, pkt_size);
                        cb_patched_cur_length += pkt_size;
-                       rc = goya_validate_wreg32(hdev, parser, kernel_pkt);
+                       rc = goya_validate_wreg32(hdev, parser,
+                                       (struct packet_wreg32 *) kernel_pkt);
                        break;
 
                case PACKET_WREG_BULK:
@@ -4351,6 +4364,8 @@ static int goya_unmask_irq_arr(struct hl_device *hdev, u32 *irq_arr,
        size_t total_pkt_size;
        long result;
        int rc;
+       int irq_num_entries, irq_arr_index;
+       __le32 *goya_irq_arr;
 
        total_pkt_size = sizeof(struct armcp_unmask_irq_arr_packet) +
                        irq_arr_size;
@@ -4368,8 +4383,16 @@ static int goya_unmask_irq_arr(struct hl_device *hdev, u32 *irq_arr,
        if (!pkt)
                return -ENOMEM;
 
-       pkt->length = cpu_to_le32(irq_arr_size / sizeof(irq_arr[0]));
-       memcpy(&pkt->irqs, irq_arr, irq_arr_size);
+       irq_num_entries = irq_arr_size / sizeof(irq_arr[0]);
+       pkt->length = cpu_to_le32(irq_num_entries);
+
+       /* We must perform any necessary endianness conversation on the irq
+        * array being passed to the goya hardware
+        */
+       for (irq_arr_index = 0, goya_irq_arr = (__le32 *) &pkt->irqs;
+                       irq_arr_index < irq_num_entries ; irq_arr_index++)
+               goya_irq_arr[irq_arr_index] =
+                               cpu_to_le32(irq_arr[irq_arr_index]);
 
        pkt->armcp_pkt.ctl = cpu_to_le32(ARMCP_PACKET_UNMASK_RAZWI_IRQ_ARRAY <<
                                                ARMCP_PKT_CTL_OPCODE_SHIFT);
@@ -4449,7 +4472,6 @@ void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry)
        case GOYA_ASYNC_EVENT_ID_AXI_ECC:
        case GOYA_ASYNC_EVENT_ID_L2_RAM_ECC:
        case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_05_SW_RESET:
-       case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_10_VRHOT_ICRIT:
                goya_print_irq_info(hdev, event_type, false);
                hl_device_reset(hdev, true, false);
                break;
@@ -4485,6 +4507,7 @@ void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry)
                goya_unmask_irq(hdev, event_type);
                break;
 
+       case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_10_VRHOT_ICRIT:
        case GOYA_ASYNC_EVENT_ID_TPC0_BMON_SPMU:
        case GOYA_ASYNC_EVENT_ID_TPC1_BMON_SPMU:
        case GOYA_ASYNC_EVENT_ID_TPC2_BMON_SPMU:
@@ -5041,7 +5064,7 @@ static const struct hl_asic_funcs goya_funcs = {
        .resume = goya_resume,
        .cb_mmap = goya_cb_mmap,
        .ring_doorbell = goya_ring_doorbell,
-       .flush_pq_write = goya_flush_pq_write,
+       .pqe_write = goya_pqe_write,
        .asic_dma_alloc_coherent = goya_dma_alloc_coherent,
        .asic_dma_free_coherent = goya_dma_free_coherent,
        .get_int_queue_base = goya_get_int_queue_base,
index f8c611883dc12b844465b9879beeeb84872c6c15..d7f48c9c41cdc7f6549b5a42441f3bfd1fb897e0 100644 (file)
@@ -177,7 +177,7 @@ int goya_late_init(struct hl_device *hdev);
 void goya_late_fini(struct hl_device *hdev);
 
 void goya_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi);
-void goya_flush_pq_write(struct hl_device *hdev, u64 *pq, u64 exp_val);
+void goya_pqe_write(struct hl_device *hdev, __le64 *pqe, struct hl_bd *bd);
 void goya_update_eq_ci(struct hl_device *hdev, u32 val);
 void goya_restore_phase_topology(struct hl_device *hdev);
 int goya_context_switch(struct hl_device *hdev, u32 asid);
index 10da9940ee0dd1ac2cbad4291dee1d297897877a..ce83adafcf2d97561cd37ae97b63187422af3085 100644 (file)
@@ -441,7 +441,11 @@ enum hl_pll_frequency {
  * @resume: handles IP specific H/W or SW changes for resume.
  * @cb_mmap: maps a CB.
  * @ring_doorbell: increment PI on a given QMAN.
- * @flush_pq_write: flush PQ entry write if necessary, WARN if flushing failed.
+ * @pqe_write: Write the PQ entry to the PQ. This is ASIC-specific
+ *             function because the PQs are located in different memory areas
+ *             per ASIC (SRAM, DRAM, Host memory) and therefore, the method of
+ *             writing the PQE must match the destination memory area
+ *             properties.
  * @asic_dma_alloc_coherent: Allocate coherent DMA memory by calling
  *                           dma_alloc_coherent(). This is ASIC function because
  *                           its implementation is not trivial when the driver
@@ -510,7 +514,8 @@ struct hl_asic_funcs {
        int (*cb_mmap)(struct hl_device *hdev, struct vm_area_struct *vma,
                        u64 kaddress, phys_addr_t paddress, u32 size);
        void (*ring_doorbell)(struct hl_device *hdev, u32 hw_queue_id, u32 pi);
-       void (*flush_pq_write)(struct hl_device *hdev, u64 *pq, u64 exp_val);
+       void (*pqe_write)(struct hl_device *hdev, __le64 *pqe,
+                       struct hl_bd *bd);
        void* (*asic_dma_alloc_coherent)(struct hl_device *hdev, size_t size,
                                        dma_addr_t *dma_handle, gfp_t flag);
        void (*asic_dma_free_coherent)(struct hl_device *hdev, size_t size,
@@ -1062,9 +1067,17 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
 /*
  * address in this macro points always to a memory location in the
  * host's (server's) memory. That location is updated asynchronously
- * either by the direct access of the device or by another core
+ * either by the direct access of the device or by another core.
+ *
+ * To work both in LE and BE architectures, we need to distinguish between the
+ * two states (device or another core updates the memory location). Therefore,
+ * if mem_written_by_device is true, the host memory being polled will be
+ * updated directly by the device. If false, the host memory being polled will
+ * be updated by host CPU. Required so host knows whether or not the memory
+ * might need to be byte-swapped before returning value to caller.
  */
-#define hl_poll_timeout_memory(hdev, addr, val, cond, sleep_us, timeout_us) \
+#define hl_poll_timeout_memory(hdev, addr, val, cond, sleep_us, timeout_us, \
+                               mem_written_by_device) \
 ({ \
        ktime_t __timeout; \
        /* timeout should be longer when working with simulator */ \
@@ -1077,10 +1090,14 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
                /* Verify we read updates done by other cores or by device */ \
                mb(); \
                (val) = *((u32 *) (uintptr_t) (addr)); \
+               if (mem_written_by_device) \
+                       (val) = le32_to_cpu(val); \
                if (cond) \
                        break; \
                if (timeout_us && ktime_compare(ktime_get(), __timeout) > 0) { \
                        (val) = *((u32 *) (uintptr_t) (addr)); \
+                       if (mem_written_by_device) \
+                               (val) = le32_to_cpu(val); \
                        break; \
                } \
                if (sleep_us) \
index e3b5517897eabf1de40c28d54b28dd540282d5f3..5f5673b749852a66e8180f3488c287396980a1ce 100644 (file)
@@ -290,23 +290,19 @@ static void int_hw_queue_schedule_job(struct hl_cs_job *job)
        struct hl_device *hdev = job->cs->ctx->hdev;
        struct hl_hw_queue *q = &hdev->kernel_queues[job->hw_queue_id];
        struct hl_bd bd;
-       u64 *pi, *pbd = (u64 *) &bd;
+       __le64 *pi;
 
        bd.ctl = 0;
-       bd.len = __cpu_to_le32(job->job_cb_size);
-       bd.ptr = __cpu_to_le64((u64) (uintptr_t) job->user_cb);
+       bd.len = cpu_to_le32(job->job_cb_size);
+       bd.ptr = cpu_to_le64((u64) (uintptr_t) job->user_cb);
 
-       pi = (u64 *) (uintptr_t) (q->kernel_address +
+       pi = (__le64 *) (uintptr_t) (q->kernel_address +
                ((q->pi & (q->int_queue_len - 1)) * sizeof(bd)));
 
-       pi[0] = pbd[0];
-       pi[1] = pbd[1];
-
        q->pi++;
        q->pi &= ((q->int_queue_len << 1) - 1);
 
-       /* Flush PQ entry write. Relevant only for specific ASICs */
-       hdev->asic_funcs->flush_pq_write(hdev, pi, pbd[0]);
+       hdev->asic_funcs->pqe_write(hdev, pi, &bd);
 
        hdev->asic_funcs->ring_doorbell(hdev, q->hw_queue_id, q->pi);
 }
index a14407b975e4e9d5608cb551826bda8ec4fa6136..ef54bad2050991a2d863fb2c03afe2e52a42210f 100644 (file)
@@ -52,6 +52,19 @@ enum goya_dma_direction {
 #define GOYA_PKT_CTL_MB_SHIFT          31
 #define GOYA_PKT_CTL_MB_MASK           0x80000000
 
+/* All packets have, at least, an 8-byte header, which contains
+ * the packet type. The kernel driver uses the packet header for packet
+ * validation and to perform any necessary required preparation before
+ * sending them off to the hardware.
+ */
+struct goya_packet {
+       __le64 header;
+       /* The rest of the packet data follows. Use the corresponding
+        * packet_XXX struct to deference the data, based on packet type
+        */
+       u8 contents[0];
+};
+
 struct packet_nop {
        __le32 reserved;
        __le32 ctl;
index ea9f72ff456cf9fe23aae5e55d38fe03b88afc31..199791b57caf2746a719349dce45e23d5d9639be 100644 (file)
@@ -80,8 +80,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
        struct hl_cs_job *job;
        bool shadow_index_valid;
        u16 shadow_index;
-       u32 *cq_entry;
-       u32 *cq_base;
+       struct hl_cq_entry *cq_entry, *cq_base;
 
        if (hdev->disabled) {
                dev_dbg(hdev->dev,
@@ -90,29 +89,29 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
                return IRQ_HANDLED;
        }
 
-       cq_base = (u32 *) (uintptr_t) cq->kernel_address;
+       cq_base = (struct hl_cq_entry *) (uintptr_t) cq->kernel_address;
 
        while (1) {
-               bool entry_ready = ((cq_base[cq->ci] & CQ_ENTRY_READY_MASK)
+               bool entry_ready = ((le32_to_cpu(cq_base[cq->ci].data) &
+                                       CQ_ENTRY_READY_MASK)
                                                >> CQ_ENTRY_READY_SHIFT);
 
                if (!entry_ready)
                        break;
 
-               cq_entry = (u32 *) &cq_base[cq->ci];
+               cq_entry = (struct hl_cq_entry *) &cq_base[cq->ci];
 
-               /*
-                * Make sure we read CQ entry contents after we've
+               /* Make sure we read CQ entry contents after we've
                 * checked the ownership bit.
                 */
                dma_rmb();
 
-               shadow_index_valid =
-                       ((*cq_entry & CQ_ENTRY_SHADOW_INDEX_VALID_MASK)
+               shadow_index_valid = ((le32_to_cpu(cq_entry->data) &
+                                       CQ_ENTRY_SHADOW_INDEX_VALID_MASK)
                                        >> CQ_ENTRY_SHADOW_INDEX_VALID_SHIFT);
 
-               shadow_index = (u16)
-                       ((*cq_entry & CQ_ENTRY_SHADOW_INDEX_MASK)
+               shadow_index = (u16) ((le32_to_cpu(cq_entry->data) &
+                                       CQ_ENTRY_SHADOW_INDEX_MASK)
                                        >> CQ_ENTRY_SHADOW_INDEX_SHIFT);
 
                queue = &hdev->kernel_queues[cq->hw_queue_id];
@@ -122,8 +121,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
                        queue_work(hdev->cq_wq, &job->finish_work);
                }
 
-               /*
-                * Update ci of the context's queue. There is no
+               /* Update ci of the context's queue. There is no
                 * need to protect it with spinlock because this update is
                 * done only inside IRQ and there is a different IRQ per
                 * queue
@@ -131,7 +129,8 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
                queue->ci = hl_queue_inc_ptr(queue->ci);
 
                /* Clear CQ entry ready bit */
-               cq_base[cq->ci] &= ~CQ_ENTRY_READY_MASK;
+               cq_entry->data = cpu_to_le32(le32_to_cpu(cq_entry->data) &
+                                               ~CQ_ENTRY_READY_MASK);
 
                cq->ci = hl_cq_inc_ptr(cq->ci);
 
index 42d237cae1dc571419ee1a107960996b2b6f3d85..365fb0cb8dfffa87291dad6eeeb8625ce0de3212 100644 (file)
@@ -1629,6 +1629,8 @@ void hl_vm_ctx_fini(struct hl_ctx *ctx)
                        dev_dbg(hdev->dev,
                                "page list 0x%p of asid %d is still alive\n",
                                phys_pg_list, ctx->asid);
+                       atomic64_sub(phys_pg_list->total_size,
+                                       &hdev->dram_used_mem);
                        free_phys_pg_pack(hdev, phys_pg_list);
                        idr_remove(&vm->phys_pg_pack_handles, i);
                }
index 1606658b9b7e35ce307c25d3dcf770ef3620f6d8..24245ccdba7207f9bb021708de67fd422d04cacb 100644 (file)
@@ -22,7 +22,7 @@ struct lkdtm_list {
  * recurse past the end of THREAD_SIZE by default.
  */
 #if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0)
-#define REC_STACK_SIZE (CONFIG_FRAME_WARN / 2)
+#define REC_STACK_SIZE (_AC(CONFIG_FRAME_WARN, UL) / 2)
 #else
 #define REC_STACK_SIZE (THREAD_SIZE / 8)
 #endif
@@ -91,7 +91,7 @@ void lkdtm_LOOP(void)
 
 void lkdtm_EXHAUST_STACK(void)
 {
-       pr_info("Calling function with %d frame size to depth %d ...\n",
+       pr_info("Calling function with %lu frame size to depth %d ...\n",
                REC_STACK_SIZE, recur_count);
        recursive_loop(recur_count);
        pr_info("FAIL: survived without exhausting stack?!\n");
index d74b182e19f3889d6bc03061c7aa4bc159896773..77f7dff7098d4633f4e37e691027fd3c36c1d7a6 100644 (file)
 
 #define MEI_DEV_ID_ICP_LP     0x34E0  /* Ice Lake Point LP */
 
+#define MEI_DEV_ID_TGP_LP     0xA0E0  /* Tiger Lake Point LP */
+
+#define MEI_DEV_ID_MCC        0x4B70  /* Mule Creek Canyon (EHL) */
+#define MEI_DEV_ID_MCC_4      0x4B75  /* Mule Creek Canyon 4 (EHL) */
+
 /*
  * MEI HW Section
  */
index 7a2b3545a7f9c2fe9fa75ec8652c442a9fcb7919..541538eff8b110490420099be16b6bd0b5c18601 100644 (file)
@@ -98,6 +98,11 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH12_CFG)},
+
+       {MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH12_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
+
        /* required last entry */
        {0, }
 };
index 8840299420e0b287f3cd81733a1c13a0c7957fb0..5e6be1527571aaf0d7e7e4646768b123f9e85f57 100644 (file)
@@ -691,7 +691,6 @@ static int vmballoon_alloc_page_list(struct vmballoon *b,
                }
 
                if (page) {
-                       vmballoon_mark_page_offline(page, ctl->page_size);
                        /* Success. Add the page to the list and continue. */
                        list_add(&page->lru, &ctl->pages);
                        continue;
@@ -930,7 +929,6 @@ static void vmballoon_release_page_list(struct list_head *page_list,
 
        list_for_each_entry_safe(page, tmp, page_list, lru) {
                list_del(&page->lru);
-               vmballoon_mark_page_online(page, page_size);
                __free_pages(page, vmballoon_page_order(page_size));
        }
 
@@ -1005,6 +1003,7 @@ static void vmballoon_enqueue_page_list(struct vmballoon *b,
                                        enum vmballoon_page_size_type page_size)
 {
        unsigned long flags;
+       struct page *page;
 
        if (page_size == VMW_BALLOON_4K_PAGE) {
                balloon_page_list_enqueue(&b->b_dev_info, pages);
@@ -1014,6 +1013,11 @@ static void vmballoon_enqueue_page_list(struct vmballoon *b,
                 * for the balloon compaction mechanism.
                 */
                spin_lock_irqsave(&b->b_dev_info.pages_lock, flags);
+
+               list_for_each_entry(page, pages, lru) {
+                       vmballoon_mark_page_offline(page, VMW_BALLOON_2M_PAGE);
+               }
+
                list_splice_init(pages, &b->huge_pages);
                __count_vm_events(BALLOON_INFLATE, *n_pages *
                                  vmballoon_page_in_frames(VMW_BALLOON_2M_PAGE));
@@ -1056,6 +1060,8 @@ static void vmballoon_dequeue_page_list(struct vmballoon *b,
        /* 2MB pages */
        spin_lock_irqsave(&b->b_dev_info.pages_lock, flags);
        list_for_each_entry_safe(page, tmp, &b->huge_pages, lru) {
+               vmballoon_mark_page_online(page, VMW_BALLOON_2M_PAGE);
+
                list_move(&page->lru, pages);
                if (++i == n_req_pages)
                        break;
index bad89b6e08024f8b296701cd0a2aebbb79dbad0b..345addd9306defffd6e43d667672df6f22966bc1 100644 (file)
@@ -310,7 +310,8 @@ int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle)
 
        entry = container_of(resource, struct dbell_entry, resource);
        if (entry->run_delayed) {
-               schedule_work(&entry->work);
+               if (!schedule_work(&entry->work))
+                       vmci_resource_put(resource);
        } else {
                entry->notify_cb(entry->client_data);
                vmci_resource_put(resource);
@@ -361,7 +362,8 @@ static void dbell_fire_entries(u32 notify_idx)
                    atomic_read(&dbell->active) == 1) {
                        if (dbell->run_delayed) {
                                vmci_resource_get(&dbell->resource);
-                               schedule_work(&dbell->work);
+                               if (!schedule_work(&dbell->work))
+                                       vmci_resource_put(&dbell->resource);
                        } else {
                                dbell->notify_cb(dbell->client_data);
                        }
index 74e4364bc9fb5df992cffe028db41e3de1072415..09113b9ad67907822ed7e53bcae652e40ec44f4c 100644 (file)
@@ -564,7 +564,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
        if (index == EXT_CSD_SANITIZE_START)
                cmd.sanitize_busy = true;
 
-       err = mmc_wait_for_cmd(host, &cmd, 0);
+       err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
        if (err)
                goto out;
 
index e327f80ebe7048ea74ff70a67cfa0e350b15a0e0..7102e2ebc614d0eb18c2122e037f5e5109c9f987 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kthread.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
+#include <linux/backing-dev.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -427,6 +428,10 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card)
                goto free_tag_set;
        }
 
+       if (mmc_host_is_spi(host) && host->use_spi_crc)
+               mq->queue->backing_dev_info->capabilities |=
+                       BDI_CAP_STABLE_WRITES;
+
        mq->queue->queuedata = mq;
        blk_queue_rq_timeout(mq->queue, 60 * HZ);
 
index d681e8aaca837f19298a7d144ea5ae02f5547ada..fe914ff5f5d660e3df1d8e4ce6c22a95d83e72c1 100644 (file)
@@ -1292,6 +1292,12 @@ int mmc_attach_sd(struct mmc_host *host)
                        goto err;
        }
 
+       /*
+        * Some SD cards claims an out of spec VDD voltage range. Let's treat
+        * these bits as being in-valid and especially also bit7.
+        */
+       ocr &= ~0x7FFF;
+
        rocr = mmc_select_voltage(host, ocr);
 
        /*
index 7e0d3a49c06d8ec443f0b8493c617411efbf7af8..bb31e13648d6577d47c5b0bd268a7cf0ccc80d5a 100644 (file)
@@ -597,7 +597,7 @@ static void bcm2835_finish_request(struct bcm2835_host *host)
        struct dma_chan *terminate_chan = NULL;
        struct mmc_request *mrq;
 
-       cancel_delayed_work_sync(&host->timeout_work);
+       cancel_delayed_work(&host->timeout_work);
 
        mrq = host->mrq;
 
index ed5cefb8376838b401aba0ac394c6a69e37dd818..89deb451e0ac6225c9481dc21ca21373f46c2d7c 100644 (file)
@@ -374,6 +374,7 @@ static int finish_dma_single(struct cvm_mmc_host *host, struct mmc_data *data)
 {
        data->bytes_xfered = data->blocks * data->blksz;
        data->error = 0;
+       dma_unmap_sg(host->dev, data->sg, data->sg_len, get_dma_dir(data));
        return 1;
 }
 
@@ -1046,7 +1047,8 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host)
                mmc->max_segs = 1;
 
        /* DMA size field can address up to 8 MB */
-       mmc->max_seg_size = 8 * 1024 * 1024;
+       mmc->max_seg_size = min_t(unsigned int, 8 * 1024 * 1024,
+                                 dma_get_max_seg_size(host->dev));
        mmc->max_req_size = mmc->max_seg_size;
        /* External DMA is in 512 byte blocks */
        mmc->max_blk_size = 512;
index faaaf52a46d278409c2f183cea9969f75f90d069..eea52e2c5a0ce9c48578390b5f74e22770c18f9b 100644 (file)
@@ -2012,8 +2012,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                 * delayed. Allowing the transfer to take place
                                 * avoids races and keeps things simple.
                                 */
-                               if ((err != -ETIMEDOUT) &&
-                                   (cmd->opcode == MMC_SEND_TUNING_BLOCK)) {
+                               if (err != -ETIMEDOUT) {
                                        state = STATE_SENDING_DATA;
                                        continue;
                                }
index 2d736e4167757dca6ff052fc551fa4d122dbcce3..ba9a63db73da934b94a79d3f882007bca792b39d 100644 (file)
@@ -73,7 +73,7 @@
        #define MESON_MX_SDIO_IRQC_IF_CONFIG_MASK               GENMASK(7, 6)
        #define MESON_MX_SDIO_IRQC_FORCE_DATA_CLK               BIT(8)
        #define MESON_MX_SDIO_IRQC_FORCE_DATA_CMD               BIT(9)
-       #define MESON_MX_SDIO_IRQC_FORCE_DATA_DAT_MASK          GENMASK(10, 13)
+       #define MESON_MX_SDIO_IRQC_FORCE_DATA_DAT_MASK          GENMASK(13, 10)
        #define MESON_MX_SDIO_IRQC_SOFT_RESET                   BIT(15)
        #define MESON_MX_SDIO_IRQC_FORCE_HALT                   BIT(30)
        #define MESON_MX_SDIO_IRQC_HALT_HOLE                    BIT(31)
index 64d3b5fb7fe563e0c958dc21e2a8090ce3e0d2d2..4a2872f49a6079445c339fa3c52f6111f1f63b16 100644 (file)
@@ -774,8 +774,6 @@ int renesas_sdhi_probe(struct platform_device *pdev,
        /* All SDHI have SDIO status bits which must be 1 */
        mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS;
 
-       pm_runtime_enable(&pdev->dev);
-
        ret = renesas_sdhi_clk_enable(host);
        if (ret)
                goto efree;
@@ -856,8 +854,6 @@ edisclk:
 efree:
        tmio_mmc_host_free(host);
 
-       pm_runtime_disable(&pdev->dev);
-
        return ret;
 }
 EXPORT_SYMBOL_GPL(renesas_sdhi_probe);
@@ -869,8 +865,6 @@ int renesas_sdhi_remove(struct platform_device *pdev)
        tmio_mmc_host_remove(host);
        renesas_sdhi_clk_disable(host);
 
-       pm_runtime_disable(&pdev->dev);
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(renesas_sdhi_remove);
index b3a130a9ee23312348ef8369c34182089e82d0a8..1604f512c7bd183b85d8b3ed0c91634ed715a4cf 100644 (file)
@@ -883,7 +883,7 @@ static int sdhci_acpi_runtime_resume(struct device *dev)
 
        sdhci_acpi_byt_setting(&c->pdev->dev);
 
-       return sdhci_runtime_resume_host(c->host);
+       return sdhci_runtime_resume_host(c->host, 0);
 }
 
 #endif
index 163d1cf4367ecb87d0a113cbcee30bfe0315d7d4..44139fceac2467d08fda740ce4a69d80bd7304c5 100644 (file)
@@ -369,6 +369,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
        host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
        host->mmc_host_ops.hs400_enhanced_strobe =
                                sdhci_cdns_hs400_enhanced_strobe;
+       sdhci_enable_v4_mode(host);
 
        sdhci_get_of_property(pdev);
 
index c391510e9ef407d54c25f4326a574a2b4b059ce6..776a942162488e87e14f3d48fd2b285ab9ecd1cf 100644 (file)
@@ -1705,7 +1705,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
                esdhc_pltfm_set_clock(host, imx_data->actual_clock);
        }
 
-       err = sdhci_runtime_resume_host(host);
+       err = sdhci_runtime_resume_host(host, 0);
        if (err)
                goto disable_ipg_clk;
 
index e377b9bc55a46d293353f3473050cae9b2494027..e7d1920729fbc98aa3fe527e3e2fce5a28379af5 100644 (file)
@@ -289,7 +289,7 @@ static int sdhci_at91_runtime_resume(struct device *dev)
        }
 
 out:
-       return sdhci_runtime_resume_host(host);
+       return sdhci_runtime_resume_host(host, 0);
 }
 #endif /* CONFIG_PM */
 
@@ -357,6 +357,9 @@ static int sdhci_at91_probe(struct platform_device *pdev)
        pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
        pm_runtime_use_autosuspend(&pdev->dev);
 
+       /* HS200 is broken at this moment */
+       host->quirks2 = SDHCI_QUIRK2_BROKEN_HS200;
+
        ret = sdhci_add_host(host);
        if (ret)
                goto pm_runtime_disable;
index 4041878eb0f3ab92c2873d0f8787a3f8d528c06c..7d06e2860c36515f996a732fb624ce17a359417e 100644 (file)
@@ -167,7 +167,7 @@ static int sdhci_pci_runtime_suspend_host(struct sdhci_pci_chip *chip)
 
 err_pci_runtime_suspend:
        while (--i >= 0)
-               sdhci_runtime_resume_host(chip->slots[i]->host);
+               sdhci_runtime_resume_host(chip->slots[i]->host, 0);
        return ret;
 }
 
@@ -181,7 +181,7 @@ static int sdhci_pci_runtime_resume_host(struct sdhci_pci_chip *chip)
                if (!slot)
                        continue;
 
-               ret = sdhci_runtime_resume_host(slot->host);
+               ret = sdhci_runtime_resume_host(slot->host, 0);
                if (ret)
                        return ret;
        }
index 9dc4548271b4b25d95c82f035b98f4f62f1e3c29..19944b0049db0d4b8778c00a4b2fa93535f029a9 100644 (file)
@@ -432,7 +432,6 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
                                        mmc_hostname(host->mmc));
                                host->flags &= ~SDHCI_SIGNALING_330;
                                host->flags |= SDHCI_SIGNALING_180;
-                               host->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
                                host->mmc->caps2 |= MMC_CAP2_NO_SD;
                                host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
                                pci_write_config_dword(chip->pdev,
@@ -682,6 +681,7 @@ static const struct sdhci_ops sdhci_pci_o2_ops = {
 const struct sdhci_pci_fixes sdhci_o2 = {
        .probe = sdhci_pci_o2_probe,
        .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+       .quirks2 = SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD,
        .probe_slot = sdhci_pci_o2_probe_slot,
 #ifdef CONFIG_PM_SLEEP
        .resume = sdhci_pci_o2_resume,
index 3ddecf47929585d6ca236fe17047316b9f8a1af5..e55037ceda734ff0e581fc8e2eecb664d882363f 100644 (file)
@@ -554,7 +554,7 @@ static int sdhci_pxav3_runtime_resume(struct device *dev)
        if (!IS_ERR(pxa->clk_core))
                clk_prepare_enable(pxa->clk_core);
 
-       return sdhci_runtime_resume_host(host);
+       return sdhci_runtime_resume_host(host, 0);
 }
 #endif
 
index 8e4a8ba33f0503bc52903755d3bd422bec233224..f5753aef71511d8bb495610858469ab3f1df028f 100644 (file)
@@ -745,7 +745,7 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
        clk_prepare_enable(busclk);
        if (ourhost->cur_clk >= 0)
                clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
-       ret = sdhci_runtime_resume_host(host);
+       ret = sdhci_runtime_resume_host(host, 0);
        return ret;
 }
 #endif
index 6ee340a3fb3a252632b1a714d82eab678173e457..d07b9793380f06b2dac0c1225ce58e71a59f3807 100644 (file)
@@ -217,10 +217,11 @@ static inline void _sdhci_sprd_set_clock(struct sdhci_host *host,
        struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
        u32 div, val, mask;
 
-       div = sdhci_sprd_calc_div(sprd_host->base_rate, clk);
+       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
-       clk |= ((div & 0x300) >> 2) | ((div & 0xFF) << 8);
-       sdhci_enable_clk(host, clk);
+       div = sdhci_sprd_calc_div(sprd_host->base_rate, clk);
+       div = ((div & 0x300) >> 2) | ((div & 0xFF) << 8);
+       sdhci_enable_clk(host, div);
 
        /* enable auto gate sdhc_enable_auto_gate */
        val = sdhci_readl(host, SDHCI_SPRD_REG_32_BUSY_POSI);
@@ -373,6 +374,11 @@ static unsigned int sdhci_sprd_get_max_timeout_count(struct sdhci_host *host)
        return 1 << 31;
 }
 
+static unsigned int sdhci_sprd_get_ro(struct sdhci_host *host)
+{
+       return 0;
+}
+
 static struct sdhci_ops sdhci_sprd_ops = {
        .read_l = sdhci_sprd_readl,
        .write_l = sdhci_sprd_writel,
@@ -385,6 +391,7 @@ static struct sdhci_ops sdhci_sprd_ops = {
        .set_uhs_signaling = sdhci_sprd_set_uhs_signaling,
        .hw_reset = sdhci_sprd_hw_reset,
        .get_max_timeout_count = sdhci_sprd_get_max_timeout_count,
+       .get_ro = sdhci_sprd_get_ro,
 };
 
 static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -501,9 +508,12 @@ static void sdhci_sprd_phy_param_parse(struct sdhci_sprd_host *sprd_host,
 }
 
 static const struct sdhci_pltfm_data sdhci_sprd_pdata = {
-       .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
+       .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+                 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+                 SDHCI_QUIRK_MISSING_CAPS,
        .quirks2 = SDHCI_QUIRK2_BROKEN_HS200 |
-                  SDHCI_QUIRK2_USE_32BIT_BLK_CNT,
+                  SDHCI_QUIRK2_USE_32BIT_BLK_CNT |
+                  SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
        .ops = &sdhci_sprd_ops,
 };
 
@@ -605,6 +615,16 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
 
        sdhci_enable_v4_mode(host);
 
+       /*
+        * Supply the existing CAPS, but clear the UHS-I modes. This
+        * will allow these modes to be specified only by device
+        * tree properties through mmc_of_parse().
+        */
+       host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+       host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+       host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
+                        SDHCI_SUPPORT_DDR50);
+
        ret = sdhci_setup_host(host);
        if (ret)
                goto pm_runtime_disable;
@@ -624,6 +644,7 @@ err_cleanup_host:
        sdhci_cleanup_host(host);
 
 pm_runtime_disable:
+       pm_runtime_put_noidle(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        pm_runtime_set_suspended(&pdev->dev);
 
@@ -695,7 +716,7 @@ static int sdhci_sprd_runtime_resume(struct device *dev)
        if (ret)
                goto clk_disable;
 
-       sdhci_runtime_resume_host(host);
+       sdhci_runtime_resume_host(host, 1);
        return 0;
 
 clk_disable:
index f4d4761cf20ab4f700e1f4054dc8dfbf9318962c..02d8f524bb9e6fc9b181d3d9616040ce3bb94dc9 100644 (file)
@@ -258,6 +258,16 @@ static void tegra210_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
        }
 }
 
+static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
+{
+       /*
+        * Write-enable shall be assumed if GPIO is missing in a board's
+        * device-tree because SDHCI's WRITE_PROTECT bit doesn't work on
+        * Tegra.
+        */
+       return mmc_gpio_get_ro(host->mmc);
+}
+
 static bool tegra_sdhci_is_pad_and_regulator_valid(struct sdhci_host *host)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -1224,6 +1234,7 @@ static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = {
 };
 
 static const struct sdhci_ops tegra_sdhci_ops = {
+       .get_ro     = tegra_sdhci_get_ro,
        .read_w     = tegra_sdhci_readw,
        .write_l    = tegra_sdhci_writel,
        .set_clock  = tegra_sdhci_set_clock,
@@ -1279,6 +1290,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra30 = {
 };
 
 static const struct sdhci_ops tegra114_sdhci_ops = {
+       .get_ro     = tegra_sdhci_get_ro,
        .read_w     = tegra_sdhci_readw,
        .write_w    = tegra_sdhci_writew,
        .write_l    = tegra_sdhci_writel,
@@ -1332,6 +1344,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra124 = {
 };
 
 static const struct sdhci_ops tegra210_sdhci_ops = {
+       .get_ro     = tegra_sdhci_get_ro,
        .read_w     = tegra_sdhci_readw,
        .write_w    = tegra210_sdhci_writew,
        .write_l    = tegra_sdhci_writel,
@@ -1366,6 +1379,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
 };
 
 static const struct sdhci_ops tegra186_sdhci_ops = {
+       .get_ro     = tegra_sdhci_get_ro,
        .read_w     = tegra_sdhci_readw,
        .write_l    = tegra_sdhci_writel,
        .set_clock  = tegra_sdhci_set_clock,
index 8a18f14cf842df20afd0609e973a7e5d5546349d..1dea1ba66f7b4e8a05e48a8a0f4fbac8875c2a14 100644 (file)
@@ -638,7 +638,7 @@ static int xenon_runtime_resume(struct device *dev)
                priv->restore_needed = false;
        }
 
-       ret = sdhci_runtime_resume_host(host);
+       ret = sdhci_runtime_resume_host(host, 0);
        if (ret)
                goto out;
        return 0;
index 59acf8e3331ee189fce0fbf2468478b48c41154c..a5dc5aae973e6e14f3915dae1c44d247a7ac7bfb 100644 (file)
@@ -3320,7 +3320,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
 }
 EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
 
-int sdhci_runtime_resume_host(struct sdhci_host *host)
+int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
 {
        struct mmc_host *mmc = host->mmc;
        unsigned long flags;
@@ -3331,7 +3331,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
                        host->ops->enable_dma(host);
        }
 
-       sdhci_init(host, 0);
+       sdhci_init(host, soft_reset);
 
        if (mmc->ios.power_mode != MMC_POWER_UNDEFINED &&
            mmc->ios.power_mode != MMC_POWER_OFF) {
index 89fd96596a1f75e18f600761a41302d455124f64..902f855efe8f8b0aad28731b1040ad56c086f688 100644 (file)
@@ -781,7 +781,7 @@ void sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
 int sdhci_suspend_host(struct sdhci_host *host);
 int sdhci_resume_host(struct sdhci_host *host);
 int sdhci_runtime_suspend_host(struct sdhci_host *host);
-int sdhci_runtime_resume_host(struct sdhci_host *host);
+int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset);
 #endif
 
 void sdhci_cqe_enable(struct mmc_host *mmc);
index 8539e10784b4096186024319c18f0df4e555e435..93e83ad25976e756bdb04408b51c506925b02534 100644 (file)
@@ -172,8 +172,6 @@ static int tmio_mmc_probe(struct platform_device *pdev)
        host->mmc->f_max = pdata->hclk;
        host->mmc->f_min = pdata->hclk / 512;
 
-       pm_runtime_enable(&pdev->dev);
-
        ret = tmio_mmc_host_probe(host);
        if (ret)
                goto host_free;
@@ -193,7 +191,6 @@ host_remove:
        tmio_mmc_host_remove(host);
 host_free:
        tmio_mmc_host_free(host);
-       pm_runtime_disable(&pdev->dev);
 cell_disable:
        if (cell->disable)
                cell->disable(pdev);
@@ -210,8 +207,6 @@ static int tmio_mmc_remove(struct platform_device *pdev)
        if (cell->disable)
                cell->disable(pdev);
 
-       pm_runtime_disable(&pdev->dev);
-
        return 0;
 }
 
index c5ba13fae39920e656de9737412804e2f5155a77..2f0b092d6dcc64d199b75ec7563600f1954502dd 100644 (file)
@@ -163,6 +163,7 @@ struct tmio_mmc_host {
        unsigned long           last_req_ts;
        struct mutex            ios_lock;       /* protect set_ios() context */
        bool                    native_hotplug;
+       bool                    runtime_synced;
        bool                    sdio_irq_enabled;
 
        /* Mandatory callback */
index 2cb3f951c3e2b793761726feb2bfa7a3ac45a980..9b6e1001e77c3acdc5c959b43bb397853f2d9eb2 100644 (file)
@@ -1153,15 +1153,6 @@ void tmio_mmc_host_free(struct tmio_mmc_host *host)
 }
 EXPORT_SYMBOL_GPL(tmio_mmc_host_free);
 
-/**
- * tmio_mmc_host_probe() - Common probe for all implementations
- * @_host: Host to probe
- *
- * Perform tasks common to all implementations probe functions.
- *
- * The caller should have called pm_runtime_enable() prior to calling
- * the common probe function.
- */
 int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
 {
        struct platform_device *pdev = _host->pdev;
@@ -1257,19 +1248,22 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
        /* See if we also get DMA */
        tmio_mmc_request_dma(_host, pdata);
 
-       pm_runtime_set_active(&pdev->dev);
        pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
        pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
 
        ret = mmc_add_host(mmc);
        if (ret)
                goto remove_host;
 
        dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
+       pm_runtime_put(&pdev->dev);
 
        return 0;
 
 remove_host:
+       pm_runtime_put_noidle(&pdev->dev);
        tmio_mmc_host_remove(_host);
        return ret;
 }
@@ -1280,12 +1274,11 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
        struct platform_device *pdev = host->pdev;
        struct mmc_host *mmc = host->mmc;
 
+       pm_runtime_get_sync(&pdev->dev);
+
        if (host->pdata->flags & TMIO_MMC_SDIO_IRQ)
                sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
 
-       if (!host->native_hotplug)
-               pm_runtime_get_sync(&pdev->dev);
-
        dev_pm_qos_hide_latency_limit(&pdev->dev);
 
        mmc_remove_host(mmc);
@@ -1294,7 +1287,10 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
        tmio_mmc_release_dma(host);
 
        pm_runtime_dont_use_autosuspend(&pdev->dev);
+       if (host->native_hotplug)
+               pm_runtime_put_noidle(&pdev->dev);
        pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
 }
 EXPORT_SYMBOL_GPL(tmio_mmc_host_remove);
 
@@ -1337,6 +1333,11 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
 {
        struct tmio_mmc_host *host = dev_get_drvdata(dev);
 
+       if (!host->runtime_synced) {
+               host->runtime_synced = true;
+               return 0;
+       }
+
        tmio_mmc_clk_enable(host);
        tmio_mmc_hw_reset(host->mmc);
 
index 49aad9a79c18d24aba0d45340964d24b5656aeb9..91a2be41edf6196bd9fc7f73262ab206efa46d1f 100644 (file)
@@ -631,7 +631,6 @@ static int uniphier_sd_probe(struct platform_device *pdev)
        host->clk_disable = uniphier_sd_clk_disable;
        host->set_clock = uniphier_sd_set_clock;
 
-       pm_runtime_enable(&pdev->dev);
        ret = uniphier_sd_clk_enable(host);
        if (ret)
                goto free_host;
@@ -653,7 +652,6 @@ static int uniphier_sd_probe(struct platform_device *pdev)
 
 free_host:
        tmio_mmc_host_free(host);
-       pm_runtime_disable(&pdev->dev);
 
        return ret;
 }
@@ -664,7 +662,6 @@ static int uniphier_sd_remove(struct platform_device *pdev)
 
        tmio_mmc_host_remove(host);
        uniphier_sd_clk_disable(host);
-       pm_runtime_disable(&pdev->dev);
 
        return 0;
 }
index cff6bbd226f50364c62f1bd42977c5536b181d96..a4d8968d133ddbc9b7aff8e08a37e6e262eb561f 100644 (file)
@@ -1,5 +1,6 @@
 menuconfig MTD_HYPERBUS
        tristate "HyperBus support"
+       depends on HAS_IOMEM
        select MTD_CFI
        select MTD_MAP_BANK_WIDTH_2
        select MTD_CFI_AMDSTD
@@ -14,8 +15,9 @@ if MTD_HYPERBUS
 
 config HBMC_AM654
        tristate "HyperBus controller driver for AM65x SoC"
+       depends on ARM64 || COMPILE_TEST
        select MULTIPLEXER
-       select MUX_MMIO
+       imply MUX_MMIO
        help
         This is the driver for HyperBus controller on TI's AM65x and
         other SoCs
index 895510d40ce4794b149baa9374576cd4a8385ca3..47602af4ee34940a3f5fd381aca7dcf7fd7c1a48 100644 (file)
@@ -81,6 +81,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
        default:
                printk(KERN_WARNING "SA1100 flash: unknown base address "
                       "0x%08lx, assuming CS0\n", phys);
+               /* Fall through */
 
        case SA1100_CS0_PHYS:
                subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
index a1f8fe1abb102f8d1756a49e11346ea722b77213..e082d632fb742e1719d68918a4be47a10c4ef1c1 100644 (file)
@@ -3259,6 +3259,7 @@ static void onenand_check_features(struct mtd_info *mtd)
        switch (density) {
        case ONENAND_DEVICE_DENSITY_8Gb:
                this->options |= ONENAND_HAS_NOP_1;
+               /* fall through */
        case ONENAND_DEVICE_DENSITY_4Gb:
                if (ONENAND_IS_DDP(this))
                        this->options |= ONENAND_HAS_2PLANE;
index 1622d3145587ee26e8468b534d3c8ceeec0f21c3..8ca9fad6e6ad158753202b9d26a39e876983bb7e 100644 (file)
@@ -390,6 +390,14 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
            (chip->id.data[4] & MICRON_ID_INTERNAL_ECC_MASK) != 0x2)
                return MICRON_ON_DIE_UNSUPPORTED;
 
+       /*
+        * It seems that there are devices which do not support ECC officially.
+        * At least the MT29F2G08ABAGA / MT29F2G08ABBGA devices supports
+        * enabling the ECC feature but don't reflect that to the READ_ID table.
+        * So we have to guarantee that we disable the ECC feature directly
+        * after we did the READ_ID table command. Later we can evaluate the
+        * ECC_ENABLE support.
+        */
        ret = micron_nand_on_die_ecc_setup(chip, true);
        if (ret)
                return MICRON_ON_DIE_UNSUPPORTED;
@@ -398,13 +406,13 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
        if (ret)
                return MICRON_ON_DIE_UNSUPPORTED;
 
-       if (!(id[4] & MICRON_ID_ECC_ENABLED))
-               return MICRON_ON_DIE_UNSUPPORTED;
-
        ret = micron_nand_on_die_ecc_setup(chip, false);
        if (ret)
                return MICRON_ON_DIE_UNSUPPORTED;
 
+       if (!(id[4] & MICRON_ID_ECC_ENABLED))
+               return MICRON_ON_DIE_UNSUPPORTED;
+
        ret = nand_readid_op(chip, 0, id, sizeof(id));
        if (ret)
                return MICRON_ON_DIE_UNSUPPORTED;
index 03cc788511d59e22935f2b03762191e24e14b663..654bdc41fc99e4aee9a2ce3b0472769c0706f079 100644 (file)
@@ -3780,8 +3780,6 @@ static int spi_nor_init_params(struct spi_nor *nor,
                default:
                        /* Kept only for backward compatibility purpose. */
                        params->quad_enable = spansion_quad_enable;
-                       if (nor->clear_sr_bp)
-                               nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
                        break;
                }
 
@@ -4035,6 +4033,9 @@ static int spi_nor_init(struct spi_nor *nor)
        int err;
 
        if (nor->clear_sr_bp) {
+               if (nor->quad_enable == spansion_quad_enable)
+                       nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
+
                err = nor->clear_sr_bp(nor);
                if (err) {
                        dev_err(nor->dev,
index 11c5bad95226698ab2888f2ad971220a2c5df8e4..14a5fb3781453526914bdab493c9b68beaa596b3 100644 (file)
@@ -363,10 +363,13 @@ static int __init arcrimi_setup(char *s)
        switch (ints[0]) {
        default:                /* ERROR */
                pr_err("Too many arguments\n");
+               /* Fall through */
        case 3:         /* Node ID */
                node = ints[3];
+               /* Fall through */
        case 2:         /* IRQ */
                irq = ints[2];
+               /* Fall through */
        case 1:         /* IO address */
                io = ints[1];
        }
index 28510e33924fbd7099f232a869c7715656eccc4e..cd27fdc1059b908900fe72d7e23503750dface0a 100644 (file)
@@ -197,16 +197,22 @@ static int __init com20020isa_setup(char *s)
        switch (ints[0]) {
        default:                /* ERROR */
                pr_info("Too many arguments\n");
+               /* Fall through */
        case 6:         /* Timeout */
                timeout = ints[6];
+               /* Fall through */
        case 5:         /* CKP value */
                clockp = ints[5];
+               /* Fall through */
        case 4:         /* Backplane flag */
                backplane = ints[4];
+               /* Fall through */
        case 3:         /* Node ID */
                node = ints[3];
+               /* Fall through */
        case 2:         /* IRQ */
                irq = ints[2];
+               /* Fall through */
        case 1:         /* IO address */
                io = ints[1];
        }
index 2c546013a98014b4c83b759d293ed24f91b3c940..186bbf87bc849f1e3e80180068412de2a5ff1606 100644 (file)
@@ -363,8 +363,10 @@ static int __init com90io_setup(char *s)
        switch (ints[0]) {
        default:                /* ERROR */
                pr_err("Too many arguments\n");
+               /* Fall through */
        case 2:         /* IRQ */
                irq = ints[2];
+               /* Fall through */
        case 1:         /* IO address */
                io = ints[1];
        }
index ca4a57c30bf89ed8d565d228aca9953153a3adf4..bd75d06ad7dfc98c982a3c7f033508a8e398d3ae 100644 (file)
@@ -693,10 +693,13 @@ static int __init com90xx_setup(char *s)
        switch (ints[0]) {
        default:                /* ERROR */
                pr_err("Too many arguments\n");
+               /* Fall through */
        case 3:         /* Mem address */
                shmem = ints[3];
+               /* Fall through */
        case 2:         /* IRQ */
                irq = ints[2];
+               /* Fall through */
        case 1:         /* IO address */
                io = ints[1];
        }
index 9b7016abca2f6c4a89185fb23b0bd719e18c08e4..931d9d9356869b400c1b653414164a3e5ecb0b51 100644 (file)
@@ -1126,6 +1126,8 @@ static void bond_compute_features(struct bonding *bond)
 done:
        bond_dev->vlan_features = vlan_features;
        bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+                                   NETIF_F_HW_VLAN_CTAG_TX |
+                                   NETIF_F_HW_VLAN_STAG_TX |
                                    NETIF_F_GSO_UDP_L4;
        bond_dev->mpls_features = mpls_features;
        bond_dev->gso_max_segs = gso_max_segs;
@@ -2196,6 +2198,15 @@ static void bond_miimon_commit(struct bonding *bond)
        bond_for_each_slave(bond, slave, iter) {
                switch (slave->new_link) {
                case BOND_LINK_NOCHANGE:
+                       /* For 802.3ad mode, check current slave speed and
+                        * duplex again in case its port was disabled after
+                        * invalid speed/duplex reporting but recovered before
+                        * link monitoring could make a decision on the actual
+                        * link status
+                        */
+                       if (BOND_MODE(bond) == BOND_MODE_8023AD &&
+                           slave->link == BOND_LINK_UP)
+                               bond_3ad_adapter_speed_duplex_changed(slave);
                        continue;
 
                case BOND_LINK_UP:
index 1d4075903971e21082ce941282d5ef7c655da3f6..c8e1a04ba384dfbea3c8e1d191cc1c07cbf455e8 100644 (file)
@@ -898,7 +898,8 @@ static void at91_irq_err_state(struct net_device *dev,
                                CAN_ERR_CRTL_TX_WARNING :
                                CAN_ERR_CRTL_RX_WARNING;
                }
-       case CAN_STATE_ERROR_WARNING:   /* fallthrough */
+               /* fall through */
+       case CAN_STATE_ERROR_WARNING:
                /*
                 * from: ERROR_ACTIVE, ERROR_WARNING
                 * to  : ERROR_PASSIVE, BUS_OFF
@@ -947,7 +948,8 @@ static void at91_irq_err_state(struct net_device *dev,
                netdev_dbg(dev, "Error Active\n");
                cf->can_id |= CAN_ERR_PROT;
                cf->data[2] = CAN_ERR_PROT_ACTIVE;
-       case CAN_STATE_ERROR_WARNING:   /* fallthrough */
+               /* fall through */
+       case CAN_STATE_ERROR_WARNING:
                reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF;
                reg_ier = AT91_IRQ_ERRP;
                break;
index b6b93a2d93a59293dccbfe00158857aae5a21965..483d270664cc87efd828993641406e24818db334 100644 (file)
@@ -1249,6 +1249,8 @@ int register_candev(struct net_device *dev)
                return -EINVAL;
 
        dev->rtnl_link_ops = &can_link_ops;
+       netif_carrier_off(dev);
+
        return register_netdev(dev);
 }
 EXPORT_SYMBOL_GPL(register_candev);
index f2fe344593d58ce66697515326efae700dab22ce..fcec8bcb53d64cd246b1e003de157432ec32bd41 100644 (file)
@@ -400,9 +400,10 @@ static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
        priv->write(reg_mcr, &regs->mcr);
 }
 
-static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
+static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
+       unsigned int ackval;
        u32 reg_mcr;
 
        reg_mcr = priv->read(&regs->mcr);
@@ -412,20 +413,37 @@ static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
        /* enable stop request */
        regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
                           1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
+
+       /* get stop acknowledgment */
+       if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
+                                    ackval, ackval & (1 << priv->stm.ack_bit),
+                                    0, FLEXCAN_TIMEOUT_US))
+               return -ETIMEDOUT;
+
+       return 0;
 }
 
-static inline void flexcan_exit_stop_mode(struct flexcan_priv *priv)
+static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
+       unsigned int ackval;
        u32 reg_mcr;
 
        /* remove stop request */
        regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
                           1 << priv->stm.req_bit, 0);
 
+       /* get stop acknowledgment */
+       if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
+                                    ackval, !(ackval & (1 << priv->stm.ack_bit)),
+                                    0, FLEXCAN_TIMEOUT_US))
+               return -ETIMEDOUT;
+
        reg_mcr = priv->read(&regs->mcr);
        reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
        priv->write(reg_mcr, &regs->mcr);
+
+       return 0;
 }
 
 static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
@@ -1437,10 +1455,10 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
 
        priv = netdev_priv(dev);
        priv->stm.gpr = syscon_node_to_regmap(gpr_np);
-       of_node_put(gpr_np);
        if (IS_ERR(priv->stm.gpr)) {
                dev_dbg(&pdev->dev, "could not find gpr regmap\n");
-               return PTR_ERR(priv->stm.gpr);
+               ret = PTR_ERR(priv->stm.gpr);
+               goto out_put_node;
        }
 
        priv->stm.req_gpr = out_val[1];
@@ -1455,7 +1473,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
 
        device_set_wakeup_capable(&pdev->dev, true);
 
-       return 0;
+out_put_node:
+       of_node_put(gpr_np);
+       return ret;
 }
 
 static const struct of_device_id flexcan_of_match[] = {
@@ -1612,7 +1632,9 @@ static int __maybe_unused flexcan_suspend(struct device *device)
                 */
                if (device_may_wakeup(device)) {
                        enable_irq_wake(dev->irq);
-                       flexcan_enter_stop_mode(priv);
+                       err = flexcan_enter_stop_mode(priv);
+                       if (err)
+                               return err;
                } else {
                        err = flexcan_chip_disable(priv);
                        if (err)
@@ -1662,10 +1684,13 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
 {
        struct net_device *dev = dev_get_drvdata(device);
        struct flexcan_priv *priv = netdev_priv(dev);
+       int err;
 
        if (netif_running(dev) && device_may_wakeup(device)) {
                flexcan_enable_wakeup_irq(priv, false);
-               flexcan_exit_stop_mode(priv);
+               err = flexcan_exit_stop_mode(priv);
+               if (err)
+                       return err;
        }
 
        return 0;
index 7f6a3b971da915809cd5fa727554172693601d20..13b10cbf236a50071be65ef06aa7a9c4c373dad1 100644 (file)
@@ -660,7 +660,7 @@ static int pciefd_can_probe(struct pciefd_board *pciefd)
                pciefd_can_writereg(priv, CANFD_CLK_SEL_80MHZ,
                                    PCIEFD_REG_CAN_CLK_SEL);
 
-               /* fallthough */
+               /* fall through */
        case CANFD_CLK_SEL_80MHZ:
                priv->ucan.can.clock.freq = 80 * 1000 * 1000;
                break;
index 05410008aa6b6ee2ac1a6a957c2b0b838f9ee2fc..de34a4b82d4ad474ff2ba253ba29f52d5347d8f3 100644 (file)
@@ -1508,10 +1508,11 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota)
 
        /* All packets processed */
        if (num_pkts < quota) {
-               napi_complete_done(napi, num_pkts);
-               /* Enable Rx FIFO interrupts */
-               rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx),
-                                  RCANFD_RFCC_RFIE);
+               if (napi_complete_done(napi, num_pkts)) {
+                       /* Enable Rx FIFO interrupts */
+                       rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx),
+                                          RCANFD_RFCC_RFIE);
+               }
        }
        return num_pkts;
 }
index 185c7f7d38a4ae15f64e6c38539534e007273411..5e0d5e8101c86913955525f93c1aacad0b83268b 100644 (file)
@@ -479,7 +479,7 @@ static void pcan_free_channels(struct pcan_pccard *card)
                if (!netdev)
                        continue;
 
-               strncpy(name, netdev->name, IFNAMSIZ);
+               strlcpy(name, netdev->name, IFNAMSIZ);
 
                unregister_sja1000dev(netdev);
 
index 44e99e3d713487ff8b9cbc5c15046276274d6c04..12358f06d19400bed0dab5d094d04e5e3da2a436 100644 (file)
@@ -664,17 +664,6 @@ static int mcp251x_power_enable(struct regulator *reg, int enable)
                return regulator_disable(reg);
 }
 
-static void mcp251x_open_clean(struct net_device *net)
-{
-       struct mcp251x_priv *priv = netdev_priv(net);
-       struct spi_device *spi = priv->spi;
-
-       free_irq(spi->irq, priv);
-       mcp251x_hw_sleep(spi);
-       mcp251x_power_enable(priv->transceiver, 0);
-       close_candev(net);
-}
-
 static int mcp251x_stop(struct net_device *net)
 {
        struct mcp251x_priv *priv = netdev_priv(net);
@@ -860,7 +849,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
                        if (new_state >= CAN_STATE_ERROR_WARNING &&
                            new_state <= CAN_STATE_BUS_OFF)
                                priv->can.can_stats.error_warning++;
-               case CAN_STATE_ERROR_WARNING:   /* fallthrough */
+                       /* fall through */
+               case CAN_STATE_ERROR_WARNING:
                        if (new_state >= CAN_STATE_ERROR_PASSIVE &&
                            new_state <= CAN_STATE_BUS_OFF)
                                priv->can.can_stats.error_passive++;
@@ -940,37 +930,43 @@ static int mcp251x_open(struct net_device *net)
                                   flags | IRQF_ONESHOT, DEVICE_NAME, priv);
        if (ret) {
                dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
-               mcp251x_power_enable(priv->transceiver, 0);
-               close_candev(net);
-               goto open_unlock;
+               goto out_close;
        }
 
        priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
                                   0);
+       if (!priv->wq) {
+               ret = -ENOMEM;
+               goto out_clean;
+       }
        INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
        INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler);
 
        ret = mcp251x_hw_reset(spi);
-       if (ret) {
-               mcp251x_open_clean(net);
-               goto open_unlock;
-       }
+       if (ret)
+               goto out_free_wq;
        ret = mcp251x_setup(net, spi);
-       if (ret) {
-               mcp251x_open_clean(net);
-               goto open_unlock;
-       }
+       if (ret)
+               goto out_free_wq;
        ret = mcp251x_set_normal_mode(spi);
-       if (ret) {
-               mcp251x_open_clean(net);
-               goto open_unlock;
-       }
+       if (ret)
+               goto out_free_wq;
 
        can_led_event(net, CAN_LED_EVENT_OPEN);
 
        netif_wake_queue(net);
+       mutex_unlock(&priv->mcp_lock);
 
-open_unlock:
+       return 0;
+
+out_free_wq:
+       destroy_workqueue(priv->wq);
+out_clean:
+       free_irq(spi->irq, priv);
+       mcp251x_hw_sleep(spi);
+out_close:
+       mcp251x_power_enable(priv->transceiver, 0);
+       close_candev(net);
        mutex_unlock(&priv->mcp_lock);
        return ret;
 }
index 15ce5ad1d6322ab40a8ad563ca013057bf3796e8..617da295b6c12647d48ee8b4e88c5a099d53e13a 100644 (file)
@@ -415,7 +415,7 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
                        new_state = CAN_STATE_ERROR_WARNING;
                        break;
                }
-               /* else: fall through */
+               /* fall through */
 
        case CAN_STATE_ERROR_WARNING:
                if (n & PCAN_USB_ERROR_BUS_HEAVY) {
index 458154c9b48298b45c1e93a83fc98afe47eb1caa..65dce642b86b54c8378bece93bfdc738573470ae 100644 (file)
@@ -568,16 +568,16 @@ static int peak_usb_ndo_stop(struct net_device *netdev)
        dev->state &= ~PCAN_USB_STATE_STARTED;
        netif_stop_queue(netdev);
 
+       close_candev(netdev);
+
+       dev->can.state = CAN_STATE_STOPPED;
+
        /* unlink all pending urbs and free used memory */
        peak_usb_unlink_all_urbs(dev);
 
        if (dev->adapter->dev_stop)
                dev->adapter->dev_stop(dev);
 
-       close_candev(netdev);
-
-       dev->can.state = CAN_STATE_STOPPED;
-
        /* can set bus off now */
        if (dev->adapter->dev_set_bus) {
                int err = dev->adapter->dev_set_bus(dev, 0);
@@ -855,7 +855,7 @@ static void peak_usb_disconnect(struct usb_interface *intf)
 
                dev_prev_siblings = dev->prev_siblings;
                dev->state &= ~PCAN_USB_STATE_CONNECTED;
-               strncpy(name, netdev->name, IFNAMSIZ);
+               strlcpy(name, netdev->name, IFNAMSIZ);
 
                unregister_netdev(netdev);
 
index 34761c3a62867d1001f48224bd9e51b1685bbb74..47cc1ff5b88e828fe65899b8ef38b447ae1da098 100644 (file)
@@ -841,7 +841,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
                        goto err_out;
 
                /* allocate command buffer once for all for the interface */
-               pdev->cmd_buffer_addr = kmalloc(PCAN_UFD_CMD_BUFFER_SIZE,
+               pdev->cmd_buffer_addr = kzalloc(PCAN_UFD_CMD_BUFFER_SIZE,
                                                GFP_KERNEL);
                if (!pdev->cmd_buffer_addr)
                        goto err_out_1;
index 178bb7cff0c1a10378ea711af07d380367021b26..53cb2f72bdd0574b4fe6bcd654dd12cf57179546 100644 (file)
@@ -494,7 +494,7 @@ static int pcan_usb_pro_drv_loaded(struct peak_usb_device *dev, int loaded)
        u8 *buffer;
        int err;
 
-       buffer = kmalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL);
+       buffer = kzalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL);
        if (!buffer)
                return -ENOMEM;
 
index 3811fdbda13e93c5033e0fc0c6bdbfc089bfb5f8..28c963a21dac33465f01e04515d9af3543d8e9c1 100644 (file)
@@ -478,6 +478,7 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port,
                                unsigned long *supported,
                                struct phylink_link_state *state)
 {
+       struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
        __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
 
        if (!phy_interface_mode_is_rgmii(state->interface) &&
@@ -487,8 +488,10 @@ static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port,
            state->interface != PHY_INTERFACE_MODE_INTERNAL &&
            state->interface != PHY_INTERFACE_MODE_MOCA) {
                bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
-               dev_err(ds->dev,
-                       "Unsupported interface: %d\n", state->interface);
+               if (port != core_readl(priv, CORE_IMP0_PRT_ID))
+                       dev_err(ds->dev,
+                               "Unsupported interface: %d for port %d\n",
+                               state->interface, port);
                return;
        }
 
@@ -526,6 +529,9 @@ static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port,
        u32 id_mode_dis = 0, port_mode;
        u32 reg, offset;
 
+       if (port == core_readl(priv, CORE_IMP0_PRT_ID))
+               return;
+
        if (priv->type == BCM7445_DEVICE_ID)
                offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
        else
index 5a9e27b337a8296839442c21b2db005fd3179eac..098b01e4ed1a9b0c4841d5c0e7241248a75b2234 100644 (file)
@@ -81,6 +81,7 @@ static const struct of_device_id ksz9477_dt_ids[] = {
        { .compatible = "microchip,ksz9897" },
        { .compatible = "microchip,ksz9893" },
        { .compatible = "microchip,ksz9563" },
+       { .compatible = "microchip,ksz8563" },
        {},
 };
 MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
index ee7096d8af070e86543888c971fea0983e1e5433..72ec250b954088e011be15b57ebf0d66b19aa18b 100644 (file)
@@ -128,6 +128,7 @@ static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,
 
 #define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign)                \
        {                                                               \
+               .name = #width,                                         \
                .val_bits = (width),                                    \
                .reg_stride = (width) / 8,                              \
                .reg_bits = (regbits) + (regalign),                     \
index 6b17cd961d061285b7f3c258ab37445559e8b04f..d0a97eb73a37678b8fba381a200399c7736769cc 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/platform_data/mv88e6xxx.h>
 #include <linux/netdevice.h>
 #include <linux/gpio/consumer.h>
-#include <linux/phy.h>
 #include <linux/phylink.h>
 #include <net/dsa.h>
 
@@ -430,7 +429,7 @@ int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
                return 0;
 
        /* Port's MAC control must not be changed unless the link is down */
-       err = chip->info->ops->port_set_link(chip, port, 0);
+       err = chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN);
        if (err)
                return err;
 
@@ -482,30 +481,6 @@ static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
        return port < chip->info->num_internal_phys;
 }
 
-/* We expect the switch to perform auto negotiation if there is a real
- * phy. However, in the case of a fixed link phy, we force the port
- * settings from the fixed link settings.
- */
-static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
-                                 struct phy_device *phydev)
-{
-       struct mv88e6xxx_chip *chip = ds->priv;
-       int err;
-
-       if (!phy_is_pseudo_fixed_link(phydev) &&
-           mv88e6xxx_phy_is_internal(ds, port))
-               return;
-
-       mv88e6xxx_reg_lock(chip);
-       err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
-                                      phydev->duplex, phydev->pause,
-                                      phydev->interface);
-       mv88e6xxx_reg_unlock(chip);
-
-       if (err && err != -EOPNOTSUPP)
-               dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
-}
-
 static void mv88e6065_phylink_validate(struct mv88e6xxx_chip *chip, int port,
                                       unsigned long *mask,
                                       struct phylink_link_state *state)
@@ -2721,6 +2696,7 @@ static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip,
                        err = mv88e6xxx_mdio_register(chip, child, true);
                        if (err) {
                                mv88e6xxx_mdios_unregister(chip);
+                               of_node_put(child);
                                return err;
                        }
                }
@@ -4638,7 +4614,6 @@ static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port,
 static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
        .get_tag_protocol       = mv88e6xxx_get_tag_protocol,
        .setup                  = mv88e6xxx_setup,
-       .adjust_link            = mv88e6xxx_adjust_link,
        .phylink_validate       = mv88e6xxx_validate,
        .phylink_mac_link_state = mv88e6xxx_link_state,
        .phylink_mac_config     = mv88e6xxx_mac_config,
index 232e8cc96f6dee10ecfba315cc9fc9eb7a9975fb..16f15c93a102c9b66d76c22ae0e8e310a6b6edf5 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
  * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
  * Copyright (c) 2016 John Crispin <john@phrozen.org>
  */
 
@@ -583,8 +583,11 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
 
        for_each_available_child_of_node(ports, port) {
                err = of_property_read_u32(port, "reg", &reg);
-               if (err)
+               if (err) {
+                       of_node_put(port);
+                       of_node_put(ports);
                        return err;
+               }
 
                if (!dsa_is_user_port(priv->ds, reg))
                        continue;
@@ -595,6 +598,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
                        internal_mdio_mask |= BIT(reg);
        }
 
+       of_node_put(ports);
        if (!external_mdio_mask && !internal_mdio_mask) {
                dev_err(priv->dev, "no PHYs are defined.\n");
                return -EINVAL;
@@ -935,6 +939,8 @@ qca8k_port_enable(struct dsa_switch *ds, int port,
        qca8k_port_set_status(priv, port, 1);
        priv->port_sts[port].enabled = 1;
 
+       phy_support_asym_pause(phy);
+
        return 0;
 }
 
index 6bfb1696a6f2806dc4b875329b9e0ae720517d90..9988c9d185678a678ca262e9dfdc6b5f09ce30ae 100644 (file)
@@ -277,6 +277,18 @@ sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
                        SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
 }
 
+static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
+                                                   enum packing_op op)
+{
+       struct sja1105_l2_lookup_entry *entry = entry_ptr;
+       u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
+       const int size = SJA1105_SIZE_DYN_CMD;
+
+       sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
+
+       return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
+}
+
 static void
 sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
                                 enum packing_op op)
@@ -477,7 +489,7 @@ sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
 /* SJA1105E/T: First generation */
 struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
        [BLK_IDX_L2_LOOKUP] = {
-               .entry_packing = sja1105et_l2_lookup_entry_packing,
+               .entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
                .cmd_packing = sja1105et_l2_lookup_cmd_packing,
                .access = (OP_READ | OP_WRITE | OP_DEL),
                .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
index 32bf3a7cc3b6db9961ec7df11cc0e9bb127de4a8..df976b259e43d24dc226d1e347c6338412868fe6 100644 (file)
@@ -218,7 +218,7 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv)
                /* This selects between Independent VLAN Learning (IVL) and
                 * Shared VLAN Learning (SVL)
                 */
-               .shared_learn = false,
+               .shared_learn = true,
                /* Don't discard management traffic based on ENFPORT -
                 * we don't perform SMAC port enforcement anyway, so
                 * what we are setting here doesn't matter.
@@ -625,6 +625,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
                if (of_property_read_u32(child, "reg", &index) < 0) {
                        dev_err(dev, "Port number not defined in device tree "
                                "(property \"reg\")\n");
+                       of_node_put(child);
                        return -ENODEV;
                }
 
@@ -634,6 +635,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
                        dev_err(dev, "Failed to read phy-mode or "
                                "phy-interface-type property for port %d\n",
                                index);
+                       of_node_put(child);
                        return -ENODEV;
                }
                ports[index].phy_mode = phy_mode;
@@ -643,6 +645,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
                        if (!of_phy_is_fixed_link(child)) {
                                dev_err(dev, "phy-handle or fixed-link "
                                        "properties missing!\n");
+                               of_node_put(child);
                                return -ENODEV;
                        }
                        /* phy-handle is missing, but fixed-link isn't.
@@ -1089,8 +1092,13 @@ int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port,
        l2_lookup.vlanid = vid;
        l2_lookup.iotag = SJA1105_S_TAG;
        l2_lookup.mask_macaddr = GENMASK_ULL(ETH_ALEN * 8 - 1, 0);
-       l2_lookup.mask_vlanid = VLAN_VID_MASK;
-       l2_lookup.mask_iotag = BIT(0);
+       if (dsa_port_is_vlan_filtering(&ds->ports[port])) {
+               l2_lookup.mask_vlanid = VLAN_VID_MASK;
+               l2_lookup.mask_iotag = BIT(0);
+       } else {
+               l2_lookup.mask_vlanid = 0;
+               l2_lookup.mask_iotag = 0;
+       }
        l2_lookup.destports = BIT(port);
 
        rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
@@ -1147,8 +1155,13 @@ int sja1105pqrs_fdb_del(struct dsa_switch *ds, int port,
        l2_lookup.vlanid = vid;
        l2_lookup.iotag = SJA1105_S_TAG;
        l2_lookup.mask_macaddr = GENMASK_ULL(ETH_ALEN * 8 - 1, 0);
-       l2_lookup.mask_vlanid = VLAN_VID_MASK;
-       l2_lookup.mask_iotag = BIT(0);
+       if (dsa_port_is_vlan_filtering(&ds->ports[port])) {
+               l2_lookup.mask_vlanid = VLAN_VID_MASK;
+               l2_lookup.mask_iotag = BIT(0);
+       } else {
+               l2_lookup.mask_vlanid = 0;
+               l2_lookup.mask_iotag = 0;
+       }
        l2_lookup.destports = BIT(port);
 
        rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
@@ -1178,60 +1191,31 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
                           const unsigned char *addr, u16 vid)
 {
        struct sja1105_private *priv = ds->priv;
-       u16 rx_vid, tx_vid;
-       int rc, i;
 
-       if (dsa_port_is_vlan_filtering(&ds->ports[port]))
-               return priv->info->fdb_add_cmd(ds, port, addr, vid);
-
-       /* Since we make use of VLANs even when the bridge core doesn't tell us
-        * to, translate these FDB entries into the correct dsa_8021q ones.
-        * The basic idea (also repeats for removal below) is:
-        * - Each of the other front-panel ports needs to be able to forward a
-        *   pvid-tagged (aka tagged with their rx_vid) frame that matches this
-        *   DMAC.
-        * - The CPU port (aka the tx_vid of this port) needs to be able to
-        *   send a frame matching this DMAC to the specified port.
-        * For a better picture see net/dsa/tag_8021q.c.
+       /* dsa_8021q is in effect when the bridge's vlan_filtering isn't,
+        * so the switch still does some VLAN processing internally.
+        * But Shared VLAN Learning (SVL) is also active, and it will take
+        * care of autonomous forwarding between the unique pvid's of each
+        * port.  Here we just make sure that users can't add duplicate FDB
+        * entries when in this mode - the actual VID doesn't matter except
+        * for what gets printed in 'bridge fdb show'.  In the case of zero,
+        * no VID gets printed at all.
         */
-       for (i = 0; i < SJA1105_NUM_PORTS; i++) {
-               if (i == port)
-                       continue;
-               if (i == dsa_upstream_port(priv->ds, port))
-                       continue;
+       if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+               vid = 0;
 
-               rx_vid = dsa_8021q_rx_vid(ds, i);
-               rc = priv->info->fdb_add_cmd(ds, port, addr, rx_vid);
-               if (rc < 0)
-                       return rc;
-       }
-       tx_vid = dsa_8021q_tx_vid(ds, port);
-       return priv->info->fdb_add_cmd(ds, port, addr, tx_vid);
+       return priv->info->fdb_add_cmd(ds, port, addr, vid);
 }
 
 static int sja1105_fdb_del(struct dsa_switch *ds, int port,
                           const unsigned char *addr, u16 vid)
 {
        struct sja1105_private *priv = ds->priv;
-       u16 rx_vid, tx_vid;
-       int rc, i;
 
-       if (dsa_port_is_vlan_filtering(&ds->ports[port]))
-               return priv->info->fdb_del_cmd(ds, port, addr, vid);
+       if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+               vid = 0;
 
-       for (i = 0; i < SJA1105_NUM_PORTS; i++) {
-               if (i == port)
-                       continue;
-               if (i == dsa_upstream_port(priv->ds, port))
-                       continue;
-
-               rx_vid = dsa_8021q_rx_vid(ds, i);
-               rc = priv->info->fdb_del_cmd(ds, port, addr, rx_vid);
-               if (rc < 0)
-                       return rc;
-       }
-       tx_vid = dsa_8021q_tx_vid(ds, port);
-       return priv->info->fdb_del_cmd(ds, port, addr, tx_vid);
+       return priv->info->fdb_del_cmd(ds, port, addr, vid);
 }
 
 static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
@@ -1239,12 +1223,8 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
 {
        struct sja1105_private *priv = ds->priv;
        struct device *dev = ds->dev;
-       u16 rx_vid, tx_vid;
        int i;
 
-       rx_vid = dsa_8021q_rx_vid(ds, port);
-       tx_vid = dsa_8021q_tx_vid(ds, port);
-
        for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
                struct sja1105_l2_lookup_entry l2_lookup = {0};
                u8 macaddr[ETH_ALEN];
@@ -1270,39 +1250,9 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
                        continue;
                u64_to_ether_addr(l2_lookup.macaddr, macaddr);
 
-               /* On SJA1105 E/T, the switch doesn't implement the LOCKEDS
-                * bit, so it doesn't tell us whether a FDB entry is static
-                * or not.
-                * But, of course, we can find out - we're the ones who added
-                * it in the first place.
-                */
-               if (priv->info->device_id == SJA1105E_DEVICE_ID ||
-                   priv->info->device_id == SJA1105T_DEVICE_ID) {
-                       int match;
-
-                       match = sja1105_find_static_fdb_entry(priv, port,
-                                                             &l2_lookup);
-                       l2_lookup.lockeds = (match >= 0);
-               }
-
-               /* We need to hide the dsa_8021q VLANs from the user. This
-                * basically means hiding the duplicates and only showing
-                * the pvid that is supposed to be active in standalone and
-                * non-vlan_filtering modes (aka 1).
-                * - For statically added FDB entries (bridge fdb add), we
-                *   can convert the TX VID (coming from the CPU port) into the
-                *   pvid and ignore the RX VIDs of the other ports.
-                * - For dynamically learned FDB entries, a single entry with
-                *   no duplicates is learned - that which has the real port's
-                *   pvid, aka RX VID.
-                */
-               if (!dsa_port_is_vlan_filtering(&ds->ports[port])) {
-                       if (l2_lookup.vlanid == tx_vid ||
-                           l2_lookup.vlanid == rx_vid)
-                               l2_lookup.vlanid = 1;
-                       else
-                               continue;
-               }
+               /* We need to hide the dsa_8021q VLANs from the user. */
+               if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+                       l2_lookup.vlanid = 0;
                cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
        }
        return 0;
@@ -1594,6 +1544,7 @@ static int sja1105_vlan_prepare(struct dsa_switch *ds, int port,
  */
 static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
 {
+       struct sja1105_l2_lookup_params_entry *l2_lookup_params;
        struct sja1105_general_params_entry *general_params;
        struct sja1105_private *priv = ds->priv;
        struct sja1105_table *table;
@@ -1622,6 +1573,28 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
        general_params->incl_srcpt1 = enabled;
        general_params->incl_srcpt0 = enabled;
 
+       /* VLAN filtering => independent VLAN learning.
+        * No VLAN filtering => shared VLAN learning.
+        *
+        * In shared VLAN learning mode, untagged traffic still gets
+        * pvid-tagged, and the FDB table gets populated with entries
+        * containing the "real" (pvid or from VLAN tag) VLAN ID.
+        * However the switch performs a masked L2 lookup in the FDB,
+        * effectively only looking up a frame's DMAC (and not VID) for the
+        * forwarding decision.
+        *
+        * This is extremely convenient for us, because in modes with
+        * vlan_filtering=0, dsa_8021q actually installs unique pvid's into
+        * each front panel port. This is good for identification but breaks
+        * learning badly - the VID of the learnt FDB entry is unique, aka
+        * no frames coming from any other port are going to have it. So
+        * for forwarding purposes, this is as though learning was broken
+        * (all frames get flooded).
+        */
+       table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS];
+       l2_lookup_params = table->entries;
+       l2_lookup_params->shared_learn = !enabled;
+
        rc = sja1105_static_config_reload(priv);
        if (rc)
                dev_err(ds->dev, "Failed to change VLAN Ethertype\n");
@@ -1751,6 +1724,8 @@ static void sja1105_teardown(struct dsa_switch *ds)
 
        cancel_work_sync(&priv->tagger_data.rxtstamp_work);
        skb_queue_purge(&priv->tagger_data.skb_rxtstamp_queue);
+       sja1105_ptp_clock_unregister(priv);
+       sja1105_static_config_free(&priv->static_config);
 }
 
 static int sja1105_mgmt_xmit(struct dsa_switch *ds, int port, int slot,
@@ -2208,9 +2183,7 @@ static int sja1105_remove(struct spi_device *spi)
 {
        struct sja1105_private *priv = spi_get_drvdata(spi);
 
-       sja1105_ptp_clock_unregister(priv);
        dsa_unregister_switch(priv->ds);
-       sja1105_static_config_free(&priv->static_config);
        return 0;
 }
 
index d19cfdf681af499ad4cae2e03aa0b9e73a754f03..d8e8dd59f3d1bba07a9b1c2a5a415818b7444020 100644 (file)
@@ -369,16 +369,15 @@ int sja1105_ptp_clock_register(struct sja1105_private *priv)
                .mult = SJA1105_CC_MULT,
        };
        mutex_init(&priv->ptp_lock);
-       INIT_DELAYED_WORK(&priv->refresh_work, sja1105_ptp_overflow_check);
-
-       schedule_delayed_work(&priv->refresh_work, SJA1105_REFRESH_INTERVAL);
-
        priv->ptp_caps = sja1105_ptp_caps;
 
        priv->clock = ptp_clock_register(&priv->ptp_caps, ds->dev);
        if (IS_ERR_OR_NULL(priv->clock))
                return PTR_ERR(priv->clock);
 
+       INIT_DELAYED_WORK(&priv->refresh_work, sja1105_ptp_overflow_check);
+       schedule_delayed_work(&priv->refresh_work, SJA1105_REFRESH_INTERVAL);
+
        return sja1105_ptp_reset(priv);
 }
 
index 2a3e2450968eeb066a8636001442d12413f78f3c..a9478577b49560f21a1b4c0f54f49f1dda0f15c4 100644 (file)
@@ -12,8 +12,8 @@ config NET_VENDOR_8390
 
          Note that the answer to this question doesn't directly affect the
          kernel: saying N will just cause the configurator to skip all
-         the questions about Western Digital cards. If you say Y, you will be
-         asked for your specific card in the following questions.
+         the questions about National Semiconductor 8390 cards. If you say Y,
+         you will be asked for your specific card in the following questions.
 
 if NET_VENDOR_8390
 
index ea34bcb868b57fba300df2d9d393aaa2ad82a926..edbb4b3604c751e9b02e4c4643b0406021514ed9 100644 (file)
@@ -2362,7 +2362,7 @@ static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
 
        /* Allocate memory for the TCB's (Transmit Control Block) */
        tx_ring->tcb_ring = kcalloc(NUM_TCB, sizeof(struct tcb),
-                                   GFP_ATOMIC | GFP_DMA);
+                                   GFP_KERNEL | GFP_DMA);
        if (!tx_ring->tcb_ring)
                return -ENOMEM;
 
index 3434730a76990b6ed78f4207428c1eabc8d49155..0537df06a9b58ae47f3f139266d12dd906ce9be6 100644 (file)
@@ -860,7 +860,9 @@ static int emac_probe(struct platform_device *pdev)
                goto out_clk_disable_unprepare;
        }
 
-       db->phy_node = of_parse_phandle(np, "phy", 0);
+       db->phy_node = of_parse_phandle(np, "phy-handle", 0);
+       if (!db->phy_node)
+               db->phy_node = of_parse_phandle(np, "phy", 0);
        if (!db->phy_node) {
                dev_err(&pdev->dev, "no associated PHY\n");
                ret = -ENODEV;
index de4950d2022e0a6d6efdc4a255cba93e2edbd77b..9f965cdfff5c99db9ff3f8d1d94a1f753cbbbd3a 100644 (file)
@@ -14,7 +14,7 @@ config NET_VENDOR_AMD
          say Y.
 
          Note that the answer to this question does not directly affect
-         the kernel: saying N will just case the configurator to skip all
+         the kernel: saying N will just cause the configurator to skip all
          the questions regarding AMD chipsets. If you say Y, you will be asked
          for your specific chipset/driver in the following questions.
 
index b41f23679a087b2a49676ae362044c1b8085820a..7ce9c69e9c44f3d4288d04f710b96222ebf2fb77 100644 (file)
@@ -469,13 +469,19 @@ static int __init xgbe_mod_init(void)
 
        ret = xgbe_platform_init();
        if (ret)
-               return ret;
+               goto err_platform_init;
 
        ret = xgbe_pci_init();
        if (ret)
-               return ret;
+               goto err_pci_init;
 
        return 0;
+
+err_pci_init:
+       xgbe_platform_exit();
+err_platform_init:
+       unregister_netdevice_notifier(&xgbe_netdev_notifier);
+       return ret;
 }
 
 static void __exit xgbe_mod_exit(void)
index fde7ae33e302b6bc169469928c4e25bde2e2161b..f78b9c841296c94b92089c40d1c82e33a75f689c 100644 (file)
@@ -11,8 +11,8 @@ config NET_VENDOR_APPLE
          If you have a network (Ethernet) card belonging to this class, say Y.
 
          Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about IBM devices. If you say Y, you will be asked for
+         kernel: saying N will just cause the configurator to skip all the
+         questions about Apple devices. If you say Y, you will be asked for
          your specific card in the following questions.
 
 if NET_VENDOR_APPLE
index 440690b1873409b843bfd898f57944b231f5b047..aee827f07c160cb1591e5156dd51dc81de9fe527 100644 (file)
@@ -431,7 +431,8 @@ int aq_del_fvlan_by_vlan(struct aq_nic_s *aq_nic, u16 vlan_id)
                if (be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id)
                        break;
        }
-       if (rule && be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) {
+       if (rule && rule->type == aq_rx_filter_vlan &&
+           be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) {
                struct ethtool_rxnfc cmd;
 
                cmd.fs.location = rule->aq_fsp.location;
@@ -843,7 +844,7 @@ int aq_filters_vlans_update(struct aq_nic_s *aq_nic)
                return err;
 
        if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
-               if (hweight < AQ_VLAN_MAX_FILTERS && hweight > 0) {
+               if (hweight <= AQ_VLAN_MAX_FILTERS && hweight > 0) {
                        err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw,
                                !(aq_nic->packet_filter & IFF_PROMISC));
                        aq_nic->aq_nic_cfg.is_vlan_force_promisc = false;
index 100722ad5c2d8002631addb5bbc3f858b1ee9d62..b4a0fb281e69ea2631db1e6e45373e0d5a556a27 100644 (file)
@@ -61,6 +61,10 @@ static int aq_ndev_open(struct net_device *ndev)
        if (err < 0)
                goto err_exit;
 
+       err = aq_filters_vlans_update(aq_nic);
+       if (err < 0)
+               goto err_exit;
+
        err = aq_nic_start(aq_nic);
        if (err < 0)
                goto err_exit;
index e1392766e21e7980d39777fba5fbda3865d136c4..8f66e781781182e553c53ba73fde92581de21ee7 100644 (file)
@@ -393,7 +393,7 @@ int aq_nic_start(struct aq_nic_s *self)
                                                   self->aq_nic_cfg.link_irq_vec);
                        err = request_threaded_irq(irqvec, NULL,
                                                   aq_linkstate_threaded_isr,
-                                                  IRQF_SHARED,
+                                                  IRQF_SHARED | IRQF_ONESHOT,
                                                   self->ndev->name, self);
                        if (err < 0)
                                goto err_exit;
index 715685aa48c399dbf75c91833d466a8bff7983a4..28892b8acd0e1e070ed4b246548b780728c69948 100644 (file)
@@ -86,6 +86,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
                        }
                }
 
+err_exit:
                if (!was_tx_cleaned)
                        work_done = budget;
 
@@ -95,7 +96,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
                                        1U << self->aq_ring_param.vec_idx);
                }
        }
-err_exit:
+
        return work_done;
 }
 
index 8b69d0d7e7269e0b8d6c92f942ad5b0df535a55a..6703960c7cf5035a6af2fd8af53fa39e9a026d96 100644 (file)
@@ -1141,7 +1141,7 @@ static int ag71xx_rings_init(struct ag71xx *ag)
 
        tx->descs_cpu = dma_alloc_coherent(&ag->pdev->dev,
                                           ring_size * AG71XX_DESC_SIZE,
-                                          &tx->descs_dma, GFP_ATOMIC);
+                                          &tx->descs_dma, GFP_KERNEL);
        if (!tx->descs_cpu) {
                kfree(tx->buf);
                tx->buf = NULL;
index e9017caf024dcf33fba30506bb8a953b686ad560..e24f5d2b6afe35477940a4a6b86c55795f855a07 100644 (file)
@@ -14,9 +14,9 @@ config NET_VENDOR_BROADCOM
          say Y.
 
          Note that the answer to this question does not directly affect
-         the kernel: saying N will just case the configurator to skip all
-         the questions regarding AMD chipsets. If you say Y, you will be asked
-         for your specific chipset/driver in the following questions.
+         the kernel: saying N will just cause the configurator to skip all
+         the questions regarding Broadcom chipsets. If you say Y, you will
+         be asked for your specific chipset/driver in the following questions.
 
 if NET_VENDOR_BROADCOM
 
index b9c5cea8db168c2284846cd8b9e1f980ae78189e..9483553ce44452e6b742b278f18c277691568ed6 100644 (file)
@@ -992,7 +992,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
 {
        struct bcm_sysport_priv *priv =
                container_of(napi, struct bcm_sysport_priv, napi);
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
        unsigned int work_done = 0;
 
        work_done = bcm_sysport_desc_rx(priv, budget);
index 656ed80647f0275ce813ac51792bcb0d11586690..d10b421ed1f19939bb4046ede23d74b55ebb5beb 100644 (file)
@@ -285,6 +285,9 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata)
        hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
        sw_cons = txdata->tx_pkt_cons;
 
+       /* Ensure subsequent loads occur after hw_cons */
+       smp_rmb();
+
        while (sw_cons != hw_cons) {
                u16 pkt_cons;
 
@@ -1931,8 +1934,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
        }
 
        /* select a non-FCoE queue */
-       return netdev_pick_tx(dev, skb, NULL) %
-              (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos);
+       return netdev_pick_tx(dev, skb, NULL) % (BNX2X_NUM_ETH_QUEUES(bp));
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -3055,12 +3057,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        /* if VF indicate to PF this function is going down (PF will delete sp
         * elements and clear initializations
         */
-       if (IS_VF(bp))
+       if (IS_VF(bp)) {
+               bnx2x_clear_vlan_info(bp);
                bnx2x_vfpf_close_vf(bp);
-       else if (unload_mode != UNLOAD_RECOVERY)
+       } else if (unload_mode != UNLOAD_RECOVERY) {
                /* if this is a normal/close unload need to clean up chip*/
                bnx2x_chip_cleanup(bp, unload_mode, keep_link);
-       else {
+       else {
                /* Send the UNLOAD_REQUEST to the MCP */
                bnx2x_send_unload_req(bp, unload_mode);
 
index c2f6e44e9a3f7e75b41f2542fedb9595fa2ef154..8b08cb18e36387e8465dda447f3b42150cab28bb 100644 (file)
@@ -425,6 +425,8 @@ void bnx2x_set_reset_global(struct bnx2x *bp);
 void bnx2x_disable_close_the_gate(struct bnx2x *bp);
 int bnx2x_init_hw_func_cnic(struct bnx2x *bp);
 
+void bnx2x_clear_vlan_info(struct bnx2x *bp);
+
 /**
  * bnx2x_sp_event - handle ramrods completion.
  *
index 2cc14db8f0ec9c1d0ee8b922ea9926320cc5bb96..192ff8d5da3247c5f9f3b2fa0d7382adbdd83fb6 100644 (file)
@@ -8482,11 +8482,21 @@ int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
        return rc;
 }
 
+void bnx2x_clear_vlan_info(struct bnx2x *bp)
+{
+       struct bnx2x_vlan_entry *vlan;
+
+       /* Mark that hw forgot all entries */
+       list_for_each_entry(vlan, &bp->vlan_reg, link)
+               vlan->hw = false;
+
+       bp->vlan_cnt = 0;
+}
+
 static int bnx2x_del_all_vlans(struct bnx2x *bp)
 {
        struct bnx2x_vlan_mac_obj *vlan_obj = &bp->sp_objs[0].vlan_obj;
        unsigned long ramrod_flags = 0, vlan_flags = 0;
-       struct bnx2x_vlan_entry *vlan;
        int rc;
 
        __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
@@ -8495,10 +8505,7 @@ static int bnx2x_del_all_vlans(struct bnx2x *bp)
        if (rc)
                return rc;
 
-       /* Mark that hw forgot all entries */
-       list_for_each_entry(vlan, &bp->vlan_reg, link)
-               vlan->hw = false;
-       bp->vlan_cnt = 0;
+       bnx2x_clear_vlan_info(bp);
 
        return 0;
 }
index 7134d2c3eb1c4ccdcdd9cdd97497adedddefa159..8dce4069472b6c02ed6d5d9cb58cce5a7b1ddeaf 100644 (file)
@@ -2021,9 +2021,9 @@ static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
        if (bnapi->events & BNXT_RX_EVENT) {
                struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
 
-               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                if (bnapi->events & BNXT_AGG_EVENT)
                        bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
        }
        bnapi->events = 0;
 }
@@ -2136,7 +2136,7 @@ static int bnxt_poll(struct napi_struct *napi, int budget)
                }
        }
        if (bp->flags & BNXT_FLAG_DIM) {
-               struct dim_sample dim_sample;
+               struct dim_sample dim_sample = {};
 
                dim_update_sample(cpr->event_ctr,
                                  cpr->rx_packets,
@@ -5064,6 +5064,7 @@ static void bnxt_set_db(struct bnxt *bp, struct bnxt_db_info *db, u32 ring_type,
 
 static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
 {
+       bool agg_rings = !!(bp->flags & BNXT_FLAG_AGG_RINGS);
        int i, rc = 0;
        u32 type;
 
@@ -5139,7 +5140,9 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                if (rc)
                        goto err_out;
                bnxt_set_db(bp, &rxr->rx_db, type, map_idx, ring->fw_ring_id);
-               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
+               /* If we have agg rings, post agg buffers first. */
+               if (!agg_rings)
+                       bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                bp->grp_info[map_idx].rx_fw_ring_id = ring->fw_ring_id;
                if (bp->flags & BNXT_FLAG_CHIP_P5) {
                        struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
@@ -5158,7 +5161,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                }
        }
 
-       if (bp->flags & BNXT_FLAG_AGG_RINGS) {
+       if (agg_rings) {
                type = HWRM_RING_ALLOC_AGG;
                for (i = 0; i < bp->rx_nr_rings; i++) {
                        struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
@@ -5174,6 +5177,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                        bnxt_set_db(bp, &rxr->rx_agg_db, type, map_idx,
                                    ring->fw_ring_id);
                        bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+                       bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                        bp->grp_info[grp_idx].agg_fw_ring_id = ring->fw_ring_id;
                }
        }
@@ -7016,19 +7020,29 @@ static void bnxt_hwrm_clear_vnic_rss(struct bnxt *bp)
                bnxt_hwrm_vnic_set_rss(bp, i, false);
 }
 
-static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
-                                   bool irq_re_init)
+static void bnxt_clear_vnic(struct bnxt *bp)
 {
-       if (bp->vnic_info) {
-               bnxt_hwrm_clear_vnic_filter(bp);
+       if (!bp->vnic_info)
+               return;
+
+       bnxt_hwrm_clear_vnic_filter(bp);
+       if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
                /* clear all RSS setting before free vnic ctx */
                bnxt_hwrm_clear_vnic_rss(bp);
                bnxt_hwrm_vnic_ctx_free(bp);
-               /* before free the vnic, undo the vnic tpa settings */
-               if (bp->flags & BNXT_FLAG_TPA)
-                       bnxt_set_tpa(bp, false);
-               bnxt_hwrm_vnic_free(bp);
        }
+       /* before free the vnic, undo the vnic tpa settings */
+       if (bp->flags & BNXT_FLAG_TPA)
+               bnxt_set_tpa(bp, false);
+       bnxt_hwrm_vnic_free(bp);
+       if (bp->flags & BNXT_FLAG_CHIP_P5)
+               bnxt_hwrm_vnic_ctx_free(bp);
+}
+
+static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
+                                   bool irq_re_init)
+{
+       bnxt_clear_vnic(bp);
        bnxt_hwrm_ring_free(bp, close_path);
        bnxt_hwrm_ring_grp_free(bp);
        if (irq_re_init) {
index 549c90d3e465f2fd4f7eb494cee47373b953aaf5..c05d663212b20519a89f18d9d9429d897ac99bdf 100644 (file)
@@ -98,10 +98,13 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
        if (idx)
                req->dimensions = cpu_to_le16(1);
 
-       if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE))
+       if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
                memcpy(data_addr, buf, bytesize);
-
-       rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
+               rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
+       } else {
+               rc = hwrm_send_message_silent(bp, msg, msg_len,
+                                             HWRM_CMD_TIMEOUT);
+       }
        if (!rc && req->req_type == cpu_to_le16(HWRM_NVM_GET_VARIABLE))
                memcpy(buf, data_addr, bytesize);
 
index c7ee63d6967983d77087a9dcdda2638b683afcf1..8445a0cce849c0c8781a14dc5f11874cba1a53a5 100644 (file)
@@ -2016,21 +2016,19 @@ static int bnxt_flash_package_from_file(struct net_device *dev,
        mutex_lock(&bp->hwrm_cmd_lock);
        hwrm_err = _hwrm_send_message(bp, &install, sizeof(install),
                                      INSTALL_PACKAGE_TIMEOUT);
-       if (hwrm_err)
-               goto flash_pkg_exit;
-
-       if (resp->error_code) {
+       if (hwrm_err) {
                u8 error_code = ((struct hwrm_err_output *)resp)->cmd_err;
 
-               if (error_code == NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
+               if (resp->error_code && error_code ==
+                   NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
                        install.flags |= cpu_to_le16(
                               NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
                        hwrm_err = _hwrm_send_message(bp, &install,
                                                      sizeof(install),
                                                      INSTALL_PACKAGE_TIMEOUT);
-                       if (hwrm_err)
-                               goto flash_pkg_exit;
                }
+               if (hwrm_err)
+                       goto flash_pkg_exit;
        }
 
        if (resp->result) {
index 6fe4a7174271b8286cac810b94e5fa8b95c1a9b5..dd621f6bd1271c8c594185b5a82b8e892b3e6576 100644 (file)
@@ -1236,7 +1236,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
 static void bnxt_tc_set_flow_dir(struct bnxt *bp, struct bnxt_tc_flow *flow,
                                 u16 src_fid)
 {
-       flow->dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
+       flow->l2_key.dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
 }
 
 static void bnxt_tc_set_src_fid(struct bnxt *bp, struct bnxt_tc_flow *flow,
@@ -1285,9 +1285,7 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid,
                goto free_node;
 
        bnxt_tc_set_src_fid(bp, flow, src_fid);
-
-       if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
-               bnxt_tc_set_flow_dir(bp, flow, src_fid);
+       bnxt_tc_set_flow_dir(bp, flow, flow->src_fid);
 
        if (!bnxt_tc_can_offload(bp, flow)) {
                rc = -EOPNOTSUPP;
@@ -1407,7 +1405,7 @@ static void bnxt_fill_cfa_stats_req(struct bnxt *bp,
                 * 2. 15th bit of flow_handle must specify the flow
                 *    direction (TX/RX).
                 */
-               if (flow_node->flow.dir == BNXT_DIR_RX)
+               if (flow_node->flow.l2_key.dir == BNXT_DIR_RX)
                        handle = CFA_FLOW_INFO_REQ_FLOW_HANDLE_DIR_RX |
                                 CFA_FLOW_INFO_REQ_FLOW_HANDLE_MAX_MASK;
                else
index ffec57d1a5ecf2830e191c64bbd270905da209e7..4f05305052f2f27905646188a2d3047683ab419f 100644 (file)
@@ -23,6 +23,9 @@ struct bnxt_tc_l2_key {
        __be16          inner_vlan_tci;
        __be16          ether_type;
        u8              num_vlans;
+       u8              dir;
+#define BNXT_DIR_RX    1
+#define BNXT_DIR_TX    0
 };
 
 struct bnxt_tc_l3_key {
@@ -98,9 +101,6 @@ struct bnxt_tc_flow {
 
        /* flow applicable to pkts ingressing on this fid */
        u16                             src_fid;
-       u8                              dir;
-#define BNXT_DIR_RX    1
-#define BNXT_DIR_TX    0
        struct bnxt_tc_l2_key           l2_key;
        struct bnxt_tc_l2_key           l2_mask;
        struct bnxt_tc_l3_key           l3_key;
index a2b57807453b6f4c57fc53c408e488d10b217b66..b22196880d6d3226ce5845c02ef8d7fa601bae95 100644 (file)
@@ -1124,6 +1124,7 @@ static const struct ethtool_ops bcmgenet_ethtool_ops = {
        .set_coalesce           = bcmgenet_set_coalesce,
        .get_link_ksettings     = bcmgenet_get_link_ksettings,
        .set_link_ksettings     = bcmgenet_set_link_ksettings,
+       .get_ts_info            = ethtool_op_get_ts_info,
 };
 
 /* Power down the unimac, based on mode. */
@@ -1895,7 +1896,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
 {
        struct bcmgenet_rx_ring *ring = container_of(napi,
                        struct bcmgenet_rx_ring, napi);
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
        unsigned int work_done;
 
        work_done = bcmgenet_desc_rx(ring, budget);
index 5ca17e62dc3e07c5fade8c4881a73d9b8b45be49..35b59b5edf0f2ec653cd0cb21361247e4194a876 100644 (file)
@@ -4154,7 +4154,7 @@ static const struct of_device_id macb_dt_ids[] = {
        { .compatible = "cdns,emac", .data = &emac_config },
        { .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
        { .compatible = "cdns,zynq-gem", .data = &zynq_config },
-       { .compatible = "sifive,fu540-macb", .data = &fu540_c000_config },
+       { .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, macb_dt_ids);
index 73632b84374985cffdba907ad605499a6d71d420..b821c9e1604cff9c9b6ea412615140f293d5ee68 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "cavium_ptp.h"
 
-#define DRV_NAME       "Cavium PTP Driver"
+#define DRV_NAME "cavium_ptp"
 
 #define PCI_DEVICE_ID_CAVIUM_PTP       0xA00C
 #define PCI_DEVICE_ID_CAVIUM_RST       0xA00E
index 032224178b647e004dbf509594dbc249822d6806..6dd65f9b347cbc4573434385daaf5ad6e17e8be4 100644 (file)
@@ -237,8 +237,10 @@ int octeon_setup_iq(struct octeon_device *oct,
        }
 
        oct->num_iqs++;
-       if (oct->fn_list.enable_io_queues(oct))
+       if (oct->fn_list.enable_io_queues(oct)) {
+               octeon_delete_instr_queue(oct, iq_no);
                return 1;
+       }
 
        return 0;
 }
index ad22554857bf35df096408cea9184e5d786f7dc3..acb016834f0470ffbb9f0f79a57ef8809d2e567e 100644 (file)
@@ -1381,24 +1381,18 @@ static int acpi_get_mac_address(struct device *dev, struct acpi_device *adev,
                                u8 *dst)
 {
        u8 mac[ETH_ALEN];
-       int ret;
+       u8 *addr;
 
-       ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev),
-                                           "mac-address", mac, ETH_ALEN);
-       if (ret)
-               goto out;
-
-       if (!is_valid_ether_addr(mac)) {
+       addr = fwnode_get_mac_address(acpi_fwnode_handle(adev), mac, ETH_ALEN);
+       if (!addr) {
                dev_err(dev, "MAC address invalid: %pM\n", mac);
-               ret = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        dev_info(dev, "MAC address set to: %pM\n", mac);
 
-       memcpy(dst, mac, ETH_ALEN);
-out:
-       return ret;
+       ether_addr_copy(dst, mac);
+       return 0;
 }
 
 /* Currently only sets the MAC address. */
index 20c09cc4b3237a91ea634b20344f8f1b84a4438b..60aa45b375b65b668359e87800abe7796211ddb8 100644 (file)
@@ -94,7 +94,7 @@ static int my3126_interrupt_handler(struct cphy *cphy)
        return cphy_cause_link_change;
 }
 
-static void my3216_poll(struct work_struct *work)
+static void my3126_poll(struct work_struct *work)
 {
        struct cphy *cphy = container_of(work, struct cphy, phy_update.work);
 
@@ -177,7 +177,7 @@ static struct cphy *my3126_phy_create(struct net_device *dev,
                return NULL;
 
        cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops);
-       INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll);
+       INIT_DELAYED_WORK(&cphy->phy_update, my3126_poll);
        cphy->bmsr = 0;
 
        return cphy;
index 1e82b9efe447191799f8e5c881d32da7e7cf96ec..58f89f6a040fe39ef02d18d1fa65123d7cc7619a 100644 (file)
@@ -3269,7 +3269,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!adapter->regs) {
                dev_err(&pdev->dev, "cannot map device registers\n");
                err = -ENOMEM;
-               goto out_free_adapter;
+               goto out_free_adapter_nofail;
        }
 
        adapter->pdev = pdev;
@@ -3397,6 +3397,9 @@ out_free_dev:
                if (adapter->port[i])
                        free_netdev(adapter->port[i]);
 
+out_free_adapter_nofail:
+       kfree_skb(adapter->nofail_skb);
+
 out_free_adapter:
        kfree(adapter);
 
index 02959035ed3f21287a3673f93c55f0e76b549de1..d692251ee252c2e98bb46423002acda19829bf8f 100644 (file)
@@ -3236,8 +3236,10 @@ static ssize_t blocked_fl_write(struct file *filp, const char __user *ubuf,
                return -ENOMEM;
 
        err = bitmap_parse_user(ubuf, count, t, adap->sge.egr_sz);
-       if (err)
+       if (err) {
+               kvfree(t);
                return err;
+       }
 
        bitmap_copy(adap->sge.blocked_fl, t, adap->sge.egr_sz);
        kvfree(t);
index 67202b6f352e59858fe56156baba43506578b319..4311ad9c84b29f8643166f083ac9ddf97f3a1069 100644 (file)
@@ -5561,7 +5561,6 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
                char name[IFNAMSIZ];
                u32 devcap2;
                u16 flags;
-               int pos;
 
                /* If we want to instantiate Virtual Functions, then our
                 * parent bridge's PCI-E needs to support Alternative Routing
@@ -5569,9 +5568,8 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
                 * and above.
                 */
                pbridge = pdev->bus->self;
-               pos = pci_find_capability(pbridge, PCI_CAP_ID_EXP);
-               pci_read_config_word(pbridge, pos + PCI_EXP_FLAGS, &flags);
-               pci_read_config_dword(pbridge, pos + PCI_EXP_DEVCAP2, &devcap2);
+               pcie_capability_read_word(pbridge, PCI_EXP_FLAGS, &flags);
+               pcie_capability_read_dword(pbridge, PCI_EXP_DEVCAP2, &devcap2);
 
                if ((flags & PCI_EXP_FLAGS_VERS) < 2 ||
                    !(devcap2 & PCI_EXP_DEVCAP2_ARI)) {
index 312599c6b35a96a70ba301d5c17fa30174146f8e..e447976bdd3e06c3cc74f2538c3db1305bf4c503 100644 (file)
@@ -67,7 +67,8 @@ static struct ch_tc_pedit_fields pedits[] = {
 static struct ch_tc_flower_entry *allocate_flower_entry(void)
 {
        struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
-       spin_lock_init(&new->lock);
+       if (new)
+               spin_lock_init(&new->lock);
        return new;
 }
 
index 9dd5ed9a29654b03e371321f6b6ca4cc11c0bea8..f7fc553356f231dd7321431f11656a64bed6832b 100644 (file)
@@ -7309,7 +7309,6 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
        } else {
                unsigned int pack_align;
                unsigned int ingpad, ingpack;
-               unsigned int pcie_cap;
 
                /* T5 introduced the separation of the Free List Padding and
                 * Packing Boundaries.  Thus, we can select a smaller Padding
@@ -7334,8 +7333,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                 * multiple of the Maximum Payload Size.
                 */
                pack_align = fl_align;
-               pcie_cap = pci_find_capability(adap->pdev, PCI_CAP_ID_EXP);
-               if (pcie_cap) {
+               if (pci_is_pcie(adap->pdev)) {
                        unsigned int mps, mps_log;
                        u16 devctl;
 
@@ -7343,9 +7341,8 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                         * [bits 7:5] encodes sizes as powers of 2 starting at
                         * 128 bytes.
                         */
-                       pci_read_config_word(adap->pdev,
-                                            pcie_cap + PCI_EXP_DEVCTL,
-                                            &devctl);
+                       pcie_capability_read_word(adap->pdev, PCI_EXP_DEVCTL,
+                                                 &devctl);
                        mps_log = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5) + 7;
                        mps = 1 << mps_log;
                        if (mps > pack_align)
index ef5d61d57597d25de28e5ce613f9a378a9878a06..323976c811e96f74c5f834c0fa29ddf62ff9d0e7 100644 (file)
@@ -550,7 +550,7 @@ int be_process_mcc(struct be_adapter *adapter)
        int num = 0, status = 0;
        struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 
-       spin_lock(&adapter->mcc_cq_lock);
+       spin_lock_bh(&adapter->mcc_cq_lock);
 
        while ((compl = be_mcc_compl_get(adapter))) {
                if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
@@ -566,7 +566,7 @@ int be_process_mcc(struct be_adapter *adapter)
        if (num)
                be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
 
-       spin_unlock(&adapter->mcc_cq_lock);
+       spin_unlock_bh(&adapter->mcc_cq_lock);
        return status;
 }
 
@@ -581,9 +581,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
                if (be_check_error(adapter, BE_ERROR_ANY))
                        return -EIO;
 
-               local_bh_disable();
                status = be_process_mcc(adapter);
-               local_bh_enable();
 
                if (atomic_read(&mcc_obj->q.used) == 0)
                        break;
index b7a246b335990ac4cc2b6dc47d80bc7424e54a20..4d8e40ac66d23144ea8b6c864c264f9a1ee98d31 100644 (file)
@@ -4698,8 +4698,13 @@ int be_update_queues(struct be_adapter *adapter)
        int status;
 
        if (netif_running(netdev)) {
+               /* be_tx_timeout() must not run concurrently with this
+                * function, synchronize with an already-running dev_watchdog
+                */
+               netif_tx_lock_bh(netdev);
                /* device cannot transmit now, avoid dev_watchdog timeouts */
                netif_carrier_off(netdev);
+               netif_tx_unlock_bh(netdev);
 
                be_close(netdev);
        }
@@ -5625,9 +5630,7 @@ static void be_worker(struct work_struct *work)
         * mcc completions
         */
        if (!netif_running(adapter->netdev)) {
-               local_bh_disable();
                be_process_mcc(adapter);
-               local_bh_enable();
                goto reschedule;
        }
 
index 133acca0bf31b448ac0c3f51594dbaef65ed3704..092da2d90026fab2e455f0ba9831ad2788042a74 100644 (file)
@@ -167,7 +167,7 @@ struct nps_enet_priv {
 };
 
 /**
- * nps_reg_set - Sets ENET register with provided value.
+ * nps_enet_reg_set - Sets ENET register with provided value.
  * @priv:       Pointer to EZchip ENET private data structure.
  * @reg:        Register offset from base address.
  * @value:      Value to set in register.
@@ -179,7 +179,7 @@ static inline void nps_enet_reg_set(struct nps_enet_priv *priv,
 }
 
 /**
- * nps_reg_get - Gets value of specified ENET register.
+ * nps_enet_reg_get - Gets value of specified ENET register.
  * @priv:       Pointer to EZchip ENET private data structure.
  * @reg:        Register offset from base address.
  *
index ed0d010c7cf260f0e8cfb98f8935207bfdbc9114..04a59db03f2bc93073dc6e0d8a71024f33bd7b02 100644 (file)
@@ -2,6 +2,7 @@
 config FSL_ENETC
        tristate "ENETC PF driver"
        depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
+       select PHYLIB
        help
          This driver supports NXP ENETC gigabit ethernet controller PCIe
          physical function (PF) devices, managing ENETC Ports at a privileged
@@ -12,6 +13,7 @@ config FSL_ENETC
 config FSL_ENETC_VF
        tristate "ENETC VF driver"
        depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
+       select PHYLIB
        help
          This driver supports NXP ENETC gigabit ethernet controller PCIe
          virtual function (VF) devices enabled by the ENETC PF driver.
index 2fd2586e42bf3f6c799df24e520a1387af080292..bc594892507acb2f569975e338886288fbeff062 100644 (file)
@@ -82,7 +82,7 @@ static int enetc_ptp_probe(struct pci_dev *pdev,
        n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
        if (n != 1) {
                err = -EPERM;
-               goto err_irq;
+               goto err_irq_vectors;
        }
 
        ptp_qoriq->irq = pci_irq_vector(pdev, 0);
@@ -107,6 +107,8 @@ static int enetc_ptp_probe(struct pci_dev *pdev,
 err_no_clock:
        free_irq(ptp_qoriq->irq, ptp_qoriq);
 err_irq:
+       pci_free_irq_vectors(pdev);
+err_irq_vectors:
        iounmap(base);
 err_ioremap:
        kfree(ptp_qoriq);
@@ -125,6 +127,7 @@ static void enetc_ptp_remove(struct pci_dev *pdev)
 
        enetc_phc_index = -1;
        ptp_qoriq_free(ptp_qoriq);
+       pci_free_irq_vectors(pdev);
        kfree(ptp_qoriq);
 
        pci_release_mem_regions(pdev);
index e80fedb27cee81411019914f483590c7ec6c1871..210749bf1eac11537376244a7bd7b68740a5bba8 100644 (file)
@@ -2439,9 +2439,6 @@ MODULE_PARM_DESC(fsl_fm_rx_extra_headroom, "Extra headroom for Rx buffers");
  * buffers when not using jumbo frames.
  * Must be large enough to accommodate the network MTU, but small enough
  * to avoid wasting skb memory.
- *
- * Could be overridden once, at boot-time, via the
- * fm_set_max_frm() callback.
  */
 static int fsl_fm_max_frm = FSL_FM_MAX_FRAME_SIZE;
 module_param(fsl_fm_max_frm, int, 0);
index 92372dc43be877807849fda3b90869cb5b618880..ebc37e2569221a9c6425704f3dade054ab86c9f1 100644 (file)
@@ -31,9 +31,6 @@
 struct gve_rx_desc_queue {
        struct gve_rx_desc *desc_ring; /* the descriptor ring */
        dma_addr_t bus; /* the bus for the desc_ring */
-       u32 cnt; /* free-running total number of completed packets */
-       u32 fill_cnt; /* free-running total number of descriptors posted */
-       u32 mask; /* masks the cnt to the size of the ring */
        u8 seqno; /* the next expected seqno for this desc*/
 };
 
@@ -60,8 +57,6 @@ struct gve_rx_data_queue {
        dma_addr_t data_bus; /* dma mapping of the slots */
        struct gve_rx_slot_page_info *page_info; /* page info of the buffers */
        struct gve_queue_page_list *qpl; /* qpl assigned to this queue */
-       u32 mask; /* masks the cnt to the size of the ring */
-       u32 cnt; /* free-running total number of completed packets */
 };
 
 struct gve_priv;
@@ -73,6 +68,9 @@ struct gve_rx_ring {
        struct gve_rx_data_queue data;
        u64 rbytes; /* free-running bytes received */
        u64 rpackets; /* free-running packets received */
+       u32 cnt; /* free-running total number of completed packets */
+       u32 fill_cnt; /* free-running total number of descs and buffs posted */
+       u32 mask; /* masks the cnt and fill_cnt to the size of the ring */
        u32 q_num; /* queue index */
        u32 ntfy_id; /* notification block index */
        struct gve_queue_resources *q_resources; /* head and tail pointer idx */
index 26540b8565410d558050177bec051305a4cc6891..d8fa816f44737ceed90cd731d46488dfb0ceb72a 100644 (file)
@@ -138,8 +138,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
                for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
                        struct gve_rx_ring *rx = &priv->rx[ring];
 
-                       data[i++] = rx->desc.cnt;
-                       data[i++] = rx->desc.fill_cnt;
+                       data[i++] = rx->cnt;
+                       data[i++] = rx->fill_cnt;
                }
        } else {
                i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
index 49729875238123cdc88b20e3feabe291dd89dcfd..aca95f64bde80b50642ea2e3066111dcb6745a09 100644 (file)
@@ -50,7 +50,7 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
                                  u64_stats_fetch_begin(&priv->tx[ring].statss);
                                s->tx_packets += priv->tx[ring].pkt_done;
                                s->tx_bytes += priv->tx[ring].bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                       } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
                                                       start));
                }
        }
index 1914b8350da7022434fcd70e6316bc0010bda24e..59564ac99d2a6df5c589d89521b5513f78ae16fc 100644 (file)
@@ -37,7 +37,7 @@ static void gve_rx_free_ring(struct gve_priv *priv, int idx)
        rx->data.qpl = NULL;
        kvfree(rx->data.page_info);
 
-       slots = rx->data.mask + 1;
+       slots = rx->mask + 1;
        bytes = sizeof(*rx->data.data_ring) * slots;
        dma_free_coherent(dev, bytes, rx->data.data_ring,
                          rx->data.data_bus);
@@ -64,7 +64,7 @@ static int gve_prefill_rx_pages(struct gve_rx_ring *rx)
        /* Allocate one page per Rx queue slot. Each page is split into two
         * packet buffers, when possible we "page flip" between the two.
         */
-       slots = rx->data.mask + 1;
+       slots = rx->mask + 1;
 
        rx->data.page_info = kvzalloc(slots *
                                      sizeof(*rx->data.page_info), GFP_KERNEL);
@@ -111,7 +111,7 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
        rx->q_num = idx;
 
        slots = priv->rx_pages_per_qpl;
-       rx->data.mask = slots - 1;
+       rx->mask = slots - 1;
 
        /* alloc rx data ring */
        bytes = sizeof(*rx->data.data_ring) * slots;
@@ -125,7 +125,7 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
                err = -ENOMEM;
                goto abort_with_slots;
        }
-       rx->desc.fill_cnt = filled_pages;
+       rx->fill_cnt = filled_pages;
        /* Ensure data ring slots (packet buffers) are visible. */
        dma_wmb();
 
@@ -156,8 +156,8 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
                err = -ENOMEM;
                goto abort_with_q_resources;
        }
-       rx->desc.mask = slots - 1;
-       rx->desc.cnt = 0;
+       rx->mask = slots - 1;
+       rx->cnt = 0;
        rx->desc.seqno = 1;
        gve_rx_add_to_block(priv, idx);
 
@@ -213,7 +213,7 @@ void gve_rx_write_doorbell(struct gve_priv *priv, struct gve_rx_ring *rx)
 {
        u32 db_idx = be32_to_cpu(rx->q_resources->db_index);
 
-       iowrite32be(rx->desc.fill_cnt, &priv->db_bar2[db_idx]);
+       iowrite32be(rx->fill_cnt, &priv->db_bar2[db_idx]);
 }
 
 static enum pkt_hash_types gve_rss_type(__be16 pkt_flags)
@@ -273,7 +273,7 @@ static void gve_rx_flip_buff(struct gve_rx_slot_page_info *page_info,
 }
 
 static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
-                  netdev_features_t feat)
+                  netdev_features_t feat, u32 idx)
 {
        struct gve_rx_slot_page_info *page_info;
        struct gve_priv *priv = rx->gve;
@@ -282,14 +282,12 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
        struct sk_buff *skb;
        int pagecount;
        u16 len;
-       u32 idx;
 
        /* drop this packet */
        if (unlikely(rx_desc->flags_seq & GVE_RXF_ERR))
                return true;
 
        len = be16_to_cpu(rx_desc->len) - GVE_RX_PAD;
-       idx = rx->data.cnt & rx->data.mask;
        page_info = &rx->data.page_info[idx];
 
        /* gvnic can only receive into registered segments. If the buffer
@@ -340,8 +338,6 @@ have_skb:
        if (!skb)
                return true;
 
-       rx->data.cnt++;
-
        if (likely(feat & NETIF_F_RXCSUM)) {
                /* NIC passes up the partial sum */
                if (rx_desc->csum)
@@ -370,7 +366,7 @@ static bool gve_rx_work_pending(struct gve_rx_ring *rx)
        __be16 flags_seq;
        u32 next_idx;
 
-       next_idx = rx->desc.cnt & rx->desc.mask;
+       next_idx = rx->cnt & rx->mask;
        desc = rx->desc.desc_ring + next_idx;
 
        flags_seq = desc->flags_seq;
@@ -385,8 +381,8 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
 {
        struct gve_priv *priv = rx->gve;
        struct gve_rx_desc *desc;
-       u32 cnt = rx->desc.cnt;
-       u32 idx = cnt & rx->desc.mask;
+       u32 cnt = rx->cnt;
+       u32 idx = cnt & rx->mask;
        u32 work_done = 0;
        u64 bytes = 0;
 
@@ -401,10 +397,10 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
                           rx->q_num, GVE_SEQNO(desc->flags_seq),
                           rx->desc.seqno);
                bytes += be16_to_cpu(desc->len) - GVE_RX_PAD;
-               if (!gve_rx(rx, desc, feat))
+               if (!gve_rx(rx, desc, feat, idx))
                        gve_schedule_reset(priv);
                cnt++;
-               idx = cnt & rx->desc.mask;
+               idx = cnt & rx->mask;
                desc = rx->desc.desc_ring + idx;
                rx->desc.seqno = gve_next_seqno(rx->desc.seqno);
                work_done++;
@@ -417,8 +413,8 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
        rx->rpackets += work_done;
        rx->rbytes += bytes;
        u64_stats_update_end(&rx->statss);
-       rx->desc.cnt = cnt;
-       rx->desc.fill_cnt += work_done;
+       rx->cnt = cnt;
+       rx->fill_cnt += work_done;
 
        /* restock desc ring slots */
        dma_wmb();      /* Ensure descs are visible before ringing doorbell */
index d60452845539f3acbd42cdfebc94865bf2f61e02..c84167447abe650c36186eae40343b2584ac4fbb 100644 (file)
@@ -220,6 +220,7 @@ struct hip04_priv {
        unsigned int reg_inten;
 
        struct napi_struct napi;
+       struct device *dev;
        struct net_device *ndev;
 
        struct tx_desc *tx_desc;
@@ -248,7 +249,7 @@ struct hip04_priv {
 
 static inline unsigned int tx_count(unsigned int head, unsigned int tail)
 {
-       return (head - tail) % (TX_DESC_NUM - 1);
+       return (head - tail) % TX_DESC_NUM;
 }
 
 static void hip04_config_port(struct net_device *ndev, u32 speed, u32 duplex)
@@ -465,7 +466,7 @@ static int hip04_tx_reclaim(struct net_device *ndev, bool force)
                }
 
                if (priv->tx_phys[tx_tail]) {
-                       dma_unmap_single(&ndev->dev, priv->tx_phys[tx_tail],
+                       dma_unmap_single(priv->dev, priv->tx_phys[tx_tail],
                                         priv->tx_skb[tx_tail]->len,
                                         DMA_TO_DEVICE);
                        priv->tx_phys[tx_tail] = 0;
@@ -516,8 +517,8 @@ hip04_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                return NETDEV_TX_BUSY;
        }
 
-       phys = dma_map_single(&ndev->dev, skb->data, skb->len, DMA_TO_DEVICE);
-       if (dma_mapping_error(&ndev->dev, phys)) {
+       phys = dma_map_single(priv->dev, skb->data, skb->len, DMA_TO_DEVICE);
+       if (dma_mapping_error(priv->dev, phys)) {
                dev_kfree_skb(skb);
                return NETDEV_TX_OK;
        }
@@ -585,6 +586,9 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
        u16 len;
        u32 err;
 
+       /* clean up tx descriptors */
+       tx_remaining = hip04_tx_reclaim(ndev, false);
+
        while (cnt && !last) {
                buf = priv->rx_buf[priv->rx_head];
                skb = build_skb(buf, priv->rx_buf_size);
@@ -593,7 +597,7 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
                        goto refill;
                }
 
-               dma_unmap_single(&ndev->dev, priv->rx_phys[priv->rx_head],
+               dma_unmap_single(priv->dev, priv->rx_phys[priv->rx_head],
                                 RX_BUF_SIZE, DMA_FROM_DEVICE);
                priv->rx_phys[priv->rx_head] = 0;
 
@@ -622,9 +626,9 @@ refill:
                buf = netdev_alloc_frag(priv->rx_buf_size);
                if (!buf)
                        goto done;
-               phys = dma_map_single(&ndev->dev, buf,
+               phys = dma_map_single(priv->dev, buf,
                                      RX_BUF_SIZE, DMA_FROM_DEVICE);
-               if (dma_mapping_error(&ndev->dev, phys))
+               if (dma_mapping_error(priv->dev, phys))
                        goto done;
                priv->rx_buf[priv->rx_head] = buf;
                priv->rx_phys[priv->rx_head] = phys;
@@ -645,8 +649,7 @@ refill:
        }
        napi_complete_done(napi, rx);
 done:
-       /* clean up tx descriptors and start a new timer if necessary */
-       tx_remaining = hip04_tx_reclaim(ndev, false);
+       /* start a new timer if necessary */
        if (rx < budget && tx_remaining)
                hip04_start_tx_timer(priv);
 
@@ -728,9 +731,9 @@ static int hip04_mac_open(struct net_device *ndev)
        for (i = 0; i < RX_DESC_NUM; i++) {
                dma_addr_t phys;
 
-               phys = dma_map_single(&ndev->dev, priv->rx_buf[i],
+               phys = dma_map_single(priv->dev, priv->rx_buf[i],
                                      RX_BUF_SIZE, DMA_FROM_DEVICE);
-               if (dma_mapping_error(&ndev->dev, phys))
+               if (dma_mapping_error(priv->dev, phys))
                        return -EIO;
 
                priv->rx_phys[i] = phys;
@@ -764,7 +767,7 @@ static int hip04_mac_stop(struct net_device *ndev)
 
        for (i = 0; i < RX_DESC_NUM; i++) {
                if (priv->rx_phys[i]) {
-                       dma_unmap_single(&ndev->dev, priv->rx_phys[i],
+                       dma_unmap_single(priv->dev, priv->rx_phys[i],
                                         RX_BUF_SIZE, DMA_FROM_DEVICE);
                        priv->rx_phys[i] = 0;
                }
@@ -907,6 +910,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        priv = netdev_priv(ndev);
+       priv->dev = d;
        priv->ndev = ndev;
        platform_set_drvdata(pdev, ndev);
        SET_NETDEV_DEV(ndev, &pdev->dev);
index 8ad5292eebbe0343e13d86d01dee619aedd138e0..75329ab775a61efa04f4aca2952ebed56c8ec495 100644 (file)
@@ -43,7 +43,7 @@ enum HCLGE_MBX_OPCODE {
        HCLGE_MBX_GET_QID_IN_PF,        /* (VF -> PF) get queue id in pf */
        HCLGE_MBX_LINK_STAT_MODE,       /* (PF -> VF) link mode has changed */
        HCLGE_MBX_GET_LINK_MODE,        /* (VF -> PF) get the link mode of pf */
-       HLCGE_MBX_PUSH_VLAN_INFO,       /* (PF -> VF) push port base vlan */
+       HCLGE_MBX_PUSH_VLAN_INFO,       /* (PF -> VF) push port base vlan */
        HCLGE_MBX_GET_MEDIA_TYPE,       /* (VF -> PF) get media type */
 
        HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
index 0a7243825e7bae6d52f0b441e3174eeed61968f8..85a3b062371df881d7184e1733803e59c58259f2 100644 (file)
@@ -98,7 +98,7 @@ static const struct hclge_hw_error hclge_igu_egu_tnl_int[] = {
          .reset_level = HNAE3_GLOBAL_RESET },
        { .int_msk = BIT(1), .msg = "rx_stp_fifo_overflow",
          .reset_level = HNAE3_GLOBAL_RESET },
-       { .int_msk = BIT(2), .msg = "rx_stp_fifo_undeflow",
+       { .int_msk = BIT(2), .msg = "rx_stp_fifo_underflow",
          .reset_level = HNAE3_GLOBAL_RESET },
        { .int_msk = BIT(3), .msg = "tx_buf_overflow",
          .reset_level = HNAE3_GLOBAL_RESET },
index a38ac7cfe16b053ce7a84389f01e91be7f615df9..690b9990215caf7aa3adf72b65a1d8b248c9a7f6 100644 (file)
@@ -304,7 +304,7 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
        memcpy(&msg_data[6], &vlan_tag, sizeof(u16));
 
        return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
-                                 HLCGE_MBX_PUSH_VLAN_INFO, vfid);
+                                 HCLGE_MBX_PUSH_VLAN_INFO, vfid);
 }
 
 static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
index f60b80bd605e5ad9ca8ab4e6827bd25a1f62474d..6a96987bd8f0018e0f5f9f88bb680601effd1678 100644 (file)
@@ -204,7 +204,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
                case HCLGE_MBX_LINK_STAT_CHANGE:
                case HCLGE_MBX_ASSERTING_RESET:
                case HCLGE_MBX_LINK_STAT_MODE:
-               case HLCGE_MBX_PUSH_VLAN_INFO:
+               case HCLGE_MBX_PUSH_VLAN_INFO:
                        /* set this mbx event as pending. This is required as we
                         * might loose interrupt event when mbx task is busy
                         * handling. This shall be cleared when mbx task just
@@ -307,7 +307,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
                        hclgevf_reset_task_schedule(hdev);
 
                        break;
-               case HLCGE_MBX_PUSH_VLAN_INFO:
+               case HCLGE_MBX_PUSH_VLAN_INFO:
                        state = le16_to_cpu(msg_q[1]);
                        vlan_info = &msg_q[1];
                        hclgevf_update_port_base_vlan_info(hdev, state,
index 4138a84803478a5b0b3ad9c7adce1e0e51f28cb3..cca71ba7a74a02b72d3c188368d6197278864243 100644 (file)
@@ -3251,7 +3251,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,
        switch (action) {
        case MEM_CANCEL_OFFLINE:
                pr_info("memory offlining canceled");
-               /* Fall through: re-add canceled memory block */
+               /* Fall through - re-add canceled memory block */
 
        case MEM_ONLINE:
                pr_info("memory is going online");
index d654c234aaf75364416d3a1eadfa4fb8fa6924ba..c5be4ebd84373ec9ff8ade34b4bae3031e937652 100644 (file)
@@ -1605,7 +1605,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
        struct net_device *netdev;
        struct ibmveth_adapter *adapter;
        unsigned char *mac_addr_p;
-       unsigned int *mcastFilterSize_p;
+       __be32 *mcastFilterSize_p;
        long ret;
        unsigned long ret_attr;
 
@@ -1627,8 +1627,9 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
                return -EINVAL;
        }
 
-       mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev,
-                                               VETH_MCAST_FILTER_SIZE, NULL);
+       mcastFilterSize_p = (__be32 *)vio_get_attribute(dev,
+                                                       VETH_MCAST_FILTER_SIZE,
+                                                       NULL);
        if (!mcastFilterSize_p) {
                dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE "
                        "attribute\n");
@@ -1645,7 +1646,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 
        adapter->vdev = dev;
        adapter->netdev = netdev;
-       adapter->mcastFilterSize = *mcastFilterSize_p;
+       adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p);
        adapter->pool_config = 0;
 
        netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
index 3da6800732656477bd5d932373dde23d1b4dde9c..5cb55ea671e3535ba1e23099f2b722a18f91b2af 100644 (file)
@@ -1568,6 +1568,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
                lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num],
                                               (u64)tx_buff->indir_dma,
                                               (u64)num_entries);
+               dma_unmap_single(dev, tx_buff->indir_dma,
+                                sizeof(tx_buff->indir_arr), DMA_TO_DEVICE);
        } else {
                tx_buff->num_entries = num_entries;
                lpar_rc = send_subcrq(adapter, handle_array[queue_num],
@@ -1981,6 +1983,13 @@ static void __ibmvnic_reset(struct work_struct *work)
 
        rwi = get_next_rwi(adapter);
        while (rwi) {
+               if (adapter->state == VNIC_REMOVING ||
+                   adapter->state == VNIC_REMOVED) {
+                       kfree(rwi);
+                       rc = EBUSY;
+                       break;
+               }
+
                if (adapter->force_reset_recovery) {
                        adapter->force_reset_recovery = false;
                        rc = do_hard_reset(adapter, rwi, reset_state);
@@ -2788,7 +2797,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
        union sub_crq *next;
        int index;
        int i, j;
-       u8 *first;
 
 restart_loop:
        while (pending_scrq(adapter, scrq)) {
@@ -2818,14 +2826,6 @@ restart_loop:
 
                                txbuff->data_dma[j] = 0;
                        }
-                       /* if sub_crq was sent indirectly */
-                       first = &txbuff->indir_arr[0].generic.first;
-                       if (*first == IBMVNIC_CRQ_CMD) {
-                               dma_unmap_single(dev, txbuff->indir_dma,
-                                                sizeof(txbuff->indir_arr),
-                                                DMA_TO_DEVICE);
-                               *first = 0;
-                       }
 
                        if (txbuff->last_frag) {
                                dev_kfree_skb_any(txbuff->skb);
index 93f3b4e6185b7e87626dfb6f1e4f86b6811f1789..aa9323e55406e323367dc1777fbd51ea6221678a 100644 (file)
@@ -3912,13 +3912,11 @@ void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value)
 s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value)
 {
        struct igc_adapter *adapter = hw->back;
-       u16 cap_offset;
 
-       cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
-       if (!cap_offset)
+       if (!pci_is_pcie(adapter->pdev))
                return -IGC_ERR_CONFIG;
 
-       pci_read_config_word(adapter->pdev, cap_offset + reg, value);
+       pcie_capability_read_word(adapter->pdev, reg, value);
 
        return IGC_SUCCESS;
 }
@@ -3926,13 +3924,11 @@ s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value)
 s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value)
 {
        struct igc_adapter *adapter = hw->back;
-       u16 cap_offset;
 
-       cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
-       if (!cap_offset)
+       if (!pci_is_pcie(adapter->pdev))
                return -IGC_ERR_CONFIG;
 
-       pci_write_config_word(adapter->pdev, cap_offset + reg, *value);
+       pcie_capability_write_word(adapter->pdev, reg, *value);
 
        return IGC_SUCCESS;
 }
index cbaf712d6529bf0e1d20289c8d0d4a0466b79623..51c696b6bf644d2a902cd0de495bdb792c23e6e0 100644 (file)
@@ -36,6 +36,7 @@
 #include <net/vxlan.h>
 #include <net/mpls.h>
 #include <net/xdp_sock.h>
+#include <net/xfrm.h>
 
 #include "ixgbe.h"
 #include "ixgbe_common.h"
@@ -2621,7 +2622,7 @@ adjust_by_size:
                /* 16K ints/sec to 9.2K ints/sec */
                avg_wire_size *= 15;
                avg_wire_size += 11452;
-       } else if (avg_wire_size <= 1980) {
+       } else if (avg_wire_size < 1968) {
                /* 9.2K ints/sec to 8K ints/sec */
                avg_wire_size *= 5;
                avg_wire_size += 22420;
@@ -2654,6 +2655,8 @@ adjust_by_size:
        case IXGBE_LINK_SPEED_2_5GB_FULL:
        case IXGBE_LINK_SPEED_1GB_FULL:
        case IXGBE_LINK_SPEED_10_FULL:
+               if (avg_wire_size > 8064)
+                       avg_wire_size = 8064;
                itr += DIV_ROUND_UP(avg_wire_size,
                                    IXGBE_ITR_ADAPTIVE_MIN_INC * 64) *
                       IXGBE_ITR_ADAPTIVE_MIN_INC;
@@ -7897,11 +7900,8 @@ static void ixgbe_service_task(struct work_struct *work)
                return;
        }
        if (ixgbe_check_fw_error(adapter)) {
-               if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
-                       rtnl_lock();
+               if (!test_bit(__IXGBE_DOWN, &adapter->state))
                        unregister_netdev(adapter->netdev);
-                       rtnl_unlock();
-               }
                ixgbe_service_event_complete(adapter);
                return;
        }
@@ -8698,7 +8698,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 #endif /* IXGBE_FCOE */
 
 #ifdef CONFIG_IXGBE_IPSEC
-       if (secpath_exists(skb) &&
+       if (xfrm_offload(skb) &&
            !ixgbe_ipsec_tx(tx_ring, first, &ipsec_tx))
                goto out_drop;
 #endif
index 6b609553329fa98647b78f4e1e5d3e9223a8aa7a..a3b6d8c89127f1a2fcfdfb84a1824dbbedc019e6 100644 (file)
@@ -633,19 +633,17 @@ static void ixgbe_clean_xdp_tx_buffer(struct ixgbe_ring *tx_ring,
 bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
                            struct ixgbe_ring *tx_ring, int napi_budget)
 {
+       u16 ntc = tx_ring->next_to_clean, ntu = tx_ring->next_to_use;
        unsigned int total_packets = 0, total_bytes = 0;
-       u32 i = tx_ring->next_to_clean, xsk_frames = 0;
-       unsigned int budget = q_vector->tx.work_limit;
        struct xdp_umem *umem = tx_ring->xsk_umem;
        union ixgbe_adv_tx_desc *tx_desc;
        struct ixgbe_tx_buffer *tx_bi;
-       bool xmit_done;
+       u32 xsk_frames = 0;
 
-       tx_bi = &tx_ring->tx_buffer_info[i];
-       tx_desc = IXGBE_TX_DESC(tx_ring, i);
-       i -= tx_ring->count;
+       tx_bi = &tx_ring->tx_buffer_info[ntc];
+       tx_desc = IXGBE_TX_DESC(tx_ring, ntc);
 
-       do {
+       while (ntc != ntu) {
                if (!(tx_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)))
                        break;
 
@@ -661,22 +659,18 @@ bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
 
                tx_bi++;
                tx_desc++;
-               i++;
-               if (unlikely(!i)) {
-                       i -= tx_ring->count;
+               ntc++;
+               if (unlikely(ntc == tx_ring->count)) {
+                       ntc = 0;
                        tx_bi = tx_ring->tx_buffer_info;
                        tx_desc = IXGBE_TX_DESC(tx_ring, 0);
                }
 
                /* issue prefetch for next Tx descriptor */
                prefetch(tx_desc);
+       }
 
-               /* update budget accounting */
-               budget--;
-       } while (likely(budget));
-
-       i += tx_ring->count;
-       tx_ring->next_to_clean = i;
+       tx_ring->next_to_clean = ntc;
 
        u64_stats_update_begin(&tx_ring->syncp);
        tx_ring->stats.bytes += total_bytes;
@@ -688,8 +682,7 @@ bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
        if (xsk_frames)
                xsk_umem_complete_tx(umem, xsk_frames);
 
-       xmit_done = ixgbe_xmit_zc(tx_ring, q_vector->tx.work_limit);
-       return budget > 0 && xmit_done;
+       return ixgbe_xmit_zc(tx_ring, q_vector->tx.work_limit);
 }
 
 int ixgbe_xsk_async_xmit(struct net_device *dev, u32 qid)
index d2b41f9f87f80513a793eafe5e65899464488a9c..72872d6ca80c4992bfe2594bfdd273385a3b331c 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/bpf.h>
 #include <linux/bpf_trace.h>
 #include <linux/atomic.h>
+#include <net/xfrm.h>
 
 #include "ixgbevf.h"
 
@@ -4161,7 +4162,7 @@ static int ixgbevf_xmit_frame_ring(struct sk_buff *skb,
        first->protocol = vlan_get_protocol(skb);
 
 #ifdef CONFIG_IXGBEVF_IPSEC
-       if (secpath_exists(skb) && !ixgbevf_ipsec_tx(tx_ring, first, &ipsec_tx))
+       if (xfrm_offload(skb) && !ixgbevf_ipsec_tx(tx_ring, first, &ipsec_tx))
                goto out_drop;
 #endif
        tso = ixgbevf_tso(tx_ring, first, &hdr_len, &ipsec_tx);
index f660cc2b82583fdc6d20cd1e0761dc71b294603b..0b9e851f3da4fb1a37989e1aed311a5ad282353f 100644 (file)
@@ -319,20 +319,33 @@ static int orion_mdio_probe(struct platform_device *pdev)
 
        init_waitqueue_head(&dev->smi_busy_wait);
 
-       for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
-               dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
-               if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
+       if (pdev->dev.of_node) {
+               for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+                       dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
+                       if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
+                               ret = -EPROBE_DEFER;
+                               goto out_clk;
+                       }
+                       if (IS_ERR(dev->clk[i]))
+                               break;
+                       clk_prepare_enable(dev->clk[i]);
+               }
+
+               if (!IS_ERR(of_clk_get(pdev->dev.of_node,
+                                      ARRAY_SIZE(dev->clk))))
+                       dev_warn(&pdev->dev,
+                                "unsupported number of clocks, limiting to the first "
+                                __stringify(ARRAY_SIZE(dev->clk)) "\n");
+       } else {
+               dev->clk[0] = clk_get(&pdev->dev, NULL);
+               if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) {
                        ret = -EPROBE_DEFER;
                        goto out_clk;
                }
-               if (IS_ERR(dev->clk[i]))
-                       break;
-               clk_prepare_enable(dev->clk[i]);
+               if (!IS_ERR(dev->clk[0]))
+                       clk_prepare_enable(dev->clk[0]);
        }
 
-       if (!IS_ERR(of_clk_get(pdev->dev.of_node, ARRAY_SIZE(dev->clk))))
-               dev_warn(&pdev->dev, "unsupported number of clocks, limiting to the first "
-                        __stringify(ARRAY_SIZE(dev->clk)) "\n");
 
        dev->err_interrupt = platform_get_irq(pdev, 0);
        if (dev->err_interrupt > 0 &&
index c51f1d5b550b1131d18fc7240e5503d461c43f4f..ccdd47f3b8fb5dbf474e2086711b2569f62a46bd 100644 (file)
@@ -811,6 +811,26 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
        return 0;
 }
 
+static void mvpp2_set_hw_csum(struct mvpp2_port *port,
+                             enum mvpp2_bm_pool_log_num new_long_pool)
+{
+       const netdev_features_t csums = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+       /* Update L4 checksum when jumbo enable/disable on port.
+        * Only port 0 supports hardware checksum offload due to
+        * the Tx FIFO size limitation.
+        * Also, don't set NETIF_F_HW_CSUM because L3_offset in TX descriptor
+        * has 7 bits, so the maximum L3 offset is 128.
+        */
+       if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
+               port->dev->features &= ~csums;
+               port->dev->hw_features &= ~csums;
+       } else {
+               port->dev->features |= csums;
+               port->dev->hw_features |= csums;
+       }
+}
+
 static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
 {
        struct mvpp2_port *port = netdev_priv(dev);
@@ -843,15 +863,7 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
                /* Add port to new short & long pool */
                mvpp2_swf_bm_pool_init(port);
 
-               /* Update L4 checksum when jumbo enable/disable on port */
-               if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
-                       dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-                       dev->hw_features &= ~(NETIF_F_IP_CSUM |
-                                             NETIF_F_IPV6_CSUM);
-               } else {
-                       dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-                       dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-               }
+               mvpp2_set_hw_csum(port, new_long_pool);
        }
 
        dev->mtu = mtu;
@@ -3700,6 +3712,7 @@ static int mvpp2_set_mac_address(struct net_device *dev, void *p)
 static int mvpp2_change_mtu(struct net_device *dev, int mtu)
 {
        struct mvpp2_port *port = netdev_priv(dev);
+       bool running = netif_running(dev);
        int err;
 
        if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
@@ -3708,40 +3721,24 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu)
                mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
        }
 
-       if (!netif_running(dev)) {
-               err = mvpp2_bm_update_mtu(dev, mtu);
-               if (!err) {
-                       port->pkt_size =  MVPP2_RX_PKT_SIZE(mtu);
-                       return 0;
-               }
-
-               /* Reconfigure BM to the original MTU */
-               err = mvpp2_bm_update_mtu(dev, dev->mtu);
-               if (err)
-                       goto log_error;
-       }
-
-       mvpp2_stop_dev(port);
+       if (running)
+               mvpp2_stop_dev(port);
 
        err = mvpp2_bm_update_mtu(dev, mtu);
-       if (!err) {
+       if (err) {
+               netdev_err(dev, "failed to change MTU\n");
+               /* Reconfigure BM to the original MTU */
+               mvpp2_bm_update_mtu(dev, dev->mtu);
+       } else {
                port->pkt_size =  MVPP2_RX_PKT_SIZE(mtu);
-               goto out_start;
        }
 
-       /* Reconfigure BM to the original MTU */
-       err = mvpp2_bm_update_mtu(dev, dev->mtu);
-       if (err)
-               goto log_error;
-
-out_start:
-       mvpp2_start_dev(port);
-       mvpp2_egress_enable(port);
-       mvpp2_ingress_enable(port);
+       if (running) {
+               mvpp2_start_dev(port);
+               mvpp2_egress_enable(port);
+               mvpp2_ingress_enable(port);
+       }
 
-       return 0;
-log_error:
-       netdev_err(dev, "failed to change MTU\n");
        return err;
 }
 
@@ -4739,9 +4736,9 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode,
        else
                ctrl0 &= ~MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
 
-       ctrl4 &= ~MVPP22_XLG_CTRL4_MACMODSELECT_GMAC;
-       ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC |
-                MVPP22_XLG_CTRL4_EN_IDLE_CHECK;
+       ctrl4 &= ~(MVPP22_XLG_CTRL4_MACMODSELECT_GMAC |
+                  MVPP22_XLG_CTRL4_EN_IDLE_CHECK);
+       ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC;
 
        if (old_ctrl0 != ctrl0)
                writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG);
@@ -5208,10 +5205,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
                dev->features |= NETIF_F_NTUPLE;
        }
 
-       if (port->pool_long->id == MVPP2_BM_JUMBO && port->id != 0) {
-               dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-               dev->hw_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-       }
+       mvpp2_set_hw_csum(port, port->pool_long->id);
 
        dev->vlan_features |= features;
        dev->gso_max_segs = MVPP2_MAX_TSO_SEGS;
@@ -5759,9 +5753,6 @@ static int mvpp2_remove(struct platform_device *pdev)
 
        mvpp2_dbgfs_cleanup(priv);
 
-       flush_workqueue(priv->stats_queue);
-       destroy_workqueue(priv->stats_queue);
-
        fwnode_for_each_available_child_node(fwnode, port_fwnode) {
                if (priv->port_list[i]) {
                        mutex_destroy(&priv->port_list[i]->gather_stats_lock);
@@ -5770,6 +5761,8 @@ static int mvpp2_remove(struct platform_device *pdev)
                i++;
        }
 
+       destroy_workqueue(priv->stats_queue);
+
        for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
                struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
 
index f518312ffe695470bf1dd4239d9e2b1b08e5ea54..e0363870f3a55c2bb784a55e9d3ef1aafcf89e4a 100644 (file)
@@ -4924,6 +4924,20 @@ static const struct dmi_system_id msi_blacklist[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
                },
        },
+       {
+               .ident = "ASUS P6T",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "P6T"),
+               },
+       },
+       {
+               .ident = "ASUS P6X",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "P6X"),
+               },
+       },
        {}
 };
 
index 263cd0909fe0de39eb6d48c39e194f904b39b846..1f7fff81f24dbb96a964326ae0a306315198afa2 100644 (file)
@@ -9,7 +9,6 @@ if NET_VENDOR_MEDIATEK
 
 config NET_MEDIATEK_SOC
        tristate "MediaTek SoC Gigabit Ethernet support"
-       depends on NET_VENDOR_MEDIATEK
        select PHYLIB
        ---help---
          This driver supports the gigabit ethernet MACs in the
index 6c01314e87b09716ca076cbe4a91621b9e474fba..db3552f2d0877e37ce8dcf215d4c273e91c2326c 100644 (file)
@@ -1187,7 +1187,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
        err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, rss_map->indir_qp);
        if (err) {
                en_err(priv, "Failed to allocate RSS indirection QP\n");
-               goto rss_err;
+               goto qp_alloc_err;
        }
 
        rss_map->indir_qp->event = mlx4_en_sqp_event;
@@ -1241,6 +1241,7 @@ indir_err:
                       MLX4_QP_STATE_RST, NULL, 0, 0, rss_map->indir_qp);
        mlx4_qp_remove(mdev->dev, rss_map->indir_qp);
        mlx4_qp_free(mdev->dev, rss_map->indir_qp);
+qp_alloc_err:
        kfree(rss_map->indir_qp);
        rss_map->indir_qp = NULL;
 rss_err:
index 1f6e16d5ea6be56b5cc663ec1f480e827ece7ae9..309470ec02190471476744602f98be74ab02f57b 100644 (file)
@@ -2240,7 +2240,7 @@ static int mlx4_validate_optimized_steering(struct mlx4_dev *dev)
        for (i = 1; i <= dev->caps.num_ports; i++) {
                if (mlx4_dev_port(dev, i, &port_cap)) {
                        mlx4_err(dev,
-                                "QUERY_DEV_CAP command failed, can't veify DMFS high rate steering.\n");
+                                "QUERY_DEV_CAP command failed, can't verify DMFS high rate steering.\n");
                } else if ((dev->caps.dmfs_high_steer_mode !=
                            MLX4_STEERING_DMFS_A0_DEFAULT) &&
                           (port_cap.dmfs_optimized_state ==
index 5bb6a26ea2672ea3ce25a8ddd6750be2ecb7733a..50862275544e52cd0610831694f8c415e1da8ed0 100644 (file)
@@ -213,7 +213,7 @@ void mlx5_unregister_device(struct mlx5_core_dev *dev)
        struct mlx5_interface *intf;
 
        mutex_lock(&mlx5_intf_mutex);
-       list_for_each_entry(intf, &intf_list, list)
+       list_for_each_entry_reverse(intf, &intf_list, list)
                mlx5_remove_device(intf, priv);
        list_del(&priv->dev_list);
        mutex_unlock(&mlx5_intf_mutex);
index 79d93d6c7d7a7fc2175d53052108a411bd3960c6..65bec19a438f15c5db9f0e0d28bd3ac53a7a0c83 100644 (file)
@@ -159,7 +159,7 @@ do {                                                            \
 enum mlx5e_rq_group {
        MLX5E_RQ_GROUP_REGULAR,
        MLX5E_RQ_GROUP_XSK,
-       MLX5E_NUM_RQ_GROUPS /* Keep last. */
+#define MLX5E_NUM_RQ_GROUPS(g) (1 + MLX5E_RQ_GROUP_##g)
 };
 
 static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size)
@@ -182,18 +182,15 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
                min_t(int, mlx5_comp_vectors_count(mdev), MLX5E_MAX_NUM_CHANNELS);
 }
 
-/* Use this function to get max num channels after netdev was created */
-static inline int mlx5e_get_netdev_max_channels(struct net_device *netdev)
-{
-       return min_t(unsigned int,
-                    netdev->num_rx_queues / MLX5E_NUM_RQ_GROUPS,
-                    netdev->num_tx_queues);
-}
-
 struct mlx5e_tx_wqe {
        struct mlx5_wqe_ctrl_seg ctrl;
-       struct mlx5_wqe_eth_seg  eth;
-       struct mlx5_wqe_data_seg data[0];
+       union {
+               struct {
+                       struct mlx5_wqe_eth_seg  eth;
+                       struct mlx5_wqe_data_seg data[0];
+               };
+               u8 tls_progress_params_ctx[0];
+       };
 };
 
 struct mlx5e_rx_wqe_ll {
@@ -830,6 +827,7 @@ struct mlx5e_priv {
        struct net_device         *netdev;
        struct mlx5e_stats         stats;
        struct mlx5e_channel_stats channel_stats[MLX5E_MAX_NUM_CHANNELS];
+       u16                        max_nch;
        u8                         max_opened_tc;
        struct hwtstamp_config     tstamp;
        u16                        q_counter;
@@ -871,6 +869,7 @@ struct mlx5e_profile {
                mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe;
        } rx_handlers;
        int     max_tc;
+       u8      rq_groups;
 };
 
 void mlx5e_build_ptys2ethtool_map(void);
@@ -1106,6 +1105,8 @@ u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv);
 u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv);
 int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
                              struct ethtool_ts_info *info);
+int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
+                              struct ethtool_flash *flash);
 void mlx5e_ethtool_get_pauseparam(struct mlx5e_priv *priv,
                                  struct ethtool_pauseparam *pauseparam);
 int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
index bd882b5ee9a746f7a6ccca891835b167a19d1ccb..3a615d663d84ec51c2142514bdbfde897cb18f2d 100644 (file)
@@ -66,9 +66,10 @@ static inline void mlx5e_qid_get_ch_and_group(struct mlx5e_params *params,
        *group = qid / nch;
 }
 
-static inline bool mlx5e_qid_validate(struct mlx5e_params *params, u64 qid)
+static inline bool mlx5e_qid_validate(const struct mlx5e_profile *profile,
+                                     struct mlx5e_params *params, u64 qid)
 {
-       return qid < params->num_channels * MLX5E_NUM_RQ_GROUPS;
+       return qid < params->num_channels * profile->rq_groups;
 }
 
 /* Parameter calculations */
index d5e5afbdca6dcbacb776571c97eef74e033cf356..f777994f3005ea2b68b707bbadb0440ecb9c51e9 100644 (file)
@@ -78,9 +78,10 @@ static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = {
 };
 
 static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
-                                    const u32 **arr, u32 *size)
+                                    const u32 **arr, u32 *size,
+                                    bool force_legacy)
 {
-       bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       bool ext = force_legacy ? false : MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
 
        *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
                      ARRAY_SIZE(mlx5e_link_speed);
@@ -152,7 +153,8 @@ int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
                            sizeof(out), MLX5_REG_PTYS, 0, 1);
 }
 
-u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
+                         bool force_legacy)
 {
        unsigned long temp = eth_proto_oper;
        const u32 *table;
@@ -160,7 +162,7 @@ u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
        u32 max_size;
        int i;
 
-       mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+       mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
        i = find_first_bit(&temp, max_size);
        if (i < max_size)
                speed = table[i];
@@ -170,6 +172,7 @@ u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
 {
        struct mlx5e_port_eth_proto eproto;
+       bool force_legacy = false;
        bool ext;
        int err;
 
@@ -177,8 +180,13 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
        err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
        if (err)
                goto out;
-
-       *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
+       if (ext && !eproto.admin) {
+               force_legacy = true;
+               err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto);
+               if (err)
+                       goto out;
+       }
+       *speed = mlx5e_port_ptys2speed(mdev, eproto.oper, force_legacy);
        if (!(*speed))
                err = -EINVAL;
 
@@ -201,7 +209,7 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
        if (err)
                return err;
 
-       mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+       mlx5e_port_get_speed_arr(mdev, &table, &max_size, false);
        for (i = 0; i < max_size; ++i)
                if (eproto.cap & MLX5E_PROT_MASK(i))
                        max_speed = max(max_speed, table[i]);
@@ -210,14 +218,15 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
        return 0;
 }
 
-u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed)
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
+                              bool force_legacy)
 {
        u32 link_modes = 0;
        const u32 *table;
        u32 max_size;
        int i;
 
-       mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+       mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
        for (i = 0; i < max_size; ++i) {
                if (table[i] == speed)
                        link_modes |= MLX5E_PROT_MASK(i);
index 70f536ec51c47523b76070a1f0971de668698b1d..4a7f4497692bc7655ce6852cc497807a935e6a59 100644 (file)
@@ -48,10 +48,12 @@ void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
                                 u8 *an_disable_cap, u8 *an_disable_admin);
 int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
                           u32 proto_admin, bool ext);
-u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper);
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
+                         bool force_legacy);
 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
 int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
-u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed);
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
+                              bool force_legacy);
 
 int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
 int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
index f3d98748b2117575ad64c83b2bb962ec7a718786..c7f86453c63843c619d6fdad7d078c0ec2acacd3 100644 (file)
@@ -76,26 +76,21 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
        u8 state;
        int err;
 
-       if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state))
-               return 0;
-
        err = mlx5_core_query_sq_state(mdev, sq->sqn, &state);
        if (err) {
                netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n",
                           sq->sqn, err);
-               return err;
+               goto out;
        }
 
-       if (state != MLX5_SQC_STATE_ERR) {
-               netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn);
-               return -EINVAL;
-       }
+       if (state != MLX5_SQC_STATE_ERR)
+               goto out;
 
        mlx5e_tx_disable_queue(sq->txq);
 
        err = mlx5e_wait_for_sq_flush(sq);
        if (err)
-               return err;
+               goto out;
 
        /* At this point, no new packets will arrive from the stack as TXQ is
         * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all
@@ -104,13 +99,17 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
 
        err = mlx5e_sq_to_ready(sq, state);
        if (err)
-               return err;
+               goto out;
 
        mlx5e_reset_txqsq_cc_pc(sq);
        sq->stats->recover++;
+       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
        mlx5e_activate_txqsq(sq);
 
        return 0;
+out:
+       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
+       return err;
 }
 
 static int mlx5_tx_health_report(struct devlink_health_reporter *tx_reporter,
index aaffa6f68dc01c161999896175ea21661be33d81..7f78c004d12f767b2d8f78b281261bebc9bc3557 100644 (file)
@@ -143,7 +143,10 @@ void mlx5e_activate_xsk(struct mlx5e_channel *c)
 {
        set_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state);
        /* TX queue is created active. */
+
+       spin_lock(&c->xskicosq_lock);
        mlx5e_trigger_irq(&c->xskicosq);
+       spin_unlock(&c->xskicosq_lock);
 }
 
 void mlx5e_deactivate_xsk(struct mlx5e_channel *c)
index 407da83474efa08a6c73e74fdebbe58503ff3e3b..b7298f9ee3d3f7d7a2adcb5cd2895d5ab2a0d78f 100644 (file)
 #include "accel/tls.h"
 
 #define MLX5E_KTLS_STATIC_UMR_WQE_SZ \
-       (sizeof(struct mlx5e_umr_wqe) + MLX5_ST_SZ_BYTES(tls_static_params))
+       (offsetof(struct mlx5e_umr_wqe, tls_static_params_ctx) + \
+        MLX5_ST_SZ_BYTES(tls_static_params))
 #define MLX5E_KTLS_STATIC_WQEBBS \
        (DIV_ROUND_UP(MLX5E_KTLS_STATIC_UMR_WQE_SZ, MLX5_SEND_WQE_BB))
 
 #define MLX5E_KTLS_PROGRESS_WQE_SZ \
-       (sizeof(struct mlx5e_tx_wqe) + MLX5_ST_SZ_BYTES(tls_progress_params))
+       (offsetof(struct mlx5e_tx_wqe, tls_progress_params_ctx) + \
+        MLX5_ST_SZ_BYTES(tls_progress_params))
 #define MLX5E_KTLS_PROGRESS_WQEBBS \
        (DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_BB))
 #define MLX5E_KTLS_MAX_DUMP_WQEBBS 2
index ea032f54197e17a8b829d4b6b37a24573fe7237e..7833ddef0427897043d7a6cbaa5fc41436ff2189 100644 (file)
@@ -69,7 +69,7 @@ build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
        cseg->qpn_ds           = cpu_to_be32((sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
                                             STATIC_PARAMS_DS_CNT);
        cseg->fm_ce_se         = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
-       cseg->imm              = cpu_to_be32(priv_tx->tisn);
+       cseg->tisn             = cpu_to_be32(priv_tx->tisn << 8);
 
        ucseg->flags = MLX5_UMR_INLINE;
        ucseg->bsf_octowords = cpu_to_be16(MLX5_ST_SZ_BYTES(tls_static_params) / 16);
@@ -80,7 +80,7 @@ build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
 static void
 fill_progress_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx)
 {
-       MLX5_SET(tls_progress_params, ctx, pd, priv_tx->tisn);
+       MLX5_SET(tls_progress_params, ctx, tisn, priv_tx->tisn);
        MLX5_SET(tls_progress_params, ctx, record_tracker_state,
                 MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START);
        MLX5_SET(tls_progress_params, ctx, auth_state,
@@ -104,18 +104,20 @@ build_progress_params(struct mlx5e_tx_wqe *wqe, u16 pc, u32 sqn,
                                             PROGRESS_PARAMS_DS_CNT);
        cseg->fm_ce_se         = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
 
-       fill_progress_params_ctx(wqe->data, priv_tx);
+       fill_progress_params_ctx(wqe->tls_progress_params_ctx, priv_tx);
 }
 
 static void tx_fill_wi(struct mlx5e_txqsq *sq,
                       u16 pi, u8 num_wqebbs,
-                      skb_frag_t *resync_dump_frag)
+                      skb_frag_t *resync_dump_frag,
+                      u32 num_bytes)
 {
        struct mlx5e_tx_wqe_info *wi = &sq->db.wqe_info[pi];
 
        wi->skb              = NULL;
        wi->num_wqebbs       = num_wqebbs;
        wi->resync_dump_frag = resync_dump_frag;
+       wi->num_bytes        = num_bytes;
 }
 
 void mlx5e_ktls_tx_offload_set_pending(struct mlx5e_ktls_offload_context_tx *priv_tx)
@@ -143,7 +145,7 @@ post_static_params(struct mlx5e_txqsq *sq,
 
        umr_wqe = mlx5e_sq_fetch_wqe(sq, MLX5E_KTLS_STATIC_UMR_WQE_SZ, &pi);
        build_static_params(umr_wqe, sq->pc, sq->sqn, priv_tx, fence);
-       tx_fill_wi(sq, pi, MLX5E_KTLS_STATIC_WQEBBS, NULL);
+       tx_fill_wi(sq, pi, MLX5E_KTLS_STATIC_WQEBBS, NULL, 0);
        sq->pc += MLX5E_KTLS_STATIC_WQEBBS;
 }
 
@@ -157,7 +159,7 @@ post_progress_params(struct mlx5e_txqsq *sq,
 
        wqe = mlx5e_sq_fetch_wqe(sq, MLX5E_KTLS_PROGRESS_WQE_SZ, &pi);
        build_progress_params(wqe, sq->pc, sq->sqn, priv_tx, fence);
-       tx_fill_wi(sq, pi, MLX5E_KTLS_PROGRESS_WQEBBS, NULL);
+       tx_fill_wi(sq, pi, MLX5E_KTLS_PROGRESS_WQEBBS, NULL, 0);
        sq->pc += MLX5E_KTLS_PROGRESS_WQEBBS;
 }
 
@@ -248,43 +250,37 @@ tx_post_resync_params(struct mlx5e_txqsq *sq,
        mlx5e_ktls_tx_post_param_wqes(sq, priv_tx, skip_static_post, true);
 }
 
+struct mlx5e_dump_wqe {
+       struct mlx5_wqe_ctrl_seg ctrl;
+       struct mlx5_wqe_data_seg data;
+};
+
 static int
 tx_post_resync_dump(struct mlx5e_txqsq *sq, struct sk_buff *skb,
                    skb_frag_t *frag, u32 tisn, bool first)
 {
        struct mlx5_wqe_ctrl_seg *cseg;
-       struct mlx5_wqe_eth_seg  *eseg;
        struct mlx5_wqe_data_seg *dseg;
-       struct mlx5e_tx_wqe *wqe;
+       struct mlx5e_dump_wqe *wqe;
        dma_addr_t dma_addr = 0;
-       u16 ds_cnt, ds_cnt_inl;
        u8  num_wqebbs;
-       u16 pi, ihs;
+       u16 ds_cnt;
        int fsz;
-
-       ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS;
-       ihs    = eth_get_headlen(skb->dev, skb->data, skb_headlen(skb));
-       ds_cnt_inl = DIV_ROUND_UP(ihs - INL_HDR_START_SZ, MLX5_SEND_WQE_DS);
-       ds_cnt += ds_cnt_inl;
-       ds_cnt += 1; /* one frag */
+       u16 pi;
 
        wqe = mlx5e_sq_fetch_wqe(sq, sizeof(*wqe), &pi);
 
+       ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS;
        num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
 
        cseg = &wqe->ctrl;
-       eseg = &wqe->eth;
-       dseg =  wqe->data;
+       dseg = &wqe->data;
 
        cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8)  | MLX5_OPCODE_DUMP);
        cseg->qpn_ds           = cpu_to_be32((sq->sqn << 8) | ds_cnt);
-       cseg->imm              = cpu_to_be32(tisn);
+       cseg->tisn             = cpu_to_be32(tisn << 8);
        cseg->fm_ce_se         = first ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
 
-       eseg->inline_hdr.sz = cpu_to_be16(ihs);
-       memcpy(eseg->inline_hdr.start, skb->data, ihs);
-       dseg += ds_cnt_inl;
-
        fsz = skb_frag_size(frag);
        dma_addr = skb_frag_dma_map(sq->pdev, frag, 0, fsz,
                                    DMA_TO_DEVICE);
@@ -296,7 +292,7 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, struct sk_buff *skb,
        dseg->byte_count = cpu_to_be32(fsz);
        mlx5e_dma_push(sq, dma_addr, fsz, MLX5E_DMA_MAP_PAGE);
 
-       tx_fill_wi(sq, pi, num_wqebbs, frag);
+       tx_fill_wi(sq, pi, num_wqebbs, frag, fsz);
        sq->pc += num_wqebbs;
 
        WARN(num_wqebbs > MLX5E_KTLS_MAX_DUMP_WQEBBS,
@@ -323,7 +319,7 @@ static void tx_post_fence_nop(struct mlx5e_txqsq *sq)
        struct mlx5_wq_cyc *wq = &sq->wq;
        u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
 
-       tx_fill_wi(sq, pi, 1, NULL);
+       tx_fill_wi(sq, pi, 1, NULL, 0);
 
        mlx5e_post_nop_fence(wq, sq->sqn, &sq->pc);
 }
@@ -412,7 +408,7 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
                goto out;
 
        tls_ctx = tls_get_ctx(skb->sk);
-       if (unlikely(tls_ctx->netdev != netdev))
+       if (unlikely(WARN_ON_ONCE(tls_ctx->netdev != netdev)))
                goto err_out;
 
        priv_tx = mlx5e_get_ktls_tx_priv_ctx(tls_ctx);
@@ -434,7 +430,7 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
        priv_tx->expected_seq = seq + datalen;
 
        cseg = &(*wqe)->ctrl;
-       cseg->imm = cpu_to_be32(priv_tx->tisn);
+       cseg->tisn = cpu_to_be32(priv_tx->tisn << 8);
 
        stats->tls_encrypted_packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
        stats->tls_encrypted_bytes   += datalen;
index 8657e0f26995b442545dabd3b7b8d5b299b5a380..2c75b2752f58de0e7d0c3e9760736d7ee8035211 100644 (file)
@@ -437,12 +437,6 @@ arfs_hash_bucket(struct arfs_table *arfs_t, __be16 src_port,
        return &arfs_t->rules_hash[bucket_idx];
 }
 
-static u8 arfs_get_ip_proto(const struct sk_buff *skb)
-{
-       return (skb->protocol == htons(ETH_P_IP)) ?
-               ip_hdr(skb)->protocol : ipv6_hdr(skb)->nexthdr;
-}
-
 static struct arfs_table *arfs_get_table(struct mlx5e_arfs_tables *arfs,
                                         u8 ip_proto, __be16 etype)
 {
@@ -602,31 +596,9 @@ out:
        arfs_may_expire_flow(priv);
 }
 
-/* return L4 destination port from ip4/6 packets */
-static __be16 arfs_get_dst_port(const struct sk_buff *skb)
-{
-       char *transport_header;
-
-       transport_header = skb_transport_header(skb);
-       if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
-               return ((struct tcphdr *)transport_header)->dest;
-       return ((struct udphdr *)transport_header)->dest;
-}
-
-/* return L4 source port from ip4/6 packets */
-static __be16 arfs_get_src_port(const struct sk_buff *skb)
-{
-       char *transport_header;
-
-       transport_header = skb_transport_header(skb);
-       if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
-               return ((struct tcphdr *)transport_header)->source;
-       return ((struct udphdr *)transport_header)->source;
-}
-
 static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
                                         struct arfs_table *arfs_t,
-                                        const struct sk_buff *skb,
+                                        const struct flow_keys *fk,
                                         u16 rxq, u32 flow_id)
 {
        struct arfs_rule *rule;
@@ -641,19 +613,19 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
        INIT_WORK(&rule->arfs_work, arfs_handle_work);
 
        tuple = &rule->tuple;
-       tuple->etype = skb->protocol;
+       tuple->etype = fk->basic.n_proto;
+       tuple->ip_proto = fk->basic.ip_proto;
        if (tuple->etype == htons(ETH_P_IP)) {
-               tuple->src_ipv4 = ip_hdr(skb)->saddr;
-               tuple->dst_ipv4 = ip_hdr(skb)->daddr;
+               tuple->src_ipv4 = fk->addrs.v4addrs.src;
+               tuple->dst_ipv4 = fk->addrs.v4addrs.dst;
        } else {
-               memcpy(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
+               memcpy(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
                       sizeof(struct in6_addr));
-               memcpy(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
+               memcpy(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
                       sizeof(struct in6_addr));
        }
-       tuple->ip_proto = arfs_get_ip_proto(skb);
-       tuple->src_port = arfs_get_src_port(skb);
-       tuple->dst_port = arfs_get_dst_port(skb);
+       tuple->src_port = fk->ports.src;
+       tuple->dst_port = fk->ports.dst;
 
        rule->flow_id = flow_id;
        rule->filter_id = priv->fs.arfs.last_filter_id++ % RPS_NO_FILTER;
@@ -664,37 +636,33 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
        return rule;
 }
 
-static bool arfs_cmp_ips(struct arfs_tuple *tuple,
-                        const struct sk_buff *skb)
+static bool arfs_cmp(const struct arfs_tuple *tuple, const struct flow_keys *fk)
 {
-       if (tuple->etype == htons(ETH_P_IP) &&
-           tuple->src_ipv4 == ip_hdr(skb)->saddr &&
-           tuple->dst_ipv4 == ip_hdr(skb)->daddr)
-               return true;
-       if (tuple->etype == htons(ETH_P_IPV6) &&
-           (!memcmp(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
-                    sizeof(struct in6_addr))) &&
-           (!memcmp(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
-                    sizeof(struct in6_addr))))
-               return true;
+       if (tuple->src_port != fk->ports.src || tuple->dst_port != fk->ports.dst)
+               return false;
+       if (tuple->etype != fk->basic.n_proto)
+               return false;
+       if (tuple->etype == htons(ETH_P_IP))
+               return tuple->src_ipv4 == fk->addrs.v4addrs.src &&
+                      tuple->dst_ipv4 == fk->addrs.v4addrs.dst;
+       if (tuple->etype == htons(ETH_P_IPV6))
+               return !memcmp(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
+                              sizeof(struct in6_addr)) &&
+                      !memcmp(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
+                              sizeof(struct in6_addr));
        return false;
 }
 
 static struct arfs_rule *arfs_find_rule(struct arfs_table *arfs_t,
-                                       const struct sk_buff *skb)
+                                       const struct flow_keys *fk)
 {
        struct arfs_rule *arfs_rule;
        struct hlist_head *head;
-       __be16 src_port = arfs_get_src_port(skb);
-       __be16 dst_port = arfs_get_dst_port(skb);
 
-       head = arfs_hash_bucket(arfs_t, src_port, dst_port);
+       head = arfs_hash_bucket(arfs_t, fk->ports.src, fk->ports.dst);
        hlist_for_each_entry(arfs_rule, head, hlist) {
-               if (arfs_rule->tuple.src_port == src_port &&
-                   arfs_rule->tuple.dst_port == dst_port &&
-                   arfs_cmp_ips(&arfs_rule->tuple, skb)) {
+               if (arfs_cmp(&arfs_rule->tuple, fk))
                        return arfs_rule;
-               }
        }
 
        return NULL;
@@ -707,20 +675,24 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
        struct mlx5e_arfs_tables *arfs = &priv->fs.arfs;
        struct arfs_table *arfs_t;
        struct arfs_rule *arfs_rule;
+       struct flow_keys fk;
+
+       if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
+               return -EPROTONOSUPPORT;
 
-       if (skb->protocol != htons(ETH_P_IP) &&
-           skb->protocol != htons(ETH_P_IPV6))
+       if (fk.basic.n_proto != htons(ETH_P_IP) &&
+           fk.basic.n_proto != htons(ETH_P_IPV6))
                return -EPROTONOSUPPORT;
 
        if (skb->encapsulation)
                return -EPROTONOSUPPORT;
 
-       arfs_t = arfs_get_table(arfs, arfs_get_ip_proto(skb), skb->protocol);
+       arfs_t = arfs_get_table(arfs, fk.basic.ip_proto, fk.basic.n_proto);
        if (!arfs_t)
                return -EPROTONOSUPPORT;
 
        spin_lock_bh(&arfs->arfs_lock);
-       arfs_rule = arfs_find_rule(arfs_t, skb);
+       arfs_rule = arfs_find_rule(arfs_t, &fk);
        if (arfs_rule) {
                if (arfs_rule->rxq == rxq_index) {
                        spin_unlock_bh(&arfs->arfs_lock);
@@ -728,8 +700,7 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                }
                arfs_rule->rxq = rxq_index;
        } else {
-               arfs_rule = arfs_alloc_rule(priv, arfs_t, skb,
-                                           rxq_index, flow_id);
+               arfs_rule = arfs_alloc_rule(priv, arfs_t, &fk, rxq_index, flow_id);
                if (!arfs_rule) {
                        spin_unlock_bh(&arfs->arfs_lock);
                        return -ENOMEM;
index 126ec41812865d99b8d32ea0ca9c2908d68763ca..20e628c907e53a3020c211575e059ab800c22e50 100644 (file)
@@ -391,7 +391,7 @@ void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv,
 {
        mutex_lock(&priv->state_lock);
 
-       ch->max_combined   = mlx5e_get_netdev_max_channels(priv->netdev);
+       ch->max_combined   = priv->max_nch;
        ch->combined_count = priv->channels.params.num_channels;
        if (priv->xsk.refcnt) {
                /* The upper half are XSK queues. */
@@ -785,7 +785,7 @@ static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings
 }
 
 static void get_speed_duplex(struct net_device *netdev,
-                            u32 eth_proto_oper,
+                            u32 eth_proto_oper, bool force_legacy,
                             struct ethtool_link_ksettings *link_ksettings)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -795,7 +795,7 @@ static void get_speed_duplex(struct net_device *netdev,
        if (!netif_carrier_ok(netdev))
                goto out;
 
-       speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper);
+       speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper, force_legacy);
        if (!speed) {
                speed = SPEED_UNKNOWN;
                goto out;
@@ -914,8 +914,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        /* Fields: eth_proto_admin and ext_eth_proto_admin  are
         * mutually exclusive. Hence try reading legacy advertising
         * when extended advertising is zero.
-        * admin_ext indicates how eth_proto_admin should be
-        * interpreted
+        * admin_ext indicates which proto_admin (ext vs. legacy)
+        * should be read and interpreted
         */
        admin_ext = ext;
        if (ext && !eth_proto_admin) {
@@ -924,7 +924,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
                admin_ext = false;
        }
 
-       eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
+       eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, admin_ext,
                                              eth_proto_oper);
        eth_proto_lp        = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
        an_disable_admin    = MLX5_GET(ptys_reg, out, an_disable_admin);
@@ -939,7 +939,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        get_supported(mdev, eth_proto_cap, link_ksettings);
        get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings,
                        admin_ext);
-       get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings);
+       get_speed_duplex(priv->netdev, eth_proto_oper, !admin_ext,
+                        link_ksettings);
 
        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
 
@@ -1016,45 +1017,77 @@ static u32 mlx5e_ethtool2ptys_ext_adver_link(const unsigned long *link_modes)
        return ptys_modes;
 }
 
+static bool ext_link_mode_requested(const unsigned long *adver)
+{
+#define MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT ETHTOOL_LINK_MODE_50000baseKR_Full_BIT
+       int size = __ETHTOOL_LINK_MODE_MASK_NBITS - MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT;
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(modes);
+
+       bitmap_set(modes, MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT, size);
+       return bitmap_intersects(modes, adver, __ETHTOOL_LINK_MODE_MASK_NBITS);
+}
+
+static bool ext_speed_requested(u32 speed)
+{
+#define MLX5E_MAX_PTYS_LEGACY_SPEED 100000
+       return !!(speed > MLX5E_MAX_PTYS_LEGACY_SPEED);
+}
+
+static bool ext_requested(u8 autoneg, const unsigned long *adver, u32 speed)
+{
+       bool ext_link_mode = ext_link_mode_requested(adver);
+       bool ext_speed = ext_speed_requested(speed);
+
+       return  autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_speed;
+}
+
 int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
                                     const struct ethtool_link_ksettings *link_ksettings)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5e_port_eth_proto eproto;
+       const unsigned long *adver;
        bool an_changes = false;
        u8 an_disable_admin;
        bool ext_supported;
-       bool ext_requested;
        u8 an_disable_cap;
        bool an_disable;
        u32 link_modes;
        u8 an_status;
+       u8 autoneg;
        u32 speed;
+       bool ext;
        int err;
 
        u32 (*ethtool2ptys_adver_func)(const unsigned long *adver);
 
-#define MLX5E_PTYS_EXT ((1ULL << ETHTOOL_LINK_MODE_50000baseKR_Full_BIT) - 1)
+       adver = link_ksettings->link_modes.advertising;
+       autoneg = link_ksettings->base.autoneg;
+       speed = link_ksettings->base.speed;
 
-       ext_requested = !!(link_ksettings->link_modes.advertising[0] >
-                       MLX5E_PTYS_EXT ||
-                       link_ksettings->link_modes.advertising[1]);
+       ext = ext_requested(autoneg, adver, speed),
        ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
-       ext_requested &= ext_supported;
+       if (!ext_supported && ext)
+               return -EOPNOTSUPP;
 
-       speed = link_ksettings->base.speed;
-       ethtool2ptys_adver_func = ext_requested ?
-                                 mlx5e_ethtool2ptys_ext_adver_link :
+       ethtool2ptys_adver_func = ext ? mlx5e_ethtool2ptys_ext_adver_link :
                                  mlx5e_ethtool2ptys_adver_link;
-       err = mlx5_port_query_eth_proto(mdev, 1, ext_requested, &eproto);
+       err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
        if (err) {
                netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
                           __func__, err);
                goto out;
        }
-       link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
-               ethtool2ptys_adver_func(link_ksettings->link_modes.advertising) :
-               mlx5e_port_speed2linkmodes(mdev, speed);
+       link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) :
+               mlx5e_port_speed2linkmodes(mdev, speed, !ext);
+
+       if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) &&
+           autoneg != AUTONEG_ENABLE) {
+               netdev_err(priv->netdev, "%s: 56G link speed requires autoneg enabled\n",
+                          __func__);
+               err = -EINVAL;
+               goto out;
+       }
 
        link_modes = link_modes & eproto.cap;
        if (!link_modes) {
@@ -1067,14 +1100,14 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
        mlx5_port_query_eth_autoneg(mdev, &an_status, &an_disable_cap,
                                    &an_disable_admin);
 
-       an_disable = link_ksettings->base.autoneg == AUTONEG_DISABLE;
+       an_disable = autoneg == AUTONEG_DISABLE;
        an_changes = ((!an_disable && an_disable_admin) ||
                      (an_disable && !an_disable_admin));
 
        if (!an_changes && link_modes == eproto.admin)
                goto out;
 
-       mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_requested);
+       mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext);
        mlx5_toggle_port_link(mdev);
 
 out:
@@ -1313,6 +1346,9 @@ int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
        struct mlx5_core_dev *mdev = priv->mdev;
        int err;
 
+       if (!MLX5_CAP_GEN(mdev, vport_group_manager))
+               return -EOPNOTSUPP;
+
        if (pauseparam->autoneg)
                return -EINVAL;
 
@@ -1654,6 +1690,40 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,
        return 0;
 }
 
+int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
+                              struct ethtool_flash *flash)
+{
+       struct mlx5_core_dev *mdev = priv->mdev;
+       struct net_device *dev = priv->netdev;
+       const struct firmware *fw;
+       int err;
+
+       if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
+               return -EOPNOTSUPP;
+
+       err = request_firmware_direct(&fw, flash->data, &dev->dev);
+       if (err)
+               return err;
+
+       dev_hold(dev);
+       rtnl_unlock();
+
+       err = mlx5_firmware_flash(mdev, fw, NULL);
+       release_firmware(fw);
+
+       rtnl_lock();
+       dev_put(dev);
+       return err;
+}
+
+static int mlx5e_flash_device(struct net_device *dev,
+                             struct ethtool_flash *flash)
+{
+       struct mlx5e_priv *priv = netdev_priv(dev);
+
+       return mlx5e_ethtool_flash_device(priv, flash);
+}
+
 static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
                                     bool is_rx_cq)
 {
@@ -1936,6 +2006,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
        .set_wol           = mlx5e_set_wol,
        .get_module_info   = mlx5e_get_module_info,
        .get_module_eeprom = mlx5e_get_module_eeprom,
+       .flash_device      = mlx5e_flash_device,
        .get_priv_flags    = mlx5e_get_priv_flags,
        .set_priv_flags    = mlx5e_set_priv_flags,
        .self_test         = mlx5e_self_test,
index ea3a490b569a58c46b49196b3637bec4923b7843..94304abc49e98102c50a6a1fcb63ca468335af96 100644 (file)
@@ -611,7 +611,8 @@ static int validate_flow(struct mlx5e_priv *priv,
                return -ENOSPC;
 
        if (fs->ring_cookie != RX_CLS_FLOW_DISC)
-               if (!mlx5e_qid_validate(&priv->channels.params, fs->ring_cookie))
+               if (!mlx5e_qid_validate(priv->profile, &priv->channels.params,
+                                       fs->ring_cookie))
                        return -EINVAL;
 
        switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
index 47eea6b3a1c385dc97339f671a1d56b49dc3c92b..9d5f6e56188f825bbbe605f1bfb3af09604d5e42 100644 (file)
@@ -331,12 +331,11 @@ static inline u64 mlx5e_get_mpwqe_offset(struct mlx5e_rq *rq, u16 wqe_ix)
 
 static void mlx5e_init_frags_partition(struct mlx5e_rq *rq)
 {
-       struct mlx5e_wqe_frag_info next_frag, *prev;
+       struct mlx5e_wqe_frag_info next_frag = {};
+       struct mlx5e_wqe_frag_info *prev = NULL;
        int i;
 
        next_frag.di = &rq->wqe.di[0];
-       next_frag.offset = 0;
-       prev = NULL;
 
        for (i = 0; i < mlx5_wq_cyc_get_size(&rq->wqe.wq); i++) {
                struct mlx5e_rq_frag_info *frag_info = &rq->wqe.info.arr[0];
@@ -1322,7 +1321,6 @@ err_free_txqsq:
 void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
 {
        sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix);
-       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
        set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
        netdev_tx_reset_queue(sq->txq);
        netif_tx_start_queue(sq->txq);
@@ -1677,10 +1675,10 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c,
                          struct mlx5e_channel_param *cparam)
 {
        struct mlx5e_priv *priv = c->priv;
-       int err, tc, max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
+       int err, tc;
 
        for (tc = 0; tc < params->num_tc; tc++) {
-               int txq_ix = c->ix + tc * max_nch;
+               int txq_ix = c->ix + tc * priv->max_nch;
 
                err = mlx5e_open_txqsq(c, c->priv->tisn[tc], txq_ix,
                                       params, &cparam->sq, &c->sq[tc], tc);
@@ -2438,11 +2436,10 @@ int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv)
 
 int mlx5e_create_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
 {
-       const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        int err;
        int ix;
 
-       for (ix = 0; ix < max_nch; ix++) {
+       for (ix = 0; ix < priv->max_nch; ix++) {
                err = mlx5e_create_rqt(priv, 1 /*size */, &tirs[ix].rqt);
                if (unlikely(err))
                        goto err_destroy_rqts;
@@ -2460,10 +2457,9 @@ err_destroy_rqts:
 
 void mlx5e_destroy_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
 {
-       const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        int i;
 
-       for (i = 0; i < max_nch; i++)
+       for (i = 0; i < priv->max_nch; i++)
                mlx5e_destroy_rqt(priv, &tirs[i].rqt);
 }
 
@@ -2557,7 +2553,7 @@ static void mlx5e_redirect_rqts(struct mlx5e_priv *priv,
                mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, rrp);
        }
 
-       for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
+       for (ix = 0; ix < priv->max_nch; ix++) {
                struct mlx5e_redirect_rqt_param direct_rrp = {
                        .is_rss = false,
                        {
@@ -2758,7 +2754,7 @@ static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
                        goto free_in;
        }
 
-       for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
+       for (ix = 0; ix < priv->max_nch; ix++) {
                err = mlx5_core_modify_tir(mdev, priv->direct_tir[ix].tirn,
                                           in, inlen);
                if (err)
@@ -2858,12 +2854,11 @@ static void mlx5e_netdev_set_tcs(struct net_device *netdev)
 
 static void mlx5e_build_tc2txq_maps(struct mlx5e_priv *priv)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        int i, tc;
 
-       for (i = 0; i < max_nch; i++)
+       for (i = 0; i < priv->max_nch; i++)
                for (tc = 0; tc < priv->profile->max_tc; tc++)
-                       priv->channel_tc2txq[i][tc] = i + tc * max_nch;
+                       priv->channel_tc2txq[i][tc] = i + tc * priv->max_nch;
 }
 
 static void mlx5e_build_tx2sq_maps(struct mlx5e_priv *priv)
@@ -2884,7 +2879,7 @@ static void mlx5e_build_tx2sq_maps(struct mlx5e_priv *priv)
 void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
 {
        int num_txqs = priv->channels.num * priv->channels.params.num_tc;
-       int num_rxqs = priv->channels.num * MLX5E_NUM_RQ_GROUPS;
+       int num_rxqs = priv->channels.num * priv->profile->rq_groups;
        struct net_device *netdev = priv->netdev;
 
        mlx5e_netdev_set_tcs(netdev);
@@ -3306,7 +3301,6 @@ err_destroy_inner_tirs:
 
 int mlx5e_create_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
 {
-       const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        struct mlx5e_tir *tir;
        void *tirc;
        int inlen;
@@ -3319,7 +3313,7 @@ int mlx5e_create_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
        if (!in)
                return -ENOMEM;
 
-       for (ix = 0; ix < max_nch; ix++) {
+       for (ix = 0; ix < priv->max_nch; ix++) {
                memset(in, 0, inlen);
                tir = &tirs[ix];
                tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
@@ -3358,10 +3352,9 @@ void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc)
 
 void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
 {
-       const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        int i;
 
-       for (i = 0; i < max_nch; i++)
+       for (i = 0; i < priv->max_nch; i++)
                mlx5e_destroy_tir(priv->mdev, &tirs[i]);
 }
 
@@ -3487,7 +3480,7 @@ void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
 {
        int i;
 
-       for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) {
+       for (i = 0; i < priv->max_nch; i++) {
                struct mlx5e_channel_stats *channel_stats = &priv->channel_stats[i];
                struct mlx5e_rq_stats *xskrq_stats = &channel_stats->xskrq;
                struct mlx5e_rq_stats *rq_stats = &channel_stats->rq;
@@ -4960,8 +4953,7 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
                return err;
 
        mlx5e_build_nic_params(mdev, &priv->xsk, rss, &priv->channels.params,
-                              mlx5e_get_netdev_max_channels(netdev),
-                              netdev->mtu);
+                              priv->max_nch, netdev->mtu);
 
        mlx5e_timestamp_init(priv);
 
@@ -5164,6 +5156,7 @@ static const struct mlx5e_profile mlx5e_nic_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe,
        .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
        .max_tc            = MLX5E_MAX_NUM_TC,
+       .rq_groups         = MLX5E_NUM_RQ_GROUPS(XSK),
 };
 
 /* mlx5e generic netdev management API (move to en_common.c) */
@@ -5181,6 +5174,7 @@ int mlx5e_netdev_init(struct net_device *netdev,
        priv->profile     = profile;
        priv->ppriv       = ppriv;
        priv->msglevel    = MLX5E_MSG_LEVEL;
+       priv->max_nch     = netdev->num_rx_queues / max_t(u8, profile->rq_groups, 1);
        priv->max_opened_tc = 1;
 
        mutex_init(&priv->state_lock);
@@ -5218,7 +5212,7 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
 
        netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
                                    nch * profile->max_tc,
-                                   nch * MLX5E_NUM_RQ_GROUPS);
+                                   nch * profile->rq_groups);
        if (!netdev) {
                mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
                return NULL;
index 7245d287633d4a8accd65664fd5b2d3b2f7ff470..d0684fdb69e1424cee0e17d147755d20fa938e85 100644 (file)
@@ -735,8 +735,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
                list_add(&indr_priv->list,
                         &rpriv->uplink_priv.tc_indr_block_priv_list);
 
-               block_cb = flow_block_cb_alloc(f->net,
-                                              mlx5e_rep_indr_setup_block_cb,
+               block_cb = flow_block_cb_alloc(mlx5e_rep_indr_setup_block_cb,
                                               indr_priv, indr_priv,
                                               mlx5e_rep_indr_tc_block_unbind);
                if (IS_ERR(block_cb)) {
@@ -753,7 +752,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
                if (!indr_priv)
                        return -ENOENT;
 
-               block_cb = flow_block_cb_lookup(f,
+               block_cb = flow_block_cb_lookup(f->block,
                                                mlx5e_rep_indr_setup_block_cb,
                                                indr_priv);
                if (!block_cb)
@@ -1702,6 +1701,7 @@ static const struct mlx5e_profile mlx5e_rep_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe_rep,
        .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
        .max_tc                 = 1,
+       .rq_groups              = MLX5E_NUM_RQ_GROUPS(REGULAR),
 };
 
 static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
@@ -1719,6 +1719,7 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe_rep,
        .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
        .max_tc                 = MLX5E_MAX_NUM_TC,
+       .rq_groups              = MLX5E_NUM_RQ_GROUPS(REGULAR),
 };
 
 static bool
index 539b4d3656da1e3af54a2977024d4a0346c584f2..57f9f346d213b0ba9be9449c2947c06442d6c6c5 100644 (file)
@@ -172,7 +172,7 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
 
        memset(s, 0, sizeof(*s));
 
-       for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) {
+       for (i = 0; i < priv->max_nch; i++) {
                struct mlx5e_channel_stats *channel_stats =
                        &priv->channel_stats[i];
                struct mlx5e_xdpsq_stats *xdpsq_red_stats = &channel_stats->xdpsq;
@@ -1395,7 +1395,7 @@ static const struct counter_desc ch_stats_desc[] = {
 
 static int mlx5e_grp_channels_get_num_stats(struct mlx5e_priv *priv)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
+       int max_nch = priv->max_nch;
 
        return (NUM_RQ_STATS * max_nch) +
               (NUM_CH_STATS * max_nch) +
@@ -1409,8 +1409,8 @@ static int mlx5e_grp_channels_get_num_stats(struct mlx5e_priv *priv)
 static int mlx5e_grp_channels_fill_strings(struct mlx5e_priv *priv, u8 *data,
                                           int idx)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        bool is_xsk = priv->xsk.ever_used;
+       int max_nch = priv->max_nch;
        int i, j, tc;
 
        for (i = 0; i < max_nch; i++)
@@ -1452,8 +1452,8 @@ static int mlx5e_grp_channels_fill_strings(struct mlx5e_priv *priv, u8 *data,
 static int mlx5e_grp_channels_fill_stats(struct mlx5e_priv *priv, u64 *data,
                                         int idx)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        bool is_xsk = priv->xsk.ever_used;
+       int max_nch = priv->max_nch;
        int i, j, tc;
 
        for (i = 0; i < max_nch; i++)
index cc096f6011d964051405dd5fa3514b428086cc5a..00b2d4a86159f142e491278769fe1679ce5a2d20 100644 (file)
@@ -1230,13 +1230,13 @@ static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow)
 void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
 {
        struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
-       u64 bytes, packets, lastuse = 0;
        struct mlx5e_tc_flow *flow;
        struct mlx5e_encap_entry *e;
        struct mlx5_fc *counter;
        struct neigh_table *tbl;
        bool neigh_used = false;
        struct neighbour *n;
+       u64 lastuse;
 
        if (m_neigh->family == AF_INET)
                tbl = &arp_tbl;
@@ -1256,7 +1256,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
                                            encaps[efi->index]);
                        if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
                                counter = mlx5e_tc_get_counter(flow);
-                               mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
+                               lastuse = mlx5_fc_query_lastuse(counter);
                                if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) {
                                        neigh_used = true;
                                        break;
@@ -1480,7 +1480,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                              struct mlx5_flow_spec *spec,
                              struct flow_cls_offload *f,
                              struct net_device *filter_dev,
-                             u8 *match_level, u8 *tunnel_match_level)
+                             u8 *inner_match_level, u8 *outer_match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1495,8 +1495,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
        struct flow_dissector *dissector = rule->match.dissector;
        u16 addr_type = 0;
        u8 ip_proto = 0;
+       u8 *match_level;
 
-       *match_level = MLX5_MATCH_NONE;
+       match_level = outer_match_level;
 
        if (dissector->used_keys &
            ~(BIT(FLOW_DISSECTOR_KEY_META) |
@@ -1524,12 +1525,14 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
        }
 
        if (mlx5e_get_tc_tun(filter_dev)) {
-               if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
+               if (parse_tunnel_attr(priv, spec, f, filter_dev,
+                                     outer_match_level))
                        return -EOPNOTSUPP;
 
-               /* In decap flow, header pointers should point to the inner
+               /* At this point, header pointers should point to the inner
                 * headers, outer header were already set by parse_tunnel_attr
                 */
+               match_level = inner_match_level;
                headers_c = get_match_headers_criteria(MLX5_FLOW_CONTEXT_ACTION_DECAP,
                                                       spec);
                headers_v = get_match_headers_value(MLX5_FLOW_CONTEXT_ACTION_DECAP,
@@ -1831,35 +1834,41 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
                            struct flow_cls_offload *f,
                            struct net_device *filter_dev)
 {
+       u8 inner_match_level, outer_match_level, non_tunnel_match_level;
        struct netlink_ext_ack *extack = f->common.extack;
        struct mlx5_core_dev *dev = priv->mdev;
        struct mlx5_eswitch *esw = dev->priv.eswitch;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
-       u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
        struct mlx5_eswitch_rep *rep;
        int err;
 
-       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
+       inner_match_level = MLX5_MATCH_NONE;
+       outer_match_level = MLX5_MATCH_NONE;
+
+       err = __parse_cls_flower(priv, spec, f, filter_dev, &inner_match_level,
+                                &outer_match_level);
+       non_tunnel_match_level = (inner_match_level == MLX5_MATCH_NONE) ?
+                                outer_match_level : inner_match_level;
 
        if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
                rep = rpriv->rep;
                if (rep->vport != MLX5_VPORT_UPLINK &&
                    (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
-                   esw->offloads.inline_mode < match_level)) {
+                   esw->offloads.inline_mode < non_tunnel_match_level)) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "Flow is not offloaded due to min inline setting");
                        netdev_warn(priv->netdev,
                                    "Flow is not offloaded due to min inline setting, required %d actual %d\n",
-                                   match_level, esw->offloads.inline_mode);
+                                   non_tunnel_match_level, esw->offloads.inline_mode);
                        return -EOPNOTSUPP;
                }
        }
 
        if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
-               flow->esw_attr->match_level = match_level;
-               flow->esw_attr->tunnel_match_level = tunnel_match_level;
+               flow->esw_attr->inner_match_level = inner_match_level;
+               flow->esw_attr->outer_match_level = outer_match_level;
        } else {
-               flow->nic_attr->match_level = match_level;
+               flow->nic_attr->match_level = non_tunnel_match_level;
        }
 
        return err;
@@ -3158,7 +3167,7 @@ mlx5e_flow_esw_attr_init(struct mlx5_esw_flow_attr *esw_attr,
 
        esw_attr->parse_attr = parse_attr;
        esw_attr->chain = f->common.chain_index;
-       esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16;
+       esw_attr->prio = f->common.prio;
 
        esw_attr->in_rep = in_rep;
        esw_attr->in_mdev = in_mdev;
index c50b6f0769c8c5086946fb8618ca42fdc4f2079c..49b06b256c92955d8b0054ade614b2d33ee41c1e 100644 (file)
@@ -49,7 +49,7 @@ static inline bool mlx5e_channel_no_affinity_change(struct mlx5e_channel *c)
 static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
 {
        struct mlx5e_sq_stats *stats = sq->stats;
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
 
        if (unlikely(!test_bit(MLX5E_SQ_STATE_AM, &sq->state)))
                return;
@@ -61,7 +61,7 @@ static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
 static void mlx5e_handle_rx_dim(struct mlx5e_rq *rq)
 {
        struct mlx5e_rq_stats *stats = rq->stats;
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
 
        if (unlikely(!test_bit(MLX5E_RQ_STATE_AM, &rq->state)))
                return;
index a38e8a3c7c9a3b71b6a51c9f440b25878508340f..04685dbb280cfad006007a070ac0d2414a5fd894 100644 (file)
@@ -377,8 +377,8 @@ struct mlx5_esw_flow_attr {
                struct mlx5_termtbl_handle *termtbl;
        } dests[MLX5_MAX_FLOW_FWD_VPORTS];
        u32     mod_hdr_id;
-       u8      match_level;
-       u8      tunnel_match_level;
+       u8      inner_match_level;
+       u8      outer_match_level;
        struct mlx5_fc *counter;
        u32     chain;
        u16     prio;
index 089ae4d48a82dda15e47c49530f9a4e513577acb..0323fd078271bce17cff6a8c963cf803b7437fda 100644 (file)
@@ -207,14 +207,10 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 
        mlx5_eswitch_set_rule_source_port(esw, spec, attr);
 
-       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
-               if (attr->tunnel_match_level != MLX5_MATCH_NONE)
-                       spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
-               if (attr->match_level != MLX5_MATCH_NONE)
-                       spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
-       } else if (attr->match_level != MLX5_MATCH_NONE) {
+       if (attr->outer_match_level != MLX5_MATCH_NONE)
                spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
-       }
+       if (attr->inner_match_level != MLX5_MATCH_NONE)
+               spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                flow_act.modify_id = attr->mod_hdr_id;
@@ -290,7 +286,7 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
        mlx5_eswitch_set_rule_source_port(esw, spec, attr);
 
        spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
-       if (attr->match_level != MLX5_MATCH_NONE)
+       if (attr->outer_match_level != MLX5_MATCH_NONE)
                spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
 
        rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);
index c48c382f926f33b5747c5f5603c18713a03e6bd0..c1252d6be0ef13f38fbe573e724b0a814f319230 100644 (file)
@@ -68,7 +68,7 @@ enum fs_flow_table_type {
        FS_FT_SNIFFER_RX        = 0X5,
        FS_FT_SNIFFER_TX        = 0X6,
        FS_FT_RDMA_RX           = 0X7,
-       FS_FT_MAX_TYPE = FS_FT_SNIFFER_TX,
+       FS_FT_MAX_TYPE = FS_FT_RDMA_RX,
 };
 
 enum fs_flow_table_op_mod {
@@ -275,7 +275,8 @@ void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
        (type == FS_FT_FDB) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) :           \
        (type == FS_FT_SNIFFER_RX) ? MLX5_CAP_FLOWTABLE_SNIFFER_RX(mdev, cap) :         \
        (type == FS_FT_SNIFFER_TX) ? MLX5_CAP_FLOWTABLE_SNIFFER_TX(mdev, cap) :         \
-       (BUILD_BUG_ON_ZERO(FS_FT_SNIFFER_TX != FS_FT_MAX_TYPE))\
+       (type == FS_FT_RDMA_RX) ? MLX5_CAP_FLOWTABLE_RDMA_RX(mdev, cap) :               \
+       (BUILD_BUG_ON_ZERO(FS_FT_RDMA_RX != FS_FT_MAX_TYPE))\
        )
 
 #endif
index b3762123a69c2188f1745965aaeeb80ca8d80bf6..1834d9f3aa1c019ee9057b141bfe86068ac757c2 100644 (file)
@@ -369,6 +369,11 @@ int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
 }
 EXPORT_SYMBOL(mlx5_fc_query);
 
+u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter)
+{
+       return counter->cache.lastuse;
+}
+
 void mlx5_fc_query_cached(struct mlx5_fc *counter,
                          u64 *bytes, u64 *packets, u64 *lastuse)
 {
index 9314777d99e3f1e542e9cb5d4aa6960ac3849a10..d685122d9ff761794a7f89d860a90e25801f29fc 100644 (file)
@@ -590,7 +590,8 @@ mlx5_fw_fatal_reporter_dump(struct devlink_health_reporter *reporter,
                        data_size = crdump_size - offset;
                else
                        data_size = MLX5_CR_DUMP_CHUNK_SIZE;
-               err = devlink_fmsg_binary_put(fmsg, cr_data, data_size);
+               err = devlink_fmsg_binary_put(fmsg, (char *)cr_data + offset,
+                                             data_size);
                if (err)
                        goto free_data;
        }
@@ -700,6 +701,16 @@ static void poll_health(struct timer_list *t)
        if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
                goto out;
 
+       fatal_error = check_fatal_sensors(dev);
+
+       if (fatal_error && !health->fatal_error) {
+               mlx5_core_err(dev, "Fatal error %u detected\n", fatal_error);
+               dev->priv.health.fatal_error = fatal_error;
+               print_health_info(dev);
+               mlx5_trigger_health_work(dev);
+               goto out;
+       }
+
        count = ioread32be(health->health_counter);
        if (count == health->prev)
                ++health->miss_counter;
@@ -718,15 +729,6 @@ static void poll_health(struct timer_list *t)
        if (health->synd && health->synd != prev_synd)
                queue_work(health->wq, &health->report_work);
 
-       fatal_error = check_fatal_sensors(dev);
-
-       if (fatal_error && !health->fatal_error) {
-               mlx5_core_err(dev, "Fatal error %u detected\n", fatal_error);
-               dev->priv.health.fatal_error = fatal_error;
-               print_health_info(dev);
-               mlx5_trigger_health_work(dev);
-       }
-
 out:
        mod_timer(&health->timer, get_next_poll_jiffies());
 }
index ebd81f6b556e9e6b00e3cf3534a5260a8f01e7ad..90cb50fe17fd95de3a5f295a8cbe60f97cabafa8 100644 (file)
@@ -122,6 +122,14 @@ static int mlx5i_get_ts_info(struct net_device *netdev,
        return mlx5e_ethtool_get_ts_info(priv, info);
 }
 
+static int mlx5i_flash_device(struct net_device *netdev,
+                             struct ethtool_flash *flash)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(netdev);
+
+       return mlx5e_ethtool_flash_device(priv, flash);
+}
+
 enum mlx5_ptys_width {
        MLX5_PTYS_WIDTH_1X      = 1 << 0,
        MLX5_PTYS_WIDTH_2X      = 1 << 1,
@@ -233,6 +241,7 @@ const struct ethtool_ops mlx5i_ethtool_ops = {
        .get_ethtool_stats  = mlx5i_get_ethtool_stats,
        .get_ringparam      = mlx5i_get_ringparam,
        .set_ringparam      = mlx5i_set_ringparam,
+       .flash_device       = mlx5i_flash_device,
        .get_channels       = mlx5i_get_channels,
        .set_channels       = mlx5i_set_channels,
        .get_coalesce       = mlx5i_get_coalesce,
index 6bfaaab362dc48dac5f5e76d91eb41578585b2fb..1a2560e3bf7c54d85390b1f8a93600ad5a84ead9 100644 (file)
@@ -88,8 +88,7 @@ int mlx5i_init(struct mlx5_core_dev *mdev,
        netdev->mtu = netdev->max_mtu;
 
        mlx5e_build_nic_params(mdev, NULL, &priv->rss_params, &priv->channels.params,
-                              mlx5e_get_netdev_max_channels(netdev),
-                              netdev->mtu);
+                              priv->max_nch, netdev->mtu);
        mlx5i_build_nic_params(mdev, &priv->channels.params);
 
        mlx5e_timestamp_init(priv);
@@ -118,11 +117,10 @@ void mlx5i_cleanup(struct mlx5e_priv *priv)
 
 static void mlx5i_grp_sw_update_stats(struct mlx5e_priv *priv)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        struct mlx5e_sw_stats s = { 0 };
        int i, j;
 
-       for (i = 0; i < max_nch; i++) {
+       for (i = 0; i < priv->max_nch; i++) {
                struct mlx5e_channel_stats *channel_stats;
                struct mlx5e_rq_stats *rq_stats;
 
@@ -436,6 +434,7 @@ static const struct mlx5e_profile mlx5i_nic_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5i_handle_rx_cqe,
        .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */
        .max_tc            = MLX5I_MAX_NUM_TC,
+       .rq_groups         = MLX5E_NUM_RQ_GROUPS(REGULAR),
 };
 
 /* mlx5i netdev NDos */
index 6e56fa769d2eb97b593b2c3da4c5aa5c40c1afdc..c5a491e22e55547def2706fa6b28c8c08fa858d1 100644 (file)
@@ -355,6 +355,7 @@ static const struct mlx5e_profile mlx5i_pkey_nic_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5i_handle_rx_cqe,
        .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */
        .max_tc            = MLX5I_MAX_NUM_TC,
+       .rq_groups         = MLX5E_NUM_RQ_GROUPS(REGULAR),
 };
 
 const struct mlx5e_profile *mlx5i_pkey_get_profile(void)
index ea9ee88491e5d13e120efed9556af2241eec92c6..ea1d4d26ece06a242b86182fe77aff766c76fbf7 100644 (file)
@@ -27,6 +27,7 @@ int mlx5_create_encryption_key(struct mlx5_core_dev *mdev,
        case 128:
                general_obj_key_size =
                        MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_KEY_SIZE_128;
+               key_p += sz_bytes;
                break;
        case 256:
                general_obj_key_size =
index 4d34d42b3b0e8717e71ade78cfca02498dd3c102..eda9c23e87b28fcca50b8935e006fb9c94e990c3 100644 (file)
@@ -1604,14 +1604,14 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
        bool register_block = false;
        int err;
 
-       block_cb = flow_block_cb_lookup(f, mlxsw_sp_setup_tc_block_cb_flower,
+       block_cb = flow_block_cb_lookup(f->block,
+                                       mlxsw_sp_setup_tc_block_cb_flower,
                                        mlxsw_sp);
        if (!block_cb) {
                acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net);
                if (!acl_block)
                        return -ENOMEM;
-               block_cb = flow_block_cb_alloc(f->net,
-                                              mlxsw_sp_setup_tc_block_cb_flower,
+               block_cb = flow_block_cb_alloc(mlxsw_sp_setup_tc_block_cb_flower,
                                               mlxsw_sp, acl_block,
                                               mlxsw_sp_tc_block_flower_release);
                if (IS_ERR(block_cb)) {
@@ -1657,7 +1657,8 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
        struct flow_block_cb *block_cb;
        int err;
 
-       block_cb = flow_block_cb_lookup(f, mlxsw_sp_setup_tc_block_cb_flower,
+       block_cb = flow_block_cb_lookup(f->block,
+                                       mlxsw_sp_setup_tc_block_cb_flower,
                                        mlxsw_sp);
        if (!block_cb)
                return;
@@ -1680,7 +1681,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
                                   struct flow_block_offload *f)
 {
        struct flow_block_cb *block_cb;
-       tc_setup_cb_t *cb;
+       flow_setup_cb_t *cb;
        bool ingress;
        int err;
 
@@ -1702,7 +1703,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
                                          &mlxsw_sp_block_cb_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net, cb, mlxsw_sp_port,
+               block_cb = flow_block_cb_alloc(cb, mlxsw_sp_port,
                                               mlxsw_sp_port, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
@@ -1718,7 +1719,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
        case FLOW_BLOCK_UNBIND:
                mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
                                                      f, ingress);
-               block_cb = flow_block_cb_lookup(f, cb, mlxsw_sp_port);
+               block_cb = flow_block_cb_lookup(f->block, cb, mlxsw_sp_port);
                if (!block_cb)
                        return -ENOENT;
 
@@ -6329,7 +6330,7 @@ static int __init mlxsw_sp_module_init(void)
        return 0;
 
 err_sp2_pci_driver_register:
-       mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver);
+       mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
 err_sp1_pci_driver_register:
        mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
 err_sp2_core_driver_register:
index 131f62ce9297a05e0ba5406995beb1a16c14bdfa..6664119fb0c8cfc39ffd24c8963657de2e47c98b 100644 (file)
@@ -951,4 +951,8 @@ void mlxsw_sp_port_nve_fini(struct mlxsw_sp_port *mlxsw_sp_port);
 int mlxsw_sp_nve_init(struct mlxsw_sp *mlxsw_sp);
 void mlxsw_sp_nve_fini(struct mlxsw_sp *mlxsw_sp);
 
+/* spectrum_nve_vxlan.c */
+int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp);
+
 #endif
index e8ac90564dbe5ee36d3206542fa06145b51bfb3b..84a87d0593338845ef6d900d9ae865763729ead4 100644 (file)
@@ -471,7 +471,7 @@ int mlxsw_sp_acl_rulei_commit(struct mlxsw_sp_acl_rule_info *rulei)
 void mlxsw_sp_acl_rulei_priority(struct mlxsw_sp_acl_rule_info *rulei,
                                 unsigned int priority)
 {
-       rulei->priority = priority >> 16;
+       rulei->priority = priority;
 }
 
 void mlxsw_sp_acl_rulei_keymask_u32(struct mlxsw_sp_acl_rule_info *rulei,
index 1537f70bc26d0fbef771b91e4c92f6d9dae1ac4f..888ba4300bcc3b5d1888e7d3c87b28d51200e7f7 100644 (file)
@@ -437,8 +437,8 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = {
                           MLXSW_SP1_SB_PR_CPU_SIZE, true, false),
 };
 
-#define MLXSW_SP2_SB_PR_INGRESS_SIZE   38128752
-#define MLXSW_SP2_SB_PR_EGRESS_SIZE    38128752
+#define MLXSW_SP2_SB_PR_INGRESS_SIZE   35297568
+#define MLXSW_SP2_SB_PR_EGRESS_SIZE    35297568
 #define MLXSW_SP2_SB_PR_CPU_SIZE       (256 * 1000)
 
 /* Order according to mlxsw_sp2_sb_pool_dess */
index 1df164a4b06d3516b45dd034b8dbd71cb7988ab1..17f334b46c4056c6689d41d8288d3812a263a406 100644 (file)
@@ -775,6 +775,7 @@ static void mlxsw_sp_nve_tunnel_fini(struct mlxsw_sp *mlxsw_sp)
                ops->fini(nve);
                mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
                                   nve->tunnel_index);
+               memset(&nve->config, 0, sizeof(nve->config));
        }
        nve->num_nve_tunnels--;
 }
index 0035640156a16ebbee0391f8c105b4bbd455dfb0..12f664f42f2108abfc85b381959905713d8971cf 100644 (file)
@@ -29,6 +29,7 @@ struct mlxsw_sp_nve {
        unsigned int num_max_mc_entries[MLXSW_SP_L3_PROTO_MAX];
        u32 tunnel_index;
        u16 ul_rif_index;       /* Reserved for Spectrum */
+       unsigned int inc_parsing_depth_refs;
 };
 
 struct mlxsw_sp_nve_ops {
index 93ccd9fc22662d78ea91f12de0d9a2ea01ab4d30..05517c7feaa563fe0b8d1a365ce26980ea93b4a4 100644 (file)
@@ -103,9 +103,9 @@ static void mlxsw_sp_nve_vxlan_config(const struct mlxsw_sp_nve *nve,
        config->udp_dport = cfg->dst_port;
 }
 
-static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
-                                   unsigned int parsing_depth,
-                                   __be16 udp_dport)
+static int __mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
+                                     unsigned int parsing_depth,
+                                     __be16 udp_dport)
 {
        char mprs_pl[MLXSW_REG_MPRS_LEN];
 
@@ -113,6 +113,56 @@ static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
 }
 
+static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
+                                   __be16 udp_dport)
+{
+       int parsing_depth = mlxsw_sp->nve->inc_parsing_depth_refs ?
+                               MLXSW_SP_NVE_VXLAN_PARSING_DEPTH :
+                               MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH;
+
+       return __mlxsw_sp_nve_parsing_set(mlxsw_sp, parsing_depth, udp_dport);
+}
+
+static int
+__mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp,
+                                    __be16 udp_dport)
+{
+       int err;
+
+       mlxsw_sp->nve->inc_parsing_depth_refs++;
+
+       err = mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
+       if (err)
+               goto err_nve_parsing_set;
+       return 0;
+
+err_nve_parsing_set:
+       mlxsw_sp->nve->inc_parsing_depth_refs--;
+       return err;
+}
+
+static void
+__mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp,
+                                    __be16 udp_dport)
+{
+       mlxsw_sp->nve->inc_parsing_depth_refs--;
+       mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
+}
+
+int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp)
+{
+       __be16 udp_dport = mlxsw_sp->nve->config.udp_dport;
+
+       return __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, udp_dport);
+}
+
+void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp)
+{
+       __be16 udp_dport = mlxsw_sp->nve->config.udp_dport;
+
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, udp_dport);
+}
+
 static void
 mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl,
                                  const struct mlxsw_sp_nve_config *config)
@@ -176,9 +226,7 @@ static int mlxsw_sp1_nve_vxlan_init(struct mlxsw_sp_nve *nve,
        struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
        int err;
 
-       err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
-                                      MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
-                                      config->udp_dport);
+       err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
        if (err)
                return err;
 
@@ -203,8 +251,7 @@ err_promote_decap:
 err_rtdp_set:
        mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
 err_config_set:
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
        return err;
 }
 
@@ -216,8 +263,7 @@ static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
        mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
                                         config->ul_proto, &config->ul_sip);
        mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
 }
 
 static int
@@ -320,9 +366,7 @@ static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve,
        struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
        int err;
 
-       err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
-                                      MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
-                                      config->udp_dport);
+       err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
        if (err)
                return err;
 
@@ -348,8 +392,7 @@ err_promote_decap:
 err_rtdp_set:
        mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
 err_config_set:
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
        return err;
 }
 
@@ -361,8 +404,7 @@ static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
        mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
                                         config->ul_proto, &config->ul_sip);
        mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
 }
 
 const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = {
index bd9c2bc2d5d6e0569935ad77aedf56f1db198594..38bb1cfe4e8c566153c138b61babb7b59bc58059 100644 (file)
@@ -29,7 +29,7 @@
 
 struct mlxsw_sp_ptp_state {
        struct mlxsw_sp *mlxsw_sp;
-       struct rhashtable unmatched_ht;
+       struct rhltable unmatched_ht;
        spinlock_t unmatched_lock; /* protects the HT */
        struct delayed_work ht_gc_dw;
        u32 gc_cycle;
@@ -45,7 +45,7 @@ struct mlxsw_sp1_ptp_key {
 
 struct mlxsw_sp1_ptp_unmatched {
        struct mlxsw_sp1_ptp_key key;
-       struct rhash_head ht_node;
+       struct rhlist_head ht_node;
        struct rcu_head rcu;
        struct sk_buff *skb;
        u64 timestamp;
@@ -359,7 +359,7 @@ static int mlxsw_sp_ptp_parse(struct sk_buff *skb,
 /* Returns NULL on successful insertion, a pointer on conflict, or an ERR_PTR on
  * error.
  */
-static struct mlxsw_sp1_ptp_unmatched *
+static int
 mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp,
                             struct mlxsw_sp1_ptp_key key,
                             struct sk_buff *skb,
@@ -368,41 +368,51 @@ mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp,
        int cycles = MLXSW_SP1_PTP_HT_GC_TIMEOUT / MLXSW_SP1_PTP_HT_GC_INTERVAL;
        struct mlxsw_sp_ptp_state *ptp_state = mlxsw_sp->ptp_state;
        struct mlxsw_sp1_ptp_unmatched *unmatched;
-       struct mlxsw_sp1_ptp_unmatched *conflict;
+       int err;
 
        unmatched = kzalloc(sizeof(*unmatched), GFP_ATOMIC);
        if (!unmatched)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
        unmatched->key = key;
        unmatched->skb = skb;
        unmatched->timestamp = timestamp;
        unmatched->gc_cycle = mlxsw_sp->ptp_state->gc_cycle + cycles;
 
-       conflict = rhashtable_lookup_get_insert_fast(&ptp_state->unmatched_ht,
-                                           &unmatched->ht_node,
-                                           mlxsw_sp1_ptp_unmatched_ht_params);
-       if (conflict)
+       err = rhltable_insert(&ptp_state->unmatched_ht, &unmatched->ht_node,
+                             mlxsw_sp1_ptp_unmatched_ht_params);
+       if (err)
                kfree(unmatched);
 
-       return conflict;
+       return err;
 }
 
 static struct mlxsw_sp1_ptp_unmatched *
 mlxsw_sp1_ptp_unmatched_lookup(struct mlxsw_sp *mlxsw_sp,
-                              struct mlxsw_sp1_ptp_key key)
+                              struct mlxsw_sp1_ptp_key key, int *p_length)
 {
-       return rhashtable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key,
-                                mlxsw_sp1_ptp_unmatched_ht_params);
+       struct mlxsw_sp1_ptp_unmatched *unmatched, *last = NULL;
+       struct rhlist_head *tmp, *list;
+       int length = 0;
+
+       list = rhltable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key,
+                              mlxsw_sp1_ptp_unmatched_ht_params);
+       rhl_for_each_entry_rcu(unmatched, tmp, list, ht_node) {
+               last = unmatched;
+               length++;
+       }
+
+       *p_length = length;
+       return last;
 }
 
 static int
 mlxsw_sp1_ptp_unmatched_remove(struct mlxsw_sp *mlxsw_sp,
                               struct mlxsw_sp1_ptp_unmatched *unmatched)
 {
-       return rhashtable_remove_fast(&mlxsw_sp->ptp_state->unmatched_ht,
-                                     &unmatched->ht_node,
-                                     mlxsw_sp1_ptp_unmatched_ht_params);
+       return rhltable_remove(&mlxsw_sp->ptp_state->unmatched_ht,
+                              &unmatched->ht_node,
+                              mlxsw_sp1_ptp_unmatched_ht_params);
 }
 
 /* This function is called in the following scenarios:
@@ -489,75 +499,38 @@ static void mlxsw_sp1_ptp_got_piece(struct mlxsw_sp *mlxsw_sp,
                                    struct mlxsw_sp1_ptp_key key,
                                    struct sk_buff *skb, u64 timestamp)
 {
-       struct mlxsw_sp1_ptp_unmatched *unmatched, *conflict;
+       struct mlxsw_sp1_ptp_unmatched *unmatched;
+       int length;
        int err;
 
        rcu_read_lock();
 
-       unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key);
-
        spin_lock(&mlxsw_sp->ptp_state->unmatched_lock);
 
-       if (unmatched) {
-               /* There was an unmatched entry when we looked, but it may have
-                * been removed before we took the lock.
-                */
-               err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp, unmatched);
-               if (err)
-                       unmatched = NULL;
-       }
-
-       if (!unmatched) {
-               /* We have no unmatched entry, but one may have been added after
-                * we looked, but before we took the lock.
-                */
-               unmatched = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
-                                                        skb, timestamp);
-               if (IS_ERR(unmatched)) {
-                       if (skb)
-                               mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
-                                                           key.local_port,
-                                                           key.ingress, NULL);
-                       unmatched = NULL;
-               } else if (unmatched) {
-                       /* Save just told us, under lock, that the entry is
-                        * there, so this has to work.
-                        */
-                       err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp,
-                                                            unmatched);
-                       WARN_ON_ONCE(err);
-               }
-       }
-
-       /* If unmatched is non-NULL here, it comes either from the lookup, or
-        * from the save attempt above. In either case the entry was removed
-        * from the hash table. If unmatched is NULL, a new unmatched entry was
-        * added to the hash table, and there was no conflict.
-        */
-
+       unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key, &length);
        if (skb && unmatched && unmatched->timestamp) {
                unmatched->skb = skb;
        } else if (timestamp && unmatched && unmatched->skb) {
                unmatched->timestamp = timestamp;
-       } else if (unmatched) {
-               /* unmatched holds an older entry of the same type: either an
-                * skb if we are handling skb, or a timestamp if we are handling
-                * timestamp. We can't match that up, so save what we have.
+       } else {
+               /* Either there is no entry to match, or one that is there is
+                * incompatible.
                 */
-               conflict = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
-                                                       skb, timestamp);
-               if (IS_ERR(conflict)) {
-                       if (skb)
-                               mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
-                                                           key.local_port,
-                                                           key.ingress, NULL);
-               } else {
-                       /* Above, we removed an object with this key from the
-                        * hash table, under lock, so conflict can not be a
-                        * valid pointer.
-                        */
-                       WARN_ON_ONCE(conflict);
-               }
+               if (length < 100)
+                       err = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
+                                                          skb, timestamp);
+               else
+                       err = -E2BIG;
+               if (err && skb)
+                       mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
+                                                   key.local_port,
+                                                   key.ingress, NULL);
+               unmatched = NULL;
+       }
+
+       if (unmatched) {
+               err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp, unmatched);
+               WARN_ON_ONCE(err);
        }
 
        spin_unlock(&mlxsw_sp->ptp_state->unmatched_lock);
@@ -669,9 +642,8 @@ mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state,
        local_bh_disable();
 
        spin_lock(&ptp_state->unmatched_lock);
-       err = rhashtable_remove_fast(&ptp_state->unmatched_ht,
-                                    &unmatched->ht_node,
-                                    mlxsw_sp1_ptp_unmatched_ht_params);
+       err = rhltable_remove(&ptp_state->unmatched_ht, &unmatched->ht_node,
+                             mlxsw_sp1_ptp_unmatched_ht_params);
        spin_unlock(&ptp_state->unmatched_lock);
 
        if (err)
@@ -702,7 +674,7 @@ static void mlxsw_sp1_ptp_ht_gc(struct work_struct *work)
        ptp_state = container_of(dwork, struct mlxsw_sp_ptp_state, ht_gc_dw);
        gc_cycle = ptp_state->gc_cycle++;
 
-       rhashtable_walk_enter(&ptp_state->unmatched_ht, &iter);
+       rhltable_walk_enter(&ptp_state->unmatched_ht, &iter);
        rhashtable_walk_start(&iter);
        while ((obj = rhashtable_walk_next(&iter))) {
                if (IS_ERR(obj))
@@ -855,8 +827,8 @@ struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp)
 
        spin_lock_init(&ptp_state->unmatched_lock);
 
-       err = rhashtable_init(&ptp_state->unmatched_ht,
-                             &mlxsw_sp1_ptp_unmatched_ht_params);
+       err = rhltable_init(&ptp_state->unmatched_ht,
+                           &mlxsw_sp1_ptp_unmatched_ht_params);
        if (err)
                goto err_hashtable_init;
 
@@ -891,7 +863,7 @@ err_fifo_clr:
 err_mtptpt1_set:
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP0, 0);
 err_mtptpt_set:
-       rhashtable_destroy(&ptp_state->unmatched_ht);
+       rhltable_destroy(&ptp_state->unmatched_ht);
 err_hashtable_init:
        kfree(ptp_state);
        return ERR_PTR(err);
@@ -906,8 +878,8 @@ void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state)
        mlxsw_sp1_ptp_set_fifo_clr_on_trap(mlxsw_sp, false);
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP1, 0);
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP0, 0);
-       rhashtable_free_and_destroy(&ptp_state->unmatched_ht,
-                                   &mlxsw_sp1_ptp_unmatched_free_fn, NULL);
+       rhltable_free_and_destroy(&ptp_state->unmatched_ht,
+                                 &mlxsw_sp1_ptp_unmatched_free_fn, NULL);
        kfree(ptp_state);
 }
 
@@ -979,6 +951,9 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        struct mlxsw_sp_port *tmp;
+       u16 orig_ing_types = 0;
+       u16 orig_egr_types = 0;
+       int err;
        int i;
 
        /* MTPPPC configures timestamping globally, not per port. Find the
@@ -986,12 +961,26 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
         */
        for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++) {
                tmp = mlxsw_sp->ports[i];
+               if (tmp) {
+                       orig_ing_types |= tmp->ptp.ing_types;
+                       orig_egr_types |= tmp->ptp.egr_types;
+               }
                if (tmp && tmp != mlxsw_sp_port) {
                        ing_types |= tmp->ptp.ing_types;
                        egr_types |= tmp->ptp.egr_types;
                }
        }
 
+       if ((ing_types || egr_types) && !(orig_ing_types || orig_egr_types)) {
+               err = mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp);
+               if (err) {
+                       netdev_err(mlxsw_sp_port->dev, "Failed to increase parsing depth");
+                       return err;
+               }
+       }
+       if (!(ing_types || egr_types) && (orig_ing_types || orig_egr_types))
+               mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp);
+
        return mlxsw_sp1_ptp_mtpppc_set(mlxsw_sp_port->mlxsw_sp,
                                       ing_types, egr_types);
 }
index b71e4ecbe469a5ec19699ed740ab0a9e63abdd45..6932e615d4b089c68b4d847649bd3adb0f70d543 100644 (file)
@@ -1818,6 +1818,7 @@ EXPORT_SYMBOL(ocelot_init);
 
 void ocelot_deinit(struct ocelot *ocelot)
 {
+       cancel_delayed_work(&ocelot->stats_work);
        destroy_workqueue(ocelot->stats_queue);
        mutex_destroy(&ocelot->stats_lock);
        ocelot_ace_deinit();
index 39aca1ab46878330e60a939550dc7e52089eb8b3..86fc6e6b46dd481838c8a75740917abcf6d19569 100644 (file)
@@ -317,7 +317,7 @@ static void is2_action_set(struct vcap_data *data,
                break;
        case OCELOT_ACL_ACTION_TRAP:
                VCAP_ACT_SET(PORT_MASK, 0x0);
-               VCAP_ACT_SET(MASK_MODE, 0x0);
+               VCAP_ACT_SET(MASK_MODE, 0x1);
                VCAP_ACT_SET(POLICE_ENA, 0x0);
                VCAP_ACT_SET(POLICE_IDX, 0x0);
                VCAP_ACT_SET(CPU_QU_NUM, 0x0);
index 7aaddc09c1851e4f3ce456cfeff003514621cdf3..b894bc0c9c1685c31d449fd61ab6466db5258c17 100644 (file)
@@ -13,12 +13,6 @@ struct ocelot_port_block {
        struct ocelot_port *port;
 };
 
-static u16 get_prio(u32 prio)
-{
-       /* prio starts from 0x1000 while the ids starts from 0 */
-       return prio >> 16;
-}
-
 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
                                      struct ocelot_ace_rule *rule)
 {
@@ -168,7 +162,7 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
        }
 
 finished_key_parsing:
-       ocelot_rule->prio = get_prio(f->common.prio);
+       ocelot_rule->prio = f->common.prio;
        ocelot_rule->id = f->cookie;
        return ocelot_flower_parse_action(f, ocelot_rule);
 }
@@ -218,7 +212,7 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f,
        struct ocelot_ace_rule rule;
        int ret;
 
-       rule.prio = get_prio(f->common.prio);
+       rule.prio = f->common.prio;
        rule.port = port_block->port;
        rule.id = f->cookie;
 
@@ -236,7 +230,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f,
        struct ocelot_ace_rule rule;
        int ret;
 
-       rule.prio = get_prio(f->common.prio);
+       rule.prio = f->common.prio;
        rule.port = port_block->port;
        rule.id = f->cookie;
        ret = ocelot_ace_rule_stats_update(&rule);
@@ -316,15 +310,14 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
        if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
                return -EOPNOTSUPP;
 
-       block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
-                                       port);
+       block_cb = flow_block_cb_lookup(f->block,
+                                       ocelot_setup_tc_block_cb_flower, port);
        if (!block_cb) {
                port_block = ocelot_port_block_create(port);
                if (!port_block)
                        return -ENOMEM;
 
-               block_cb = flow_block_cb_alloc(f->net,
-                                              ocelot_setup_tc_block_cb_flower,
+               block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower,
                                               port, port_block,
                                               ocelot_tc_block_unbind);
                if (IS_ERR(block_cb)) {
@@ -351,8 +344,8 @@ void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
 {
        struct flow_block_cb *block_cb;
 
-       block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
-                                       port);
+       block_cb = flow_block_cb_lookup(f->block,
+                                       ocelot_setup_tc_block_cb_flower, port);
        if (!block_cb)
                return;
 
index 9e6464ffae5d1d6d4a9490119071d92e0281f86c..16a6db71ca5e7eeabb53bd7aed58d7d130ffe890 100644 (file)
@@ -134,7 +134,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
                                 struct flow_block_offload *f)
 {
        struct flow_block_cb *block_cb;
-       tc_setup_cb_t *cb;
+       flow_setup_cb_t *cb;
        int err;
 
        netdev_dbg(port->dev, "tc_block command %d, binder_type %d\n",
@@ -156,7 +156,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
                if (flow_block_cb_is_busy(cb, port, &ocelot_block_cb_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net, cb, port, port, NULL);
+               block_cb = flow_block_cb_alloc(cb, port, port, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
 
@@ -169,7 +169,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
                list_add_tail(&block_cb->driver_list, f->driver_block_list);
                return 0;
        case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f, cb, port);
+               block_cb = flow_block_cb_lookup(f->block, cb, port);
                if (!block_cb)
                        return -ENOENT;
 
index d8b7fba96d58ed109a4962e0128909f9ea283e50..337b0cbfd153ef6bdabcbd8f4e26a1b21bfb2b00 100644 (file)
@@ -3919,7 +3919,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * setup (if available). */
        status = myri10ge_request_irq(mgp);
        if (status != 0)
-               goto abort_with_firmware;
+               goto abort_with_slices;
        myri10ge_free_irq(mgp);
 
        /* Save configuration space to be restored if the
index d0a01e8f000aee71413425d94efc921856a062f7..b339125b2f097fcfdafd7e45f9ee8c5eeac5190a 100644 (file)
@@ -232,9 +232,9 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
 
        laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
        if (!laddr) {
-               printk(KERN_ERR "%s: failed to map tx DMA buffer.\n", dev->name);
-               dev_kfree_skb(skb);
-               return NETDEV_TX_BUSY;
+               pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
        }
 
        sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0);       /* clear status */
index 4054b70d77196d2fb21d2c337487aaeb06393a50..5afcb3c4c2ef115709a266d42bdcb2b9cd997416 100644 (file)
@@ -1163,7 +1163,7 @@ mem_op_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
             bool clr_gpr, lmem_step step)
 {
        s32 off = nfp_prog->stack_frame_depth + meta->insn.off + ptr_off;
-       bool first = true, last;
+       bool first = true, narrow_ld, last;
        bool needs_inc = false;
        swreg stack_off_reg;
        u8 prev_gpr = 255;
@@ -1209,13 +1209,22 @@ mem_op_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
 
                needs_inc = true;
        }
+
+       narrow_ld = clr_gpr && size < 8;
+
        if (lm3) {
+               unsigned int nop_cnt;
+
                emit_csr_wr(nfp_prog, imm_b(nfp_prog), NFP_CSR_ACT_LM_ADDR3);
-               /* For size < 4 one slot will be filled by zeroing of upper. */
-               wrp_nops(nfp_prog, clr_gpr && size < 8 ? 2 : 3);
+               /* For size < 4 one slot will be filled by zeroing of upper,
+                * but be careful, that zeroing could be eliminated by zext
+                * optimization.
+                */
+               nop_cnt = narrow_ld && meta->flags & FLAG_INSN_DO_ZEXT ? 2 : 3;
+               wrp_nops(nfp_prog, nop_cnt);
        }
 
-       if (clr_gpr && size < 8)
+       if (narrow_ld)
                wrp_zext(nfp_prog, meta, gpr);
 
        while (size) {
index d5bbe3d6048bf3cec01fc5aadce5c75cc0d5f066..05981b54eaab7dccd70d0f90dd90508c230481ad 100644 (file)
@@ -260,9 +260,6 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
 
        type = cmsg_hdr->type;
        switch (type) {
-       case NFP_FLOWER_CMSG_TYPE_PORT_REIFY:
-               nfp_flower_cmsg_portreify_rx(app, skb);
-               break;
        case NFP_FLOWER_CMSG_TYPE_PORT_MOD:
                nfp_flower_cmsg_portmod_rx(app, skb);
                break;
@@ -328,8 +325,7 @@ nfp_flower_queue_ctl_msg(struct nfp_app *app, struct sk_buff *skb, int type)
        struct nfp_flower_priv *priv = app->priv;
        struct sk_buff_head *skb_head;
 
-       if (type == NFP_FLOWER_CMSG_TYPE_PORT_REIFY ||
-           type == NFP_FLOWER_CMSG_TYPE_PORT_MOD)
+       if (type == NFP_FLOWER_CMSG_TYPE_PORT_MOD)
                skb_head = &priv->cmsg_skbs_high;
        else
                skb_head = &priv->cmsg_skbs_low;
@@ -368,6 +364,10 @@ void nfp_flower_cmsg_rx(struct nfp_app *app, struct sk_buff *skb)
        } else if (cmsg_hdr->type == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH) {
                /* Acks from the NFP that the route is added - ignore. */
                dev_consume_skb_any(skb);
+       } else if (cmsg_hdr->type == NFP_FLOWER_CMSG_TYPE_PORT_REIFY) {
+               /* Handle REIFY acks outside wq to prevent RTNL conflict. */
+               nfp_flower_cmsg_portreify_rx(app, skb);
+               dev_consume_skb_any(skb);
        } else {
                nfp_flower_queue_ctl_msg(app, skb, cmsg_hdr->type);
        }
index faa8ba012a374f9c623c292b8470e46967f7df2f..457bdc60f3ee8027bff83198c83bf7c612d67782 100644 (file)
@@ -1318,8 +1318,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
                                          &nfp_block_cb_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net,
-                                              nfp_flower_setup_tc_block_cb,
+               block_cb = flow_block_cb_alloc(nfp_flower_setup_tc_block_cb,
                                               repr, repr, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
@@ -1328,7 +1327,8 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
                list_add_tail(&block_cb->driver_list, &nfp_block_cb_list);
                return 0;
        case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f, nfp_flower_setup_tc_block_cb,
+               block_cb = flow_block_cb_lookup(f->block,
+                                               nfp_flower_setup_tc_block_cb,
                                                repr);
                if (!block_cb)
                        return -ENOENT;
@@ -1409,13 +1409,21 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
        struct nfp_flower_priv *priv = app->priv;
        struct flow_block_cb *block_cb;
 
-       if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
-           !(f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
-             nfp_flower_internal_port_can_offload(app, netdev)))
+       if ((f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
+            !nfp_flower_internal_port_can_offload(app, netdev)) ||
+           (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
+            nfp_flower_internal_port_can_offload(app, netdev)))
                return -EOPNOTSUPP;
 
        switch (f->command) {
        case FLOW_BLOCK_BIND:
+               cb_priv = nfp_flower_indr_block_cb_priv_lookup(app, netdev);
+               if (cb_priv &&
+                   flow_block_cb_is_busy(nfp_flower_setup_indr_block_cb,
+                                         cb_priv,
+                                         &nfp_block_cb_list))
+                       return -EBUSY;
+
                cb_priv = kmalloc(sizeof(*cb_priv), GFP_KERNEL);
                if (!cb_priv)
                        return -ENOMEM;
@@ -1424,8 +1432,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
                cb_priv->app = app;
                list_add(&cb_priv->list, &priv->indr_block_cb_priv);
 
-               block_cb = flow_block_cb_alloc(f->net,
-                                              nfp_flower_setup_indr_block_cb,
+               block_cb = flow_block_cb_alloc(nfp_flower_setup_indr_block_cb,
                                               cb_priv, cb_priv,
                                               nfp_flower_setup_indr_tc_release);
                if (IS_ERR(block_cb)) {
@@ -1442,7 +1449,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
                if (!cb_priv)
                        return -ENOENT;
 
-               block_cb = flow_block_cb_lookup(f,
+               block_cb = flow_block_cb_lookup(f->block,
                                                nfp_flower_setup_indr_block_cb,
                                                cb_priv);
                if (!block_cb)
index 86e968cd5ffd3dc6ce9cc17ef29bffeb59ec5caa..124a43dc136a8a28ba1e4a971f6ded621cfaf7e6 100644 (file)
@@ -93,7 +93,7 @@ nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev,
                return -EOPNOTSUPP;
        }
 
-       if (flow->common.prio != (1 << 16)) {
+       if (flow->common.prio != 1) {
                NL_SET_ERR_MSG_MOD(extack, "unsupported offload: qos rate limit offload requires highest priority");
                return -EOPNOTSUPP;
        }
index a7a80f4b722a9d7dc2d5efa7d5b89fc93bedcb33..f0ee982eb1b5f27672292997477f565545729e22 100644 (file)
@@ -328,13 +328,13 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
 
        flow.daddr = *(__be32 *)n->primary_key;
 
-       /* Only concerned with route changes for representors. */
-       if (!nfp_netdev_is_nfp_repr(n->dev))
-               return NOTIFY_DONE;
-
        app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
        app = app_priv->app;
 
+       if (!nfp_netdev_is_nfp_repr(n->dev) &&
+           !nfp_flower_internal_port_can_offload(app, n->dev))
+               return NOTIFY_DONE;
+
        /* Only concerned with changes to routes already added to NFP. */
        if (!nfp_tun_has_route(app, flow.daddr))
                return NOTIFY_DONE;
index d9cbe84ac6ade4105af2e9c93a2f847f944cf8f6..1b840ee4733969a4b61e74e98bf2bfcd3ad2aecb 100644 (file)
@@ -444,12 +444,12 @@ static u8 *nfp_vnic_get_sw_stats_strings(struct net_device *netdev, u8 *data)
        data = nfp_pr_et(data, "hw_rx_csum_complete");
        data = nfp_pr_et(data, "hw_rx_csum_err");
        data = nfp_pr_et(data, "rx_replace_buf_alloc_fail");
-       data = nfp_pr_et(data, "rx_tls_decrypted");
+       data = nfp_pr_et(data, "rx_tls_decrypted_packets");
        data = nfp_pr_et(data, "hw_tx_csum");
        data = nfp_pr_et(data, "hw_tx_inner_csum");
        data = nfp_pr_et(data, "tx_gather");
        data = nfp_pr_et(data, "tx_lso");
-       data = nfp_pr_et(data, "tx_tls_encrypted");
+       data = nfp_pr_et(data, "tx_tls_encrypted_packets");
        data = nfp_pr_et(data, "tx_tls_ooo");
        data = nfp_pr_et(data, "tx_tls_drop_no_sync_data");
 
index 70b1a03c0953e696a92f51769e1db6388a55cab7..01229190132d484ff7d44ccc8606960d4bb76171 100644 (file)
@@ -11,7 +11,7 @@ config NET_VENDOR_NI
 
          Note that the answer to this question doesn't directly affect the
          kernel: saying N will just cause the configurator to skip all
-         the questions about National Instrument devices.
+         the questions about National Instruments devices.
          If you say Y, you will be asked for your specific device in the
          following questions.
 
index b327b29f5d577a3f72bbeb3b744ecda2cb27219f..a6b4bfae4684fbbfdc1d83125c11cf55d920a9b0 100644 (file)
@@ -713,6 +713,21 @@ struct nv_skb_map {
        struct nv_skb_map *next_tx_ctx;
 };
 
+struct nv_txrx_stats {
+       u64 stat_rx_packets;
+       u64 stat_rx_bytes; /* not always available in HW */
+       u64 stat_rx_missed_errors;
+       u64 stat_rx_dropped;
+       u64 stat_tx_packets; /* not always available in HW */
+       u64 stat_tx_bytes;
+       u64 stat_tx_dropped;
+};
+
+#define nv_txrx_stats_inc(member) \
+               __this_cpu_inc(np->txrx_stats->member)
+#define nv_txrx_stats_add(member, count) \
+               __this_cpu_add(np->txrx_stats->member, (count))
+
 /*
  * SMP locking:
  * All hardware access under netdev_priv(dev)->lock, except the performance
@@ -797,10 +812,7 @@ struct fe_priv {
 
        /* RX software stats */
        struct u64_stats_sync swstats_rx_syncp;
-       u64 stat_rx_packets;
-       u64 stat_rx_bytes; /* not always available in HW */
-       u64 stat_rx_missed_errors;
-       u64 stat_rx_dropped;
+       struct nv_txrx_stats __percpu *txrx_stats;
 
        /* media detection workaround.
         * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
@@ -826,9 +838,6 @@ struct fe_priv {
 
        /* TX software stats */
        struct u64_stats_sync swstats_tx_syncp;
-       u64 stat_tx_packets; /* not always available in HW */
-       u64 stat_tx_bytes;
-       u64 stat_tx_dropped;
 
        /* msi/msi-x fields */
        u32 msi_flags;
@@ -1721,6 +1730,39 @@ static void nv_update_stats(struct net_device *dev)
        }
 }
 
+static void nv_get_stats(int cpu, struct fe_priv *np,
+                        struct rtnl_link_stats64 *storage)
+{
+       struct nv_txrx_stats *src = per_cpu_ptr(np->txrx_stats, cpu);
+       unsigned int syncp_start;
+       u64 rx_packets, rx_bytes, rx_dropped, rx_missed_errors;
+       u64 tx_packets, tx_bytes, tx_dropped;
+
+       do {
+               syncp_start = u64_stats_fetch_begin_irq(&np->swstats_rx_syncp);
+               rx_packets       = src->stat_rx_packets;
+               rx_bytes         = src->stat_rx_bytes;
+               rx_dropped       = src->stat_rx_dropped;
+               rx_missed_errors = src->stat_rx_missed_errors;
+       } while (u64_stats_fetch_retry_irq(&np->swstats_rx_syncp, syncp_start));
+
+       storage->rx_packets       += rx_packets;
+       storage->rx_bytes         += rx_bytes;
+       storage->rx_dropped       += rx_dropped;
+       storage->rx_missed_errors += rx_missed_errors;
+
+       do {
+               syncp_start = u64_stats_fetch_begin_irq(&np->swstats_tx_syncp);
+               tx_packets  = src->stat_tx_packets;
+               tx_bytes    = src->stat_tx_bytes;
+               tx_dropped  = src->stat_tx_dropped;
+       } while (u64_stats_fetch_retry_irq(&np->swstats_tx_syncp, syncp_start));
+
+       storage->tx_packets += tx_packets;
+       storage->tx_bytes   += tx_bytes;
+       storage->tx_dropped += tx_dropped;
+}
+
 /*
  * nv_get_stats64: dev->ndo_get_stats64 function
  * Get latest stats value from the nic.
@@ -1733,7 +1775,7 @@ nv_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *storage)
        __releases(&netdev_priv(dev)->hwstats_lock)
 {
        struct fe_priv *np = netdev_priv(dev);
-       unsigned int syncp_start;
+       int cpu;
 
        /*
         * Note: because HW stats are not always available and for
@@ -1746,20 +1788,8 @@ nv_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *storage)
         */
 
        /* software stats */
-       do {
-               syncp_start = u64_stats_fetch_begin_irq(&np->swstats_rx_syncp);
-               storage->rx_packets       = np->stat_rx_packets;
-               storage->rx_bytes         = np->stat_rx_bytes;
-               storage->rx_dropped       = np->stat_rx_dropped;
-               storage->rx_missed_errors = np->stat_rx_missed_errors;
-       } while (u64_stats_fetch_retry_irq(&np->swstats_rx_syncp, syncp_start));
-
-       do {
-               syncp_start = u64_stats_fetch_begin_irq(&np->swstats_tx_syncp);
-               storage->tx_packets = np->stat_tx_packets;
-               storage->tx_bytes   = np->stat_tx_bytes;
-               storage->tx_dropped = np->stat_tx_dropped;
-       } while (u64_stats_fetch_retry_irq(&np->swstats_tx_syncp, syncp_start));
+       for_each_online_cpu(cpu)
+               nv_get_stats(cpu, np, storage);
 
        /* If the nic supports hw counters then retrieve latest values */
        if (np->driver_data & DEV_HAS_STATISTICS_V123) {
@@ -1827,7 +1857,7 @@ static int nv_alloc_rx(struct net_device *dev)
                } else {
 packet_dropped:
                        u64_stats_update_begin(&np->swstats_rx_syncp);
-                       np->stat_rx_dropped++;
+                       nv_txrx_stats_inc(stat_rx_dropped);
                        u64_stats_update_end(&np->swstats_rx_syncp);
                        return 1;
                }
@@ -1869,7 +1899,7 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
                } else {
 packet_dropped:
                        u64_stats_update_begin(&np->swstats_rx_syncp);
-                       np->stat_rx_dropped++;
+                       nv_txrx_stats_inc(stat_rx_dropped);
                        u64_stats_update_end(&np->swstats_rx_syncp);
                        return 1;
                }
@@ -2013,7 +2043,7 @@ static void nv_drain_tx(struct net_device *dev)
                }
                if (nv_release_txskb(np, &np->tx_skb[i])) {
                        u64_stats_update_begin(&np->swstats_tx_syncp);
-                       np->stat_tx_dropped++;
+                       nv_txrx_stats_inc(stat_tx_dropped);
                        u64_stats_update_end(&np->swstats_tx_syncp);
                }
                np->tx_skb[i].dma = 0;
@@ -2227,7 +2257,7 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        /* on DMA mapping error - drop the packet */
                        dev_kfree_skb_any(skb);
                        u64_stats_update_begin(&np->swstats_tx_syncp);
-                       np->stat_tx_dropped++;
+                       nv_txrx_stats_inc(stat_tx_dropped);
                        u64_stats_update_end(&np->swstats_tx_syncp);
                        return NETDEV_TX_OK;
                }
@@ -2273,7 +2303,7 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                dev_kfree_skb_any(skb);
                                np->put_tx_ctx = start_tx_ctx;
                                u64_stats_update_begin(&np->swstats_tx_syncp);
-                               np->stat_tx_dropped++;
+                               nv_txrx_stats_inc(stat_tx_dropped);
                                u64_stats_update_end(&np->swstats_tx_syncp);
                                return NETDEV_TX_OK;
                        }
@@ -2384,7 +2414,7 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
                        /* on DMA mapping error - drop the packet */
                        dev_kfree_skb_any(skb);
                        u64_stats_update_begin(&np->swstats_tx_syncp);
-                       np->stat_tx_dropped++;
+                       nv_txrx_stats_inc(stat_tx_dropped);
                        u64_stats_update_end(&np->swstats_tx_syncp);
                        return NETDEV_TX_OK;
                }
@@ -2431,7 +2461,7 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb,
                                dev_kfree_skb_any(skb);
                                np->put_tx_ctx = start_tx_ctx;
                                u64_stats_update_begin(&np->swstats_tx_syncp);
-                               np->stat_tx_dropped++;
+                               nv_txrx_stats_inc(stat_tx_dropped);
                                u64_stats_update_end(&np->swstats_tx_syncp);
                                return NETDEV_TX_OK;
                        }
@@ -2560,9 +2590,12 @@ static int nv_tx_done(struct net_device *dev, int limit)
                                            && !(flags & NV_TX_RETRYCOUNT_MASK))
                                                nv_legacybackoff_reseed(dev);
                                } else {
+                                       unsigned int len;
+
                                        u64_stats_update_begin(&np->swstats_tx_syncp);
-                                       np->stat_tx_packets++;
-                                       np->stat_tx_bytes += np->get_tx_ctx->skb->len;
+                                       nv_txrx_stats_inc(stat_tx_packets);
+                                       len = np->get_tx_ctx->skb->len;
+                                       nv_txrx_stats_add(stat_tx_bytes, len);
                                        u64_stats_update_end(&np->swstats_tx_syncp);
                                }
                                bytes_compl += np->get_tx_ctx->skb->len;
@@ -2577,9 +2610,12 @@ static int nv_tx_done(struct net_device *dev, int limit)
                                            && !(flags & NV_TX2_RETRYCOUNT_MASK))
                                                nv_legacybackoff_reseed(dev);
                                } else {
+                                       unsigned int len;
+
                                        u64_stats_update_begin(&np->swstats_tx_syncp);
-                                       np->stat_tx_packets++;
-                                       np->stat_tx_bytes += np->get_tx_ctx->skb->len;
+                                       nv_txrx_stats_inc(stat_tx_packets);
+                                       len = np->get_tx_ctx->skb->len;
+                                       nv_txrx_stats_add(stat_tx_bytes, len);
                                        u64_stats_update_end(&np->swstats_tx_syncp);
                                }
                                bytes_compl += np->get_tx_ctx->skb->len;
@@ -2627,9 +2663,12 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit)
                                                nv_legacybackoff_reseed(dev);
                                }
                        } else {
+                               unsigned int len;
+
                                u64_stats_update_begin(&np->swstats_tx_syncp);
-                               np->stat_tx_packets++;
-                               np->stat_tx_bytes += np->get_tx_ctx->skb->len;
+                               nv_txrx_stats_inc(stat_tx_packets);
+                               len = np->get_tx_ctx->skb->len;
+                               nv_txrx_stats_add(stat_tx_bytes, len);
                                u64_stats_update_end(&np->swstats_tx_syncp);
                        }
 
@@ -2806,6 +2845,15 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
        }
 }
 
+static void rx_missing_handler(u32 flags, struct fe_priv *np)
+{
+       if (flags & NV_RX_MISSEDFRAME) {
+               u64_stats_update_begin(&np->swstats_rx_syncp);
+               nv_txrx_stats_inc(stat_rx_missed_errors);
+               u64_stats_update_end(&np->swstats_rx_syncp);
+       }
+}
+
 static int nv_rx_process(struct net_device *dev, int limit)
 {
        struct fe_priv *np = netdev_priv(dev);
@@ -2848,11 +2896,7 @@ static int nv_rx_process(struct net_device *dev, int limit)
                                        }
                                        /* the rest are hard errors */
                                        else {
-                                               if (flags & NV_RX_MISSEDFRAME) {
-                                                       u64_stats_update_begin(&np->swstats_rx_syncp);
-                                                       np->stat_rx_missed_errors++;
-                                                       u64_stats_update_end(&np->swstats_rx_syncp);
-                                               }
+                                               rx_missing_handler(flags, np);
                                                dev_kfree_skb(skb);
                                                goto next_pkt;
                                        }
@@ -2896,8 +2940,8 @@ static int nv_rx_process(struct net_device *dev, int limit)
                skb->protocol = eth_type_trans(skb, dev);
                napi_gro_receive(&np->napi, skb);
                u64_stats_update_begin(&np->swstats_rx_syncp);
-               np->stat_rx_packets++;
-               np->stat_rx_bytes += len;
+               nv_txrx_stats_inc(stat_rx_packets);
+               nv_txrx_stats_add(stat_rx_bytes, len);
                u64_stats_update_end(&np->swstats_rx_syncp);
 next_pkt:
                if (unlikely(np->get_rx.orig++ == np->last_rx.orig))
@@ -2982,8 +3026,8 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
                        }
                        napi_gro_receive(&np->napi, skb);
                        u64_stats_update_begin(&np->swstats_rx_syncp);
-                       np->stat_rx_packets++;
-                       np->stat_rx_bytes += len;
+                       nv_txrx_stats_inc(stat_rx_packets);
+                       nv_txrx_stats_add(stat_rx_bytes, len);
                        u64_stats_update_end(&np->swstats_rx_syncp);
                } else {
                        dev_kfree_skb(skb);
@@ -5651,6 +5695,12 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
        SET_NETDEV_DEV(dev, &pci_dev->dev);
        u64_stats_init(&np->swstats_rx_syncp);
        u64_stats_init(&np->swstats_tx_syncp);
+       np->txrx_stats = alloc_percpu(struct nv_txrx_stats);
+       if (!np->txrx_stats) {
+               pr_err("np->txrx_stats, alloc memory error.\n");
+               err = -ENOMEM;
+               goto out_alloc_percpu;
+       }
 
        timer_setup(&np->oom_kick, nv_do_rx_refill, 0);
        timer_setup(&np->nic_poll, nv_do_nic_poll, 0);
@@ -6060,6 +6110,8 @@ out_relreg:
 out_disable:
        pci_disable_device(pci_dev);
 out_free:
+       free_percpu(np->txrx_stats);
+out_alloc_percpu:
        free_netdev(dev);
 out:
        return err;
@@ -6105,6 +6157,9 @@ static void nv_restore_mac_addr(struct pci_dev *pci_dev)
 static void nv_remove(struct pci_dev *pci_dev)
 {
        struct net_device *dev = pci_get_drvdata(pci_dev);
+       struct fe_priv *np = netdev_priv(dev);
+
+       free_percpu(np->txrx_stats);
 
        unregister_netdev(dev);
 
index 8161e308e64b0f16e8f527e84145ca9a208bf23f..ead3750b4489d1bf9f2678af74ee7adaec3bd5fc 100644 (file)
@@ -1,10 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
-# Packet engine device configuration
+# Packet Engines device configuration
 #
 
 config NET_VENDOR_PACKET_ENGINES
-       bool "Packet Engine devices"
+       bool "Packet Engines devices"
        default y
        depends on PCI
        ---help---
@@ -12,7 +12,7 @@ config NET_VENDOR_PACKET_ENGINES
 
          Note that the answer to this question doesn't directly affect the
          kernel: saying N will just cause the configurator to skip all
-         the questions about packet engine devices. If you say Y, you will
+         the questions about Packet Engines devices. If you say Y, you will
          be asked for your specific card in the following questions.
 
 if NET_VENDOR_PACKET_ENGINES
index 1553c9cfc254d6f8a17aa1f84e0a225515ebff4e..cf054b796d1112316f9cebe199a375b24415f725 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
-# Makefile for the Packet Engine network device drivers.
+# Makefile for the Packet Engines network device drivers.
 #
 
 obj-$(CONFIG_HAMACHI) += hamachi.o
index 4e8118a0865455d9ff68447f7c7507d6cc92a8ee..9f5113639eaf0cf2649769e3b2f481f19ff9fec1 100644 (file)
@@ -1093,7 +1093,7 @@ static int qed_int_deassertion(struct qed_hwfn  *p_hwfn,
                                                snprintf(bit_name, 30,
                                                         p_aeu->bit_name, num);
                                        else
-                                               strncpy(bit_name,
+                                               strlcpy(bit_name,
                                                        p_aeu->bit_name, 30);
 
                                        /* We now need to pass bitmask in its
index 829dd60ab9370e3a1441b2f57c23478ffe4adcec..1efff7f68ef6b62b1ed543f3ae94d9d745d1e9ec 100644 (file)
@@ -1325,7 +1325,7 @@ static int qed_slowpath_start(struct qed_dev *cdev,
                                              &drv_version);
                if (rc) {
                        DP_NOTICE(cdev, "Failed sending drv version command\n");
-                       return rc;
+                       goto err4;
                }
        }
 
@@ -1333,6 +1333,8 @@ static int qed_slowpath_start(struct qed_dev *cdev,
 
        return 0;
 
+err4:
+       qed_ll2_dealloc_if(cdev);
 err3:
        qed_hw_stop(cdev);
 err2:
index f900fde448dba7f993842704db60f9cff19f263a..158ac07389118278766ae3c9836a13d8f5307981 100644 (file)
@@ -442,7 +442,7 @@ static void qed_rdma_init_devinfo(struct qed_hwfn *p_hwfn,
        /* Vendor specific information */
        dev->vendor_id = cdev->vendor_id;
        dev->vendor_part_id = cdev->device_id;
-       dev->hw_ver = 0;
+       dev->hw_ver = cdev->chip_rev;
        dev->fw_ver = (FW_MAJOR_VERSION << 24) | (FW_MINOR_VERSION << 16) |
                      (FW_REVISION_VERSION << 8) | (FW_ENGINEERING_VERSION);
 
@@ -530,9 +530,8 @@ static void qed_rdma_init_devinfo(struct qed_hwfn *p_hwfn,
        SET_FIELD(dev->dev_caps, QED_RDMA_DEV_CAP_LOCAL_INV_FENCE, 1);
 
        /* Check atomic operations support in PCI configuration space. */
-       pci_read_config_dword(cdev->pdev,
-                             cdev->pdev->pcie_cap + PCI_EXP_DEVCTL2,
-                             &pci_status_control);
+       pcie_capability_read_dword(cdev->pdev, PCI_EXP_DEVCTL2,
+                                  &pci_status_control);
 
        if (pci_status_control & PCI_EXP_DEVCTL2_LTR_EN)
                SET_FIELD(dev->dev_caps, QED_RDMA_DEV_CAP_ATOMIC_OP, 1);
index 60189923737a79f0735ffec15b96c3c110b579d6..21d38167f96180718fdcda68ed2433d73271b1bf 100644 (file)
@@ -206,9 +206,9 @@ rmnet_map_ipv4_ul_csum_header(void *iphdr,
        ul_header->csum_insert_offset = skb->csum_offset;
        ul_header->csum_enabled = 1;
        if (ip4h->protocol == IPPROTO_UDP)
-               ul_header->udp_ip4_ind = 1;
+               ul_header->udp_ind = 1;
        else
-               ul_header->udp_ip4_ind = 0;
+               ul_header->udp_ind = 0;
 
        /* Changing remaining fields to network order */
        hdr++;
@@ -239,6 +239,7 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
                              struct rmnet_map_ul_csum_header *ul_header,
                              struct sk_buff *skb)
 {
+       struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr;
        __be16 *hdr = (__be16 *)ul_header, offset;
 
        offset = htons((__force u16)(skb_transport_header(skb) -
@@ -246,7 +247,11 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
        ul_header->csum_start_offset = offset;
        ul_header->csum_insert_offset = skb->csum_offset;
        ul_header->csum_enabled = 1;
-       ul_header->udp_ip4_ind = 0;
+
+       if (ip6h->nexthdr == IPPROTO_UDP)
+               ul_header->udp_ind = 1;
+       else
+               ul_header->udp_ind = 0;
 
        /* Changing remaining fields to network order */
        hdr++;
@@ -419,7 +424,7 @@ sw_csum:
        ul_header->csum_start_offset = 0;
        ul_header->csum_insert_offset = 0;
        ul_header->csum_enabled = 0;
-       ul_header->udp_ip4_ind = 0;
+       ul_header->udp_ind = 0;
 
        priv->stats.csum_sw++;
 }
index 0637c6752a78e7451826f08f48d30ac97ec85765..bae0074ab9aadf287df7cf07b4deef285393cd9c 100644 (file)
@@ -3251,9 +3251,9 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
 
        ret = phy_read_paged(tp->phydev, 0x0a46, 0x13);
        if (ret & BIT(8))
-               phy_modify_paged(tp->phydev, 0x0c41, 0x12, 0, BIT(1));
+               phy_modify_paged(tp->phydev, 0x0c41, 0x15, 0, BIT(1));
        else
-               phy_modify_paged(tp->phydev, 0x0c41, 0x12, BIT(1), 0);
+               phy_modify_paged(tp->phydev, 0x0c41, 0x15, BIT(1), 0);
 
        /* Enable PHY auto speed down */
        phy_modify_paged(tp->phydev, 0x0a44, 0x11, 0, BIT(3) | BIT(2));
@@ -5921,6 +5921,7 @@ static struct sk_buff *rtl8169_try_rx_copy(void *data,
        skb = napi_alloc_skb(&tp->napi, pkt_size);
        if (skb)
                skb_copy_to_linear_data(skb, data, pkt_size);
+       dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
 
        return skb;
 }
@@ -6136,10 +6137,7 @@ static int r8169_phy_connect(struct rtl8169_private *tp)
        if (ret)
                return ret;
 
-       if (tp->supports_gmii)
-               phy_remove_link_mode(phydev,
-                                    ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
-       else
+       if (!tp->supports_gmii)
                phy_set_max_speed(phydev, SPEED_100);
 
        phy_support_asym_pause(phydev);
@@ -6589,13 +6587,18 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
 {
        unsigned int flags;
 
-       if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
+       switch (tp->mac_version) {
+       case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
                rtl_unlock_config_regs(tp);
                RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
                rtl_lock_config_regs(tp);
+               /* fall through */
+       case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_24:
                flags = PCI_IRQ_LEGACY;
-       } else {
+               break;
+       default:
                flags = PCI_IRQ_ALL_TYPES;
+               break;
        }
 
        return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags);
index ef8f08931fe8b9d3cb75daee8a09c18aaa858f5f..6cacd5e893acacfd5da3bc16444de50acd89e764 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Renesas Ethernet AVB device driver
  *
- * Copyright (C) 2014-2015 Renesas Electronics Corporation
+ * Copyright (C) 2014-2019 Renesas Electronics Corporation
  * Copyright (C) 2015 Renesas Solutions Corp.
  * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com>
  *
@@ -513,7 +513,10 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
                        kfree(ts_skb);
                        if (tag == tfa_tag) {
                                skb_tstamp_tx(skb, &shhwtstamps);
+                               dev_consume_skb_any(skb);
                                break;
+                       } else {
+                               dev_kfree_skb_any(skb);
                        }
                }
                ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR);
@@ -1564,7 +1567,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                        }
                        goto unmap;
                }
-               ts_skb->skb = skb;
+               ts_skb->skb = skb_get(skb);
                ts_skb->tag = priv->ts_skb_tag++;
                priv->ts_skb_tag &= 0x3ff;
                list_add_tail(&ts_skb->list, &priv->ts_skb_list);
@@ -1693,6 +1696,7 @@ static int ravb_close(struct net_device *ndev)
        /* Clear the timestamp list */
        list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
                list_del(&ts_skb->list);
+               kfree_skb(ts_skb->skb);
                kfree(ts_skb);
        }
 
index 079f459c73a5d45a9802da81caf403c1c4e43d35..2c5d3f5b84dd6ef1096f3289b8c86ebc49b0348b 100644 (file)
@@ -2208,10 +2208,12 @@ static int rocker_router_fib_event(struct notifier_block *nb,
 
                        if (fen_info->fi->fib_nh_is_v6) {
                                NL_SET_ERR_MSG_MOD(info->extack, "IPv6 gateway with IPv4 route is not supported");
+                               kfree(fib_work);
                                return notifier_from_errno(-EINVAL);
                        }
                        if (fen_info->fi->nh) {
                                NL_SET_ERR_MSG_MOD(info->extack, "IPv4 route with nexthop objects is not supported");
+                               kfree(fib_work);
                                return notifier_from_errno(-EINVAL);
                        }
                }
index 027938017579130fd1072b0b3c0745a541933107..e92a178a76df0849600734c1193ee0cbdbc9ca19 100644 (file)
@@ -11,7 +11,7 @@ config NET_VENDOR_SAMSUNG
          say Y.
 
          Note that the answer to this question does not directly affect
-         the kernel: saying N will just case the configurator to skip all
+         the kernel: saying N will just cause the configurator to skip all
          the questions about Samsung chipsets. If you say Y, you will be asked
          for your specific chipset/driver in the following questions.
 
index 7a5e6c5abb57bd48407fde0438a51a4f2ecb0acd..276c7cae7ceeb02b721a6d0118a5df570fd2704e 100644 (file)
@@ -794,15 +794,16 @@ static int sgiseeq_probe(struct platform_device *pdev)
                printk(KERN_ERR "Sgiseeq: Cannot register net device, "
                       "aborting.\n");
                err = -ENODEV;
-               goto err_out_free_page;
+               goto err_out_free_attrs;
        }
 
        printk(KERN_INFO "%s: %s %pM\n", dev->name, sgiseeqstr, dev->dev_addr);
 
        return 0;
 
-err_out_free_page:
-       free_page((unsigned long) sp->srings);
+err_out_free_attrs:
+       dma_free_attrs(&pdev->dev, sizeof(*sp->srings), sp->srings,
+                      sp->srings_dma, DMA_ATTR_NON_CONSISTENT);
 err_out_free_dev:
        free_netdev(dev);
 
index bd14803545de30b7fb7c7a7ff0201227cdd39bdb..8d88e40834567fc23797515f55dbe0e08543622d 100644 (file)
@@ -712,6 +712,7 @@ static void smc911x_phy_detect(struct net_device *dev)
                                        /* Found an external PHY */
                                        break;
                        }
+                       /* Else, fall through */
                default:
                        /* Internal media only */
                        SMC_GET_PHY_ID1(lp, 1, id1);
index 4644b2aeeba1cd39ea3d56b7bd3b66024115671d..e2e469c37a4d0713fcaf5e96b5bc3050503cf133 100644 (file)
@@ -1194,10 +1194,8 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
        int ret;
        struct device *dev = &bsp_priv->pdev->dev;
 
-       if (!ldo) {
-               dev_err(dev, "no regulator found\n");
-               return -1;
-       }
+       if (!ldo)
+               return 0;
 
        if (enable) {
                ret = regulator_enable(ldo);
index 4083019c547a4b1b04509738ac4a6cb4ee0808e5..f97a4096f8fc8e44ef2456e822952a885e48de83 100644 (file)
@@ -873,7 +873,12 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
        int ret;
        u32 reg, val;
 
-       regmap_field_read(gmac->regmap_field, &val);
+       ret = regmap_field_read(gmac->regmap_field, &val);
+       if (ret) {
+               dev_err(priv->device, "Fail to read from regmap field.\n");
+               return ret;
+       }
+
        reg = gmac->variant->default_syscon_value;
        if (reg != val)
                dev_warn(priv->device,
index 01c2e2d83e76dc78eadbb6faef74ec620199d1a2..fc9954e4a7729e79b86313af8d916290006ba9c2 100644 (file)
@@ -85,6 +85,8 @@ static void dwmac4_rx_queue_priority(struct mac_device_info *hw,
        u32 value;
 
        base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3;
+       if (queue >= 4)
+               queue -= 4;
 
        value = readl(ioaddr + base_register);
 
@@ -102,6 +104,8 @@ static void dwmac4_tx_queue_priority(struct mac_device_info *hw,
        u32 value;
 
        base_register = (queue < 4) ? GMAC_TXQ_PRTY_MAP0 : GMAC_TXQ_PRTY_MAP1;
+       if (queue >= 4)
+               queue -= 4;
 
        value = readl(ioaddr + base_register);
 
index 7f86dffb264d352f57019c581baedda9a798e285..3174b701aa903f6b07f6267dbc4fac64cfc1c818 100644 (file)
 #define XGMAC_CORE_INIT_RX             0
 #define XGMAC_PACKET_FILTER            0x00000008
 #define XGMAC_FILTER_RA                        BIT(31)
+#define XGMAC_FILTER_HPF               BIT(10)
 #define XGMAC_FILTER_PCF               BIT(7)
 #define XGMAC_FILTER_PM                        BIT(4)
 #define XGMAC_FILTER_HMC               BIT(2)
 #define XGMAC_FILTER_PR                        BIT(0)
 #define XGMAC_HASH_TABLE(x)            (0x00000010 + (x) * 4)
+#define XGMAC_MAX_HASH_TABLE           8
 #define XGMAC_RXQ_CTRL0                        0x000000a0
 #define XGMAC_RXQEN(x)                 GENMASK((x) * 2 + 1, (x) * 2)
 #define XGMAC_RXQEN_SHIFT(x)           ((x) * 2)
 #define XGMAC_MDIO_ADDR                        0x00000200
 #define XGMAC_MDIO_DATA                        0x00000204
 #define XGMAC_MDIO_C22P                        0x00000220
-#define XGMAC_ADDR0_HIGH               0x00000300
+#define XGMAC_ADDRx_HIGH(x)            (0x00000300 + (x) * 0x8)
+#define XGMAC_ADDR_MAX                 32
 #define XGMAC_AE                       BIT(31)
 #define XGMAC_DCS                      GENMASK(19, 16)
 #define XGMAC_DCS_SHIFT                        16
-#define XGMAC_ADDR0_LOW                        0x00000304
+#define XGMAC_ADDRx_LOW(x)             (0x00000304 + (x) * 0x8)
 #define XGMAC_ARP_ADDR                 0x00000c10
 #define XGMAC_TIMESTAMP_STATUS         0x00000d20
 #define XGMAC_TXTSC                    BIT(15)
index 0a32c96a7854e95eef3b7f0834249131760bd612..85c68b7ee8c6a557cb8a306d5bbb6ae633432c0b 100644 (file)
@@ -4,6 +4,8 @@
  * stmmac XGMAC support.
  */
 
+#include <linux/bitrev.h>
+#include <linux/crc32.h>
 #include "stmmac.h"
 #include "dwxgmac2.h"
 
@@ -106,6 +108,8 @@ static void dwxgmac2_rx_queue_prio(struct mac_device_info *hw, u32 prio,
        u32 value, reg;
 
        reg = (queue < 4) ? XGMAC_RXQ_CTRL2 : XGMAC_RXQ_CTRL3;
+       if (queue >= 4)
+               queue -= 4;
 
        value = readl(ioaddr + reg);
        value &= ~XGMAC_PSRQ(queue);
@@ -169,6 +173,8 @@ static void dwxgmac2_map_mtl_to_dma(struct mac_device_info *hw, u32 queue,
        u32 value, reg;
 
        reg = (queue < 4) ? XGMAC_MTL_RXQ_DMA_MAP0 : XGMAC_MTL_RXQ_DMA_MAP1;
+       if (queue >= 4)
+               queue -= 4;
 
        value = readl(ioaddr + reg);
        value &= ~XGMAC_QxMDMACH(queue);
@@ -278,10 +284,10 @@ static void dwxgmac2_set_umac_addr(struct mac_device_info *hw,
        u32 value;
 
        value = (addr[5] << 8) | addr[4];
-       writel(value | XGMAC_AE, ioaddr + XGMAC_ADDR0_HIGH);
+       writel(value | XGMAC_AE, ioaddr + XGMAC_ADDRx_HIGH(reg_n));
 
        value = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
-       writel(value, ioaddr + XGMAC_ADDR0_LOW);
+       writel(value, ioaddr + XGMAC_ADDRx_LOW(reg_n));
 }
 
 static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
@@ -291,8 +297,8 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
        u32 hi_addr, lo_addr;
 
        /* Read the MAC address from the hardware */
-       hi_addr = readl(ioaddr + XGMAC_ADDR0_HIGH);
-       lo_addr = readl(ioaddr + XGMAC_ADDR0_LOW);
+       hi_addr = readl(ioaddr + XGMAC_ADDRx_HIGH(reg_n));
+       lo_addr = readl(ioaddr + XGMAC_ADDRx_LOW(reg_n));
 
        /* Extract the MAC address from the high and low words */
        addr[0] = lo_addr & 0xff;
@@ -303,19 +309,82 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
        addr[5] = (hi_addr >> 8) & 0xff;
 }
 
+static void dwxgmac2_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
+                               int mcbitslog2)
+{
+       int numhashregs, regs;
+
+       switch (mcbitslog2) {
+       case 6:
+               numhashregs = 2;
+               break;
+       case 7:
+               numhashregs = 4;
+               break;
+       case 8:
+               numhashregs = 8;
+               break;
+       default:
+               return;
+       }
+
+       for (regs = 0; regs < numhashregs; regs++)
+               writel(mcfilterbits[regs], ioaddr + XGMAC_HASH_TABLE(regs));
+}
+
 static void dwxgmac2_set_filter(struct mac_device_info *hw,
                                struct net_device *dev)
 {
        void __iomem *ioaddr = (void __iomem *)dev->base_addr;
-       u32 value = XGMAC_FILTER_RA;
+       u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
+       int mcbitslog2 = hw->mcast_bits_log2;
+       u32 mc_filter[8];
+       int i;
+
+       value &= ~(XGMAC_FILTER_PR | XGMAC_FILTER_HMC | XGMAC_FILTER_PM);
+       value |= XGMAC_FILTER_HPF;
+
+       memset(mc_filter, 0, sizeof(mc_filter));
 
        if (dev->flags & IFF_PROMISC) {
-               value |= XGMAC_FILTER_PR | XGMAC_FILTER_PCF;
+               value |= XGMAC_FILTER_PR;
+               value |= XGMAC_FILTER_PCF;
        } else if ((dev->flags & IFF_ALLMULTI) ||
-                  (netdev_mc_count(dev) > HASH_TABLE_SIZE)) {
+                  (netdev_mc_count(dev) > hw->multicast_filter_bins)) {
                value |= XGMAC_FILTER_PM;
-               writel(~0x0, ioaddr + XGMAC_HASH_TABLE(0));
-               writel(~0x0, ioaddr + XGMAC_HASH_TABLE(1));
+
+               for (i = 0; i < XGMAC_MAX_HASH_TABLE; i++)
+                       writel(~0x0, ioaddr + XGMAC_HASH_TABLE(i));
+       } else if (!netdev_mc_empty(dev)) {
+               struct netdev_hw_addr *ha;
+
+               value |= XGMAC_FILTER_HMC;
+
+               netdev_for_each_mc_addr(ha, dev) {
+                       int nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >>
+                                       (32 - mcbitslog2));
+                       mc_filter[nr >> 5] |= (1 << (nr & 0x1F));
+               }
+       }
+
+       dwxgmac2_set_mchash(ioaddr, mc_filter, mcbitslog2);
+
+       /* Handle multiple unicast addresses */
+       if (netdev_uc_count(dev) > XGMAC_ADDR_MAX) {
+               value |= XGMAC_FILTER_PR;
+       } else {
+               struct netdev_hw_addr *ha;
+               int reg = 1;
+
+               netdev_for_each_uc_addr(ha, dev) {
+                       dwxgmac2_set_umac_addr(hw, ha->addr, reg);
+                       reg++;
+               }
+
+               for ( ; reg < XGMAC_ADDR_MAX; reg++) {
+                       writel(0, ioaddr + XGMAC_ADDRx_HIGH(reg));
+                       writel(0, ioaddr + XGMAC_ADDRx_LOW(reg));
+               }
        }
 
        writel(value, ioaddr + XGMAC_PACKET_FILTER);
index c7c9e5f162e6de73f2534dc5f8d5b5a38222e743..fd54c7c8748548e279cc5293ea3df19d656c6366 100644 (file)
@@ -814,20 +814,15 @@ static void stmmac_validate(struct phylink_config *config,
        phylink_set(mac_supported, 10baseT_Full);
        phylink_set(mac_supported, 100baseT_Half);
        phylink_set(mac_supported, 100baseT_Full);
+       phylink_set(mac_supported, 1000baseT_Half);
+       phylink_set(mac_supported, 1000baseT_Full);
+       phylink_set(mac_supported, 1000baseKX_Full);
 
        phylink_set(mac_supported, Autoneg);
        phylink_set(mac_supported, Pause);
        phylink_set(mac_supported, Asym_Pause);
        phylink_set_port_modes(mac_supported);
 
-       if (priv->plat->has_gmac ||
-           priv->plat->has_gmac4 ||
-           priv->plat->has_xgmac) {
-               phylink_set(mac_supported, 1000baseT_Half);
-               phylink_set(mac_supported, 1000baseT_Full);
-               phylink_set(mac_supported, 1000baseKX_Full);
-       }
-
        /* Cut down 1G if asked to */
        if ((max_speed > 0) && (max_speed < 1000)) {
                phylink_set(mask, 1000baseT_Full);
@@ -1295,6 +1290,8 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
                          "(%s) dma_rx_phy=0x%08x\n", __func__,
                          (u32)rx_q->dma_rx_phy);
 
+               stmmac_clear_rx_descriptors(priv, queue);
+
                for (i = 0; i < DMA_RX_SIZE; i++) {
                        struct dma_desc *p;
 
@@ -1312,8 +1309,6 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
                rx_q->cur_rx = 0;
                rx_q->dirty_rx = (unsigned int)(i - DMA_RX_SIZE);
 
-               stmmac_clear_rx_descriptors(priv, queue);
-
                /* Setup the chained descriptor addresses */
                if (priv->mode == STMMAC_CHAIN_MODE) {
                        if (priv->extend_desc)
@@ -1555,9 +1550,8 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
                        goto err_dma;
                }
 
-               rx_q->buf_pool = kmalloc_array(DMA_RX_SIZE,
-                                              sizeof(*rx_q->buf_pool),
-                                              GFP_KERNEL);
+               rx_q->buf_pool = kcalloc(DMA_RX_SIZE, sizeof(*rx_q->buf_pool),
+                                        GFP_KERNEL);
                if (!rx_q->buf_pool)
                        goto err_dma;
 
@@ -1608,15 +1602,15 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
                tx_q->queue_index = queue;
                tx_q->priv_data = priv;
 
-               tx_q->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE,
-                                                   sizeof(*tx_q->tx_skbuff_dma),
-                                                   GFP_KERNEL);
+               tx_q->tx_skbuff_dma = kcalloc(DMA_TX_SIZE,
+                                             sizeof(*tx_q->tx_skbuff_dma),
+                                             GFP_KERNEL);
                if (!tx_q->tx_skbuff_dma)
                        goto err_dma;
 
-               tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE,
-                                               sizeof(struct sk_buff *),
-                                               GFP_KERNEL);
+               tx_q->tx_skbuff = kcalloc(DMA_TX_SIZE,
+                                         sizeof(struct sk_buff *),
+                                         GFP_KERNEL);
                if (!tx_q->tx_skbuff)
                        goto err_dma;
 
@@ -3277,9 +3271,11 @@ static inline int stmmac_rx_threshold_count(struct stmmac_rx_queue *rx_q)
 static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
 {
        struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
-       int dirty = stmmac_rx_dirty(priv, queue);
+       int len, dirty = stmmac_rx_dirty(priv, queue);
        unsigned int entry = rx_q->dirty_rx;
 
+       len = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
+
        while (dirty-- > 0) {
                struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry];
                struct dma_desc *p;
@@ -3297,6 +3293,13 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
                }
 
                buf->addr = page_pool_get_dma_addr(buf->page);
+
+               /* Sync whole allocation to device. This will invalidate old
+                * data.
+                */
+               dma_sync_single_for_device(priv->device, buf->addr, len,
+                                          DMA_FROM_DEVICE);
+
                stmmac_set_desc_addr(priv, p, buf->addr);
                stmmac_refill_desc3(priv, rx_q, p);
 
@@ -3431,8 +3434,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
                        skb_copy_to_linear_data(skb, page_address(buf->page),
                                                frame_len);
                        skb_put(skb, frame_len);
-                       dma_sync_single_for_device(priv->device, buf->addr,
-                                                  frame_len, DMA_FROM_DEVICE);
 
                        if (netif_msg_pktdata(priv)) {
                                netdev_dbg(priv->dev, "frame received (%dbytes)",
@@ -4319,8 +4320,9 @@ int stmmac_dvr_probe(struct device *device,
                                       NAPI_POLL_WEIGHT);
                }
                if (queue < priv->plat->tx_queues_to_use) {
-                       netif_napi_add(ndev, &ch->tx_napi, stmmac_napi_poll_tx,
-                                      NAPI_POLL_WEIGHT);
+                       netif_tx_napi_add(ndev, &ch->tx_napi,
+                                         stmmac_napi_poll_tx,
+                                         NAPI_POLL_WEIGHT);
                }
        }
 
index 73fc2524372e25269a3f4e39987ae65270054ef3..154daf4d10724e9928770319167c16fadc5a476a 100644 (file)
@@ -370,6 +370,13 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
                return ERR_PTR(-ENOMEM);
 
        *mac = of_get_mac_address(np);
+       if (IS_ERR(*mac)) {
+               if (PTR_ERR(*mac) == -EPROBE_DEFER)
+                       return ERR_CAST(*mac);
+
+               *mac = NULL;
+       }
+
        plat->interface = of_get_phy_mode(np);
 
        /* Some wrapper drivers still rely on phy_node. Let's save it while
index 58ea18af9813ab950b1252cde08d626abe61c30e..6c305b6ecad04a9077f15e6f063bc5aba6914561 100644 (file)
@@ -37,7 +37,7 @@ static struct stmmac_tc_entry *tc_find_entry(struct stmmac_priv *priv,
                entry = &priv->tc_entries[i];
                if (!entry->in_use && !first && free)
                        first = entry;
-               if (entry->handle == loc && !free)
+               if ((entry->handle == loc) && !free && !entry->is_frag)
                        dup = entry;
        }
 
@@ -94,7 +94,7 @@ static int tc_fill_entry(struct stmmac_priv *priv,
        struct stmmac_tc_entry *entry, *frag = NULL;
        struct tc_u32_sel *sel = cls->knode.sel;
        u32 off, data, mask, real_off, rem;
-       u32 prio = cls->common.prio;
+       u32 prio = cls->common.prio << 16;
        int ret;
 
        /* Only 1 match per entry */
index 32a89744972db40c866ade7dccbd2c2232f7ec00..a46b8b2e44e14d60f1b04af3c64d3a763dba42d0 100644 (file)
@@ -2775,6 +2775,7 @@ static int cpsw_probe(struct platform_device *pdev)
        if (!cpsw)
                return -ENOMEM;
 
+       platform_set_drvdata(pdev, cpsw);
        cpsw->dev = dev;
 
        mode = devm_gpiod_get_array_optional(dev, "mode", GPIOD_OUT_LOW);
@@ -2879,7 +2880,6 @@ static int cpsw_probe(struct platform_device *pdev)
                goto clean_cpts;
        }
 
-       platform_set_drvdata(pdev, cpsw);
        priv = netdev_priv(ndev);
        priv->cpsw = cpsw;
        priv->ndev = ndev;
index 5b196ebfed492e44b381f46b5eaa1d5d0d2e8f3e..0f346761a2b294ecd519a3e7ed8f5d389dcc91f3 100644 (file)
@@ -788,6 +788,7 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
                        /* fallthrough, if we release the descriptors
                         * brutally (then we don't care about
                         * SPIDER_NET_DESCR_CARDOWNED) */
+                       /* Fall through */
 
                case SPIDER_NET_DESCR_RESPONSE_ERROR:
                case SPIDER_NET_DESCR_PROTECTION_ERROR:
index 8479a440527b8902cfc6b1b5cd25ef34c6171e7b..12466a72cefceafa86830a1f68280f432da3ffb5 100644 (file)
@@ -1504,7 +1504,7 @@ tc35815_rx(struct net_device *dev, int limit)
                        pci_unmap_single(lp->pci_dev,
                                         lp->rx_skbs[cur_bd].skb_dma,
                                         RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-                       if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN)
+                       if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN != 0)
                                memmove(skb->data, skb->data - NET_IP_ALIGN,
                                        pkt_len);
                        data = skb_put(skb, pkt_len);
index 78a7de3fb622f4d98fae24768297caa9bcf1003c..c62f474b6d08eb74c159811c9ea32549845072e9 100644 (file)
@@ -371,9 +371,10 @@ tsi108_stat_carry_one(int carry, int carry_bit, int carry_shift,
 static void tsi108_stat_carry(struct net_device *dev)
 {
        struct tsi108_prv_data *data = netdev_priv(dev);
+       unsigned long flags;
        u32 carry1, carry2;
 
-       spin_lock_irq(&data->misclock);
+       spin_lock_irqsave(&data->misclock, flags);
 
        carry1 = TSI_READ(TSI108_STAT_CARRY1);
        carry2 = TSI_READ(TSI108_STAT_CARRY2);
@@ -441,7 +442,7 @@ static void tsi108_stat_carry(struct net_device *dev)
                              TSI108_STAT_TXPAUSEDROP_CARRY,
                              &data->tx_pause_drop);
 
-       spin_unlock_irq(&data->misclock);
+       spin_unlock_irqrestore(&data->misclock, flags);
 }
 
 /* Read a stat counter atomically with respect to carries.
index 2f354ba029a6149154a66de43e3abc44139996e7..cd0a8f46e7c6c1438231e7f845e5dcc025adc456 100644 (file)
@@ -13,7 +13,7 @@ config NET_VENDOR_XSCALE
 
          Note that the answer to this question does not directly affect the
          kernel: saying N will just cause the configurator to skip all
-         the questions about XSacle IXP devices. If you say Y, you will be
+         the questions about XScale IXP devices. If you say Y, you will be
          asked for your specific card in the following questions.
 
 if NET_VENDOR_XSCALE
index 331c16d30d5df02d1a00bca2c4871362e5dbfeb6..23281aeeb2226ee4dc9d7655aebc247c94c94def 100644 (file)
@@ -344,10 +344,10 @@ static void sp_bump(struct sixpack *sp, char cmd)
 
        sp->dev->stats.rx_bytes += count;
 
-       if ((skb = dev_alloc_skb(count)) == NULL)
+       if ((skb = dev_alloc_skb(count + 1)) == NULL)
                goto out_mem;
 
-       ptr = skb_put(skb, count);
+       ptr = skb_put(skb, count + 1);
        *ptr++ = cmd;   /* KISS command */
 
        memcpy(ptr, sp->cooked_buf + 1, count);
index daab2c07d891dc3d718c7122708e695ea553507b..9303aeb2595f412cefa9ddcaca09ff93f9a4ecd8 100644 (file)
@@ -500,8 +500,9 @@ static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)
                                }
                                break;
                        }
+                       /* fall through */
 
-               default:  /* fall through */
+               default:
                        if (bc->hdlctx.calibrate <= 0)
                                return 0;
                        i = min_t(int, cnt, bc->hdlctx.calibrate);
index afdcc5664ea6a0c69cadd71034aaf3d15ceaf9b5..e8fce6d715ef069fe2e482b014b4d3f6e4f3e088 100644 (file)
@@ -836,7 +836,6 @@ int netvsc_recv_callback(struct net_device *net,
 
        if (unlikely(!skb)) {
                ++net_device_ctx->eth_stats.rx_no_memory;
-               rcu_read_unlock();
                return NVSP_STAT_FAIL;
        }
 
@@ -1240,12 +1239,15 @@ static void netvsc_get_stats64(struct net_device *net,
                               struct rtnl_link_stats64 *t)
 {
        struct net_device_context *ndev_ctx = netdev_priv(net);
-       struct netvsc_device *nvdev = rcu_dereference_rtnl(ndev_ctx->nvdev);
+       struct netvsc_device *nvdev;
        struct netvsc_vf_pcpu_stats vf_tot;
        int i;
 
+       rcu_read_lock();
+
+       nvdev = rcu_dereference(ndev_ctx->nvdev);
        if (!nvdev)
-               return;
+               goto out;
 
        netdev_stats_to_stats64(t, &net->stats);
 
@@ -1284,6 +1286,8 @@ static void netvsc_get_stats64(struct net_device *net,
                t->rx_packets   += packets;
                t->multicast    += multicast;
        }
+out:
+       rcu_read_unlock();
 }
 
 static int netvsc_set_mac_addr(struct net_device *ndev, void *p)
index b41696e16bdc835ff1ec8f516c8ed4c711501ad6..c20e7ef18bc955984f58dd9f8cba38e1bedcb663 100644 (file)
@@ -802,7 +802,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
                err = hwsim_subscribe_all_others(phy);
                if (err < 0) {
                        mutex_unlock(&hwsim_phys_lock);
-                       goto err_reg;
+                       goto err_subscribe;
                }
        }
        list_add_tail(&phy->list, &hwsim_phys);
@@ -812,6 +812,8 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
 
        return idx;
 
+err_subscribe:
+       ieee802154_unregister_hw(phy->hw);
 err_reg:
        kfree(pib);
 err_pib:
@@ -901,9 +903,9 @@ static __init int hwsim_init_module(void)
        return 0;
 
 platform_drv:
-       genl_unregister_family(&hwsim_genl_family);
-platform_dev:
        platform_device_unregister(mac802154hwsim_dev);
+platform_dev:
+       genl_unregister_family(&hwsim_genl_family);
        return rc;
 }
 
index c5c417a3c0ce71d46bf1c5e4dd77dfd261b26407..bcc40a2366248be1954f4ba7d67184009b58e548 100644 (file)
@@ -73,46 +73,47 @@ static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
        debugfs_remove_recursive(nsim_dev_port->ddir);
 }
 
+static struct net *nsim_devlink_net(struct devlink *devlink)
+{
+       return &init_net;
+}
+
 static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV4_FIB, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, false);
 }
 
 static u64 nsim_dev_ipv4_fib_rules_res_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV4_FIB_RULES, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, false);
 }
 
 static u64 nsim_dev_ipv6_fib_resource_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV6_FIB, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, false);
 }
 
 static u64 nsim_dev_ipv6_fib_rules_res_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV6_FIB_RULES, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, false);
 }
 
 static int nsim_dev_resources_register(struct devlink *devlink)
 {
-       struct nsim_dev *nsim_dev = devlink_priv(devlink);
        struct devlink_resource_size_params params = {
                .size_max = (u64)-1,
                .size_granularity = 1,
                .unit = DEVLINK_RESOURCE_UNIT_ENTRY
        };
+       struct net *net = nsim_devlink_net(devlink);
        int err;
        u64 n;
 
@@ -126,8 +127,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                goto out;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV4_FIB, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, true);
        err = devlink_resource_register(devlink, "fib", n,
                                        NSIM_RESOURCE_IPV4_FIB,
                                        NSIM_RESOURCE_IPV4, &params);
@@ -136,8 +136,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                return err;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV4_FIB_RULES, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, true);
        err = devlink_resource_register(devlink, "fib-rules", n,
                                        NSIM_RESOURCE_IPV4_FIB_RULES,
                                        NSIM_RESOURCE_IPV4, &params);
@@ -156,8 +155,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                goto out;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV6_FIB, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, true);
        err = devlink_resource_register(devlink, "fib", n,
                                        NSIM_RESOURCE_IPV6_FIB,
                                        NSIM_RESOURCE_IPV6, &params);
@@ -166,8 +164,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                return err;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV6_FIB_RULES, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, true);
        err = devlink_resource_register(devlink, "fib-rules", n,
                                        NSIM_RESOURCE_IPV6_FIB_RULES,
                                        NSIM_RESOURCE_IPV6, &params);
@@ -179,19 +176,19 @@ static int nsim_dev_resources_register(struct devlink *devlink)
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV4_FIB,
                                          nsim_dev_ipv4_fib_resource_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV4_FIB_RULES,
                                          nsim_dev_ipv4_fib_rules_res_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV6_FIB,
                                          nsim_dev_ipv6_fib_resource_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV6_FIB_RULES,
                                          nsim_dev_ipv6_fib_rules_res_occ_get,
-                                         nsim_dev);
+                                         net);
 out:
        return err;
 }
@@ -199,11 +196,11 @@ out:
 static int nsim_dev_reload(struct devlink *devlink,
                           struct netlink_ext_ack *extack)
 {
-       struct nsim_dev *nsim_dev = devlink_priv(devlink);
        enum nsim_resource_id res_ids[] = {
                NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
                NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
        };
+       struct net *net = nsim_devlink_net(devlink);
        int i;
 
        for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
@@ -212,8 +209,7 @@ static int nsim_dev_reload(struct devlink *devlink,
 
                err = devlink_resource_size_get(devlink, res_ids[i], &val);
                if (!err) {
-                       err = nsim_fib_set_max(nsim_dev->fib_data,
-                                              res_ids[i], val, extack);
+                       err = nsim_fib_set_max(net, res_ids[i], val, extack);
                        if (err)
                                return err;
                }
@@ -285,15 +281,9 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count)
        mutex_init(&nsim_dev->port_list_lock);
        nsim_dev->fw_update_status = true;
 
-       nsim_dev->fib_data = nsim_fib_create();
-       if (IS_ERR(nsim_dev->fib_data)) {
-               err = PTR_ERR(nsim_dev->fib_data);
-               goto err_devlink_free;
-       }
-
        err = nsim_dev_resources_register(devlink);
        if (err)
-               goto err_fib_destroy;
+               goto err_devlink_free;
 
        err = devlink_register(devlink, &nsim_bus_dev->dev);
        if (err)
@@ -315,8 +305,6 @@ err_dl_unregister:
        devlink_unregister(devlink);
 err_resources_unregister:
        devlink_resources_unregister(devlink, NULL);
-err_fib_destroy:
-       nsim_fib_destroy(nsim_dev->fib_data);
 err_devlink_free:
        devlink_free(devlink);
        return ERR_PTR(err);
@@ -330,7 +318,6 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev)
        nsim_dev_debugfs_exit(nsim_dev);
        devlink_unregister(devlink);
        devlink_resources_unregister(devlink, NULL);
-       nsim_fib_destroy(nsim_dev->fib_data);
        mutex_destroy(&nsim_dev->port_list_lock);
        devlink_free(devlink);
 }
index 8c57ba7477726650bb6c0b188a2c8ebb989b14d7..f61d094746c069bb7ac1c6db9eb77fe0820d2562 100644 (file)
@@ -18,6 +18,7 @@
 #include <net/ip_fib.h>
 #include <net/ip6_fib.h>
 #include <net/fib_rules.h>
+#include <net/netns/generic.h>
 
 #include "netdevsim.h"
 
@@ -32,14 +33,15 @@ struct nsim_per_fib_data {
 };
 
 struct nsim_fib_data {
-       struct notifier_block fib_nb;
        struct nsim_per_fib_data ipv4;
        struct nsim_per_fib_data ipv6;
 };
 
-u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, bool max)
+static unsigned int nsim_fib_net_id;
+
+u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max)
 {
+       struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
        struct nsim_fib_entry *entry;
 
        switch (res_id) {
@@ -62,10 +64,10 @@ u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
        return max ? entry->max : entry->num;
 }
 
-int nsim_fib_set_max(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, u64 val,
+int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
                     struct netlink_ext_ack *extack)
 {
+       struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
        struct nsim_fib_entry *entry;
        int err = 0;
 
@@ -118,9 +120,9 @@ static int nsim_fib_rule_account(struct nsim_fib_entry *entry, bool add,
        return err;
 }
 
-static int nsim_fib_rule_event(struct nsim_fib_data *data,
-                              struct fib_notifier_info *info, bool add)
+static int nsim_fib_rule_event(struct fib_notifier_info *info, bool add)
 {
+       struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
        struct netlink_ext_ack *extack = info->extack;
        int err = 0;
 
@@ -155,9 +157,9 @@ static int nsim_fib_account(struct nsim_fib_entry *entry, bool add,
        return err;
 }
 
-static int nsim_fib_event(struct nsim_fib_data *data,
-                         struct fib_notifier_info *info, bool add)
+static int nsim_fib_event(struct fib_notifier_info *info, bool add)
 {
+       struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
        struct netlink_ext_ack *extack = info->extack;
        int err = 0;
 
@@ -176,22 +178,18 @@ static int nsim_fib_event(struct nsim_fib_data *data,
 static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
                             void *ptr)
 {
-       struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
-                                                 fib_nb);
        struct fib_notifier_info *info = ptr;
        int err = 0;
 
        switch (event) {
        case FIB_EVENT_RULE_ADD: /* fall through */
        case FIB_EVENT_RULE_DEL:
-               err = nsim_fib_rule_event(data, info,
-                                         event == FIB_EVENT_RULE_ADD);
+               err = nsim_fib_rule_event(info, event == FIB_EVENT_RULE_ADD);
                break;
 
        case FIB_EVENT_ENTRY_ADD:  /* fall through */
        case FIB_EVENT_ENTRY_DEL:
-               err = nsim_fib_event(data, info,
-                                    event == FIB_EVENT_ENTRY_ADD);
+               err = nsim_fib_event(info, event == FIB_EVENT_ENTRY_ADD);
                break;
        }
 
@@ -201,23 +199,30 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
 /* inconsistent dump, trying again */
 static void nsim_fib_dump_inconsistent(struct notifier_block *nb)
 {
-       struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
-                                                 fib_nb);
+       struct nsim_fib_data *data;
+       struct net *net;
+
+       rcu_read_lock();
+       for_each_net_rcu(net) {
+               data = net_generic(net, nsim_fib_net_id);
+
+               data->ipv4.fib.num = 0ULL;
+               data->ipv4.rules.num = 0ULL;
 
-       data->ipv4.fib.num = 0ULL;
-       data->ipv4.rules.num = 0ULL;
-       data->ipv6.fib.num = 0ULL;
-       data->ipv6.rules.num = 0ULL;
+               data->ipv6.fib.num = 0ULL;
+               data->ipv6.rules.num = 0ULL;
+       }
+       rcu_read_unlock();
 }
 
-struct nsim_fib_data *nsim_fib_create(void)
-{
-       struct nsim_fib_data *data;
-       int err;
+static struct notifier_block nsim_fib_nb = {
+       .notifier_call = nsim_fib_event_nb,
+};
 
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return ERR_PTR(-ENOMEM);
+/* Initialize per network namespace state */
+static int __net_init nsim_fib_netns_init(struct net *net)
+{
+       struct nsim_fib_data *data = net_generic(net, nsim_fib_net_id);
 
        data->ipv4.fib.max = (u64)-1;
        data->ipv4.rules.max = (u64)-1;
@@ -225,22 +230,37 @@ struct nsim_fib_data *nsim_fib_create(void)
        data->ipv6.fib.max = (u64)-1;
        data->ipv6.rules.max = (u64)-1;
 
-       data->fib_nb.notifier_call = nsim_fib_event_nb;
-       err = register_fib_notifier(&data->fib_nb, nsim_fib_dump_inconsistent);
-       if (err) {
-               pr_err("Failed to register fib notifier\n");
-               goto err_out;
-       }
+       return 0;
+}
 
-       return data;
+static struct pernet_operations nsim_fib_net_ops = {
+       .init = nsim_fib_netns_init,
+       .id   = &nsim_fib_net_id,
+       .size = sizeof(struct nsim_fib_data),
+};
 
-err_out:
-       kfree(data);
-       return ERR_PTR(err);
+void nsim_fib_exit(void)
+{
+       unregister_pernet_subsys(&nsim_fib_net_ops);
+       unregister_fib_notifier(&nsim_fib_nb);
 }
 
-void nsim_fib_destroy(struct nsim_fib_data *data)
+int nsim_fib_init(void)
 {
-       unregister_fib_notifier(&data->fib_nb);
-       kfree(data);
+       int err;
+
+       err = register_pernet_subsys(&nsim_fib_net_ops);
+       if (err < 0) {
+               pr_err("Failed to register pernet subsystem\n");
+               goto err_out;
+       }
+
+       err = register_fib_notifier(&nsim_fib_nb, nsim_fib_dump_inconsistent);
+       if (err < 0) {
+               pr_err("Failed to register fib notifier\n");
+               goto err_out;
+       }
+
+err_out:
+       return err;
 }
index 0740940f41b12949558b6150edec27917d3cfe3c..55f57f76d01bb014e8c79b93c739cb1da29460a5 100644 (file)
@@ -357,12 +357,18 @@ static int __init nsim_module_init(void)
        if (err)
                goto err_dev_exit;
 
-       err = rtnl_link_register(&nsim_link_ops);
+       err = nsim_fib_init();
        if (err)
                goto err_bus_exit;
 
+       err = rtnl_link_register(&nsim_link_ops);
+       if (err)
+               goto err_fib_exit;
+
        return 0;
 
+err_fib_exit:
+       nsim_fib_exit();
 err_bus_exit:
        nsim_bus_exit();
 err_dev_exit:
@@ -373,6 +379,7 @@ err_dev_exit:
 static void __exit nsim_module_exit(void)
 {
        rtnl_link_unregister(&nsim_link_ops);
+       nsim_fib_exit();
        nsim_bus_exit();
        nsim_dev_exit();
 }
index 79c05af2a7c0505d6f68eb1345d7629afa61d5b6..9404637d34b7ab30da70c32492abec2b1c07558b 100644 (file)
@@ -169,12 +169,10 @@ int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
 int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
                      unsigned int port_index);
 
-struct nsim_fib_data *nsim_fib_create(void);
-void nsim_fib_destroy(struct nsim_fib_data *fib_data);
-u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, bool max);
-int nsim_fib_set_max(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, u64 val,
+int nsim_fib_init(void);
+void nsim_fib_exit(void);
+u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max);
+int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
                     struct netlink_ext_ack *extack);
 
 #if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
index 222ccd9ecfcebc0bf92beb82e177fba7c3bfaea5..6ad8b1c63c3426c9f7a554eceb6033bab675be62 100644 (file)
@@ -257,36 +257,20 @@ static int at803x_config_init(struct phy_device *phydev)
         *   after HW reset: RX delay enabled and TX delay disabled
         *   after SW reset: RX delay enabled, while TX delay retains the
         *   value before reset.
-        *
-        * So let's first disable the RX and TX delays in PHY and enable
-        * them based on the mode selected (this also takes care of RGMII
-        * mode where we expect delays to be disabled)
         */
-
-       ret = at803x_disable_rx_delay(phydev);
-       if (ret < 0)
-               return ret;
-       ret = at803x_disable_tx_delay(phydev);
-       if (ret < 0)
-               return ret;
-
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-           phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
-               /* If RGMII_ID or RGMII_RXID are specified enable RX delay,
-                * otherwise keep it disabled
-                */
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
                ret = at803x_enable_rx_delay(phydev);
-               if (ret < 0)
-                       return ret;
-       }
+       else
+               ret = at803x_disable_rx_delay(phydev);
+       if (ret < 0)
+               return ret;
 
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-           phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
-               /* If RGMII_ID or RGMII_TXID are specified enable TX delay,
-                * otherwise keep it disabled
-                */
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
                ret = at803x_enable_tx_delay(phydev);
-       }
+       else
+               ret = at803x_disable_tx_delay(phydev);
 
        return ret;
 }
index 3ffe46df249ee2a482b748ac66a79ff31141690a..7c5265fd2b94d31f03ce61ce0f9505310d434f7b 100644 (file)
@@ -216,8 +216,10 @@ static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np)
        if (IS_ERR(gpiod)) {
                if (PTR_ERR(gpiod) == -EPROBE_DEFER)
                        return gpiod;
-               pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
-                      fixed_link_node);
+
+               if (PTR_ERR(gpiod) != -ENOENT)
+                       pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
+                              fixed_link_node);
                gpiod = NULL;
        }
 
index 28676af97b42c275f6d2df4a285d3d6d391ec7f6..645d354ffb4852605f19782ff60815f517d72e40 100644 (file)
@@ -2226,8 +2226,8 @@ static int vsc8514_probe(struct phy_device *phydev)
        vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
        vsc8531->hw_stats = vsc85xx_hw_stats;
        vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
-       vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
-                                           sizeof(u64), GFP_KERNEL);
+       vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+                                     sizeof(u64), GFP_KERNEL);
        if (!vsc8531->stats)
                return -ENOMEM;
 
@@ -2251,8 +2251,8 @@ static int vsc8574_probe(struct phy_device *phydev)
        vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
        vsc8531->hw_stats = vsc8584_hw_stats;
        vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
-       vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
-                                           sizeof(u64), GFP_KERNEL);
+       vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+                                     sizeof(u64), GFP_KERNEL);
        if (!vsc8531->stats)
                return -ENOMEM;
 
@@ -2281,8 +2281,8 @@ static int vsc8584_probe(struct phy_device *phydev)
        vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
        vsc8531->hw_stats = vsc8584_hw_stats;
        vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
-       vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
-                                           sizeof(u64), GFP_KERNEL);
+       vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+                                     sizeof(u64), GFP_KERNEL);
        if (!vsc8531->stats)
                return -ENOMEM;
 
@@ -2311,8 +2311,8 @@ static int vsc85xx_probe(struct phy_device *phydev)
        vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
        vsc8531->hw_stats = vsc85xx_hw_stats;
        vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
-       vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
-                                           sizeof(u64), GFP_KERNEL);
+       vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+                                     sizeof(u64), GFP_KERNEL);
        if (!vsc8531->stats)
                return -ENOMEM;
 
index b9d4145781caa092625adb94214549a02b66fd50..7935593debb11eaeec20a931350d64dc0746b82d 100644 (file)
@@ -219,6 +219,20 @@ int genphy_c45_read_link(struct phy_device *phydev)
        int val, devad;
        bool link = true;
 
+       if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
+               val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+               if (val < 0)
+                       return val;
+
+               /* Autoneg is being started, therefore disregard current
+                * link status and report link as down.
+                */
+               if (val & MDIO_AN_CTRL1_RESTART) {
+                       phydev->link = 0;
+                       return 0;
+               }
+       }
+
        while (mmd_mask && link) {
                devad = __ffs(mmd_mask);
                mmd_mask &= ~BIT(devad);
@@ -509,6 +523,32 @@ int genphy_c45_read_status(struct phy_device *phydev)
 }
 EXPORT_SYMBOL_GPL(genphy_c45_read_status);
 
+/**
+ * genphy_c45_config_aneg - restart auto-negotiation or forced setup
+ * @phydev: target phy_device struct
+ *
+ * Description: If auto-negotiation is enabled, we configure the
+ *   advertising, and then restart auto-negotiation.  If it is not
+ *   enabled, then we force a configuration.
+ */
+int genphy_c45_config_aneg(struct phy_device *phydev)
+{
+       bool changed = false;
+       int ret;
+
+       if (phydev->autoneg == AUTONEG_DISABLE)
+               return genphy_c45_pma_setup_forced(phydev);
+
+       ret = genphy_c45_an_config_aneg(phydev);
+       if (ret < 0)
+               return ret;
+       if (ret > 0)
+               changed = true;
+
+       return genphy_c45_check_and_restart_aneg(phydev, changed);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_config_aneg);
+
 /* The gen10g_* functions are the old Clause 45 stub */
 
 int gen10g_config_aneg(struct phy_device *phydev)
index ef7aa738e0dc4537e3234340c6b2e56110c949c6..6b0f89369b460e7c01eef92bc13e24e430f22102 100644 (file)
@@ -507,7 +507,7 @@ static int phy_config_aneg(struct phy_device *phydev)
         * allowed to call genphy_config_aneg()
         */
        if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0)))
-               return -EOPNOTSUPP;
+               return genphy_c45_config_aneg(phydev);
 
        return genphy_config_aneg(phydev);
 }
index 6b5cb87f38661d70b4e2d1ea30eccbe2e7200f73..27ebc2c6c2d0c4eb111f39a5596f50d976ca4a1a 100644 (file)
@@ -1752,7 +1752,17 @@ EXPORT_SYMBOL(genphy_aneg_done);
  */
 int genphy_update_link(struct phy_device *phydev)
 {
-       int status;
+       int status = 0, bmcr;
+
+       bmcr = phy_read(phydev, MII_BMCR);
+       if (bmcr < 0)
+               return bmcr;
+
+       /* Autoneg is being started, therefore disregard BMSR value and
+        * report link as down.
+        */
+       if (bmcr & BMCR_ANRESTART)
+               goto done;
 
        /* The link state is latched low so that momentary link
         * drops can be detected. Do not double-read the status
@@ -1774,6 +1784,12 @@ done:
        phydev->link = status & BMSR_LSTATUS ? 1 : 0;
        phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
 
+       /* Consider the case that autoneg was started and "aneg complete"
+        * bit has been reset, but "link up" bit not yet.
+        */
+       if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
+               phydev->link = 0;
+
        return 0;
 }
 EXPORT_SYMBOL(genphy_update_link);
index b86a4b2116f8156af6c32f82a6e8df9bfaa441d0..59a94e07e7c55b88d860cac214603228c22f021d 100644 (file)
@@ -48,8 +48,9 @@ void phy_led_trigger_change_speed(struct phy_device *phy)
                if (!phy->last_triggered)
                        led_trigger_event(&phy->led_link_trigger->trigger,
                                          LED_FULL);
+               else
+                       led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
 
-               led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
                led_trigger_event(&plt->trigger, LED_FULL);
                phy->last_triggered = plt;
        }
index 5d0af041b8f9f662d957d19353b05a8cb4bf4157..a5a57ca94c1ac541092867b685fe7d616218f96b 100644 (file)
@@ -216,6 +216,8 @@ static int phylink_parse_fixedlink(struct phylink *pl,
                               pl->supported, true);
        linkmode_zero(pl->supported);
        phylink_set(pl->supported, MII);
+       phylink_set(pl->supported, Pause);
+       phylink_set(pl->supported, Asym_Pause);
        if (s) {
                __set_bit(s->bit, pl->supported);
        } else {
@@ -374,8 +376,8 @@ static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_stat
  *  Local device  Link partner
  *  Pause AsymDir Pause AsymDir Result
  *    1     X       1     X     TX+RX
- *    0     1       1     1     RX
- *    1     1       0     1     TX
+ *    0     1       1     1     TX
+ *    1     1       0     1     RX
  */
 static void phylink_resolve_flow(struct phylink *pl,
                                 struct phylink_link_state *state)
@@ -396,7 +398,7 @@ static void phylink_resolve_flow(struct phylink *pl,
                        new_pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
                else if (pause & MLO_PAUSE_ASYM)
                        new_pause = state->pause & MLO_PAUSE_SYM ?
-                                MLO_PAUSE_RX : MLO_PAUSE_TX;
+                                MLO_PAUSE_TX : MLO_PAUSE_RX;
        } else {
                new_pause = pl->link_config.pause & MLO_PAUSE_TXRX_MASK;
        }
@@ -990,10 +992,10 @@ void phylink_start(struct phylink *pl)
        }
        if (pl->link_an_mode == MLO_AN_FIXED && pl->get_fixed_state)
                mod_timer(&pl->link_poll, jiffies + HZ);
-       if (pl->sfp_bus)
-               sfp_upstream_start(pl->sfp_bus);
        if (pl->phydev)
                phy_start(pl->phydev);
+       if (pl->sfp_bus)
+               sfp_upstream_start(pl->sfp_bus);
 }
 EXPORT_SYMBOL_GPL(phylink_start);
 
@@ -1010,10 +1012,10 @@ void phylink_stop(struct phylink *pl)
 {
        ASSERT_RTNL();
 
-       if (pl->phydev)
-               phy_stop(pl->phydev);
        if (pl->sfp_bus)
                sfp_upstream_stop(pl->sfp_bus);
+       if (pl->phydev)
+               phy_stop(pl->phydev);
        del_timer_sync(&pl->link_poll);
        if (pl->link_irq) {
                free_irq(pl->link_irq, pl);
index 2d816aadea79501cbdde69db3056fffc56c20486..e36c04c268664595cb9cd35d235d777c79fdf362 100644 (file)
@@ -517,7 +517,7 @@ static int sfp_hwmon_read_sensor(struct sfp *sfp, int reg, long *value)
 
 static void sfp_hwmon_to_rx_power(long *value)
 {
-       *value = DIV_ROUND_CLOSEST(*value, 100);
+       *value = DIV_ROUND_CLOSEST(*value, 10);
 }
 
 static void sfp_hwmon_calibrate(struct sfp *sfp, unsigned int slope, int offset,
index 1d902ecb4aa8b76dc14147841cf51ce12ae02127..a44dd3c8af632565043be1639efb99910e9afc25 100644 (file)
@@ -1115,6 +1115,9 @@ static const struct proto_ops pppoe_ops = {
        .recvmsg        = pppoe_recvmsg,
        .mmap           = sock_no_mmap,
        .ioctl          = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = pppox_compat_ioctl,
+#endif
 };
 
 static const struct pppox_proto pppoe_proto = {
index 5ef422a43d70b479e44991062cbdc03de9aa8951..08364f10a43fae46642f57225121bec00b70a0e0 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/compat.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/net.h>
@@ -98,6 +99,18 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
 EXPORT_SYMBOL(pppox_ioctl);
 
+#ifdef CONFIG_COMPAT
+int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       if (cmd == PPPOEIOCSFWD32)
+               cmd = PPPOEIOCSFWD;
+
+       return pppox_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
+}
+
+EXPORT_SYMBOL(pppox_compat_ioctl);
+#endif
+
 static int pppox_create(struct net *net, struct socket *sock, int protocol,
                        int kern)
 {
index a8e52c8e4128370ca5bc3f44e5be55881846f02f..734de7de03f7893158e1370056f5193f82b7bd54 100644 (file)
@@ -623,6 +623,9 @@ static const struct proto_ops pptp_ops = {
        .recvmsg    = sock_no_recvmsg,
        .mmap       = sock_no_mmap,
        .ioctl      = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = pppox_compat_ioctl,
+#endif
 };
 
 static const struct pppox_proto pppox_pptp_proto = {
index abfa0da9bbd28d8765867e2e4920cd4bf029a229..e8089def5a4671bad10efbde7b00297e4c37df69 100644 (file)
@@ -1004,6 +1004,8 @@ static void __team_compute_features(struct team *team)
 
        team->dev->vlan_features = vlan_features;
        team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+                                    NETIF_F_HW_VLAN_CTAG_TX |
+                                    NETIF_F_HW_VLAN_STAG_TX |
                                     NETIF_F_GSO_UDP_L4;
        team->dev->hard_header_len = max_hard_header_len;
 
index 3d443597bd0496fc99e181f1df29a7ca70191125..aab0be40d4430ab1c1fed92782f4a263f38020bd 100644 (file)
@@ -787,7 +787,8 @@ static void tun_detach_all(struct net_device *dev)
 }
 
 static int tun_attach(struct tun_struct *tun, struct file *file,
-                     bool skip_filter, bool napi, bool napi_frags)
+                     bool skip_filter, bool napi, bool napi_frags,
+                     bool publish_tun)
 {
        struct tun_file *tfile = file->private_data;
        struct net_device *dev = tun->dev;
@@ -870,7 +871,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
         * initialized tfile; otherwise we risk using half-initialized
         * object.
         */
-       rcu_assign_pointer(tfile->tun, tun);
+       if (publish_tun)
+               rcu_assign_pointer(tfile->tun, tun);
        rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
        tun->numqueues++;
        tun_set_real_num_queues(tun);
@@ -1599,7 +1601,8 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
        return true;
 }
 
-static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char *buf,
+static struct sk_buff *__tun_build_skb(struct tun_file *tfile,
+                                      struct page_frag *alloc_frag, char *buf,
                                       int buflen, int len, int pad)
 {
        struct sk_buff *skb = build_skb(buf, buflen);
@@ -1609,6 +1612,7 @@ static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char *buf,
 
        skb_reserve(skb, pad);
        skb_put(skb, len);
+       skb_set_owner_w(skb, tfile->socket.sk);
 
        get_page(alloc_frag->page);
        alloc_frag->offset += buflen;
@@ -1686,7 +1690,8 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
         */
        if (hdr->gso_type || !xdp_prog) {
                *skb_xdp = 1;
-               return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
+               return __tun_build_skb(tfile, alloc_frag, buf, buflen, len,
+                                      pad);
        }
 
        *skb_xdp = 0;
@@ -1723,7 +1728,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
        rcu_read_unlock();
        local_bh_enable();
 
-       return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
+       return __tun_build_skb(tfile, alloc_frag, buf, buflen, len, pad);
 
 err_xdp:
        put_page(alloc_frag->page);
@@ -2727,7 +2732,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
                err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER,
                                 ifr->ifr_flags & IFF_NAPI,
-                                ifr->ifr_flags & IFF_NAPI_FRAGS);
+                                ifr->ifr_flags & IFF_NAPI_FRAGS, true);
                if (err < 0)
                        return err;
 
@@ -2826,13 +2831,17 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
                INIT_LIST_HEAD(&tun->disabled);
                err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI,
-                                ifr->ifr_flags & IFF_NAPI_FRAGS);
+                                ifr->ifr_flags & IFF_NAPI_FRAGS, false);
                if (err < 0)
                        goto err_free_flow;
 
                err = register_netdevice(tun->dev);
                if (err < 0)
                        goto err_detach;
+               /* free_netdev() won't check refcnt, to aovid race
+                * with dev_put() we need publish tun after registration.
+                */
+               rcu_assign_pointer(tfile->tun, tun);
        }
 
        netif_carrier_on(tun->dev);
@@ -2975,7 +2984,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
                if (ret < 0)
                        goto unlock;
                ret = tun_attach(tun, file, false, tun->flags & IFF_NAPI,
-                                tun->flags & IFF_NAPI_FRAGS);
+                                tun->flags & IFF_NAPI_FRAGS, true);
        } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
                tun = rtnl_dereference(tfile->tun);
                if (!tun || !(tun->flags & IFF_MULTI_QUEUE) || tfile->detached)
index 8458e88c18e9e017f579128c36a9707b1232ab97..32f53de5b1fe7abff0eb2882240bcd295977af08 100644 (file)
@@ -206,7 +206,15 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
                goto bad_desc;
        }
 skip:
-       if (rndis && header.usb_cdc_acm_descriptor &&
+       /* Communcation class functions with bmCapabilities are not
+        * RNDIS.  But some Wireless class RNDIS functions use
+        * bmCapabilities for their own purpose. The failsafe is
+        * therefore applied only to Communication class RNDIS
+        * functions.  The rndis test is redundant, but a cheap
+        * optimization.
+        */
+       if (rndis && is_rndis(&intf->cur_altsetting->desc) &&
+           header.usb_cdc_acm_descriptor &&
            header.usb_cdc_acm_descriptor->bmCapabilities) {
                dev_dbg(&intf->dev,
                        "ACM capabilities %02x, not really RNDIS?\n",
index 5519248a791ebefd9003ae6892894f2d95b96a03..32b08b18e12086f9634284b54a2f336994986092 100644 (file)
@@ -163,7 +163,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
        }
        if (!timeout) {
                dev_err(&udev->dev, "firmware not ready in time\n");
-               return -ETIMEDOUT;
+               ret = -ETIMEDOUT;
+               goto err;
        }
 
        /* enable ethernet mode (?) */
index d62b6706a5376a6f50834721ec32297ff3481bc7..fc5895f85cee2f8256661f37de0802054826d421 100644 (file)
@@ -113,16 +113,16 @@ kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
        status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_1),
                                         usb_buf, 24);
        if (status != 0)
-               return status;
+               goto out;
 
        memcpy(usb_buf, init_msg_2, 12);
        status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_2),
                                         usb_buf, 28);
        if (status != 0)
-               return status;
+               goto out;
 
        memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN);
-
+out:
        kfree(usb_buf);
        return status;
 }
index 3d92ea6fcc02be12c00083cdc71832745c8a70fb..f033fee225a11cc7c5b977d26f639042f7896524 100644 (file)
@@ -3792,7 +3792,7 @@ static int lan78xx_probe(struct usb_interface *intf,
        ret = register_netdev(netdev);
        if (ret != 0) {
                netif_err(dev, probe, netdev, "couldn't register the device\n");
-               goto out3;
+               goto out4;
        }
 
        usb_set_intfdata(intf, dev);
@@ -3807,12 +3807,14 @@ static int lan78xx_probe(struct usb_interface *intf,
 
        ret = lan78xx_phy_init(dev);
        if (ret < 0)
-               goto out4;
+               goto out5;
 
        return 0;
 
-out4:
+out5:
        unregister_netdev(netdev);
+out4:
+       usb_free_urb(dev->urb_intr);
 out3:
        lan78xx_unbind(dev, intf);
 out2:
index 6d25dea5ad4b2a956c7c0e4772e64c100c5bd5b1..f7d117d80cfbb81b7fad2e22dd13900290030dc9 100644 (file)
@@ -282,7 +282,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
 static int read_eprom_word(pegasus_t *pegasus, __u8 index, __u16 *retdata)
 {
        int i;
-       __u8 tmp;
+       __u8 tmp = 0;
        __le16 retdatai;
        int ret;
 
index 69e0a2acfcb05b140d5f953e7e4b8f663e9321dc..b6dc5d714b5e636c5b39fa199eb7fd64c1c125bd 100644 (file)
@@ -1295,6 +1295,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x2001, 0x7e3d, 4)},    /* D-Link DWM-222 A2 */
        {QMI_FIXED_INTF(0x2020, 0x2031, 4)},    /* Olicard 600 */
        {QMI_FIXED_INTF(0x2020, 0x2033, 4)},    /* BroadMobi BM806U */
+       {QMI_FIXED_INTF(0x2020, 0x2060, 4)},    /* BroadMobi BM818 */
        {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 8)},    /* Sierra Wireless MC7710 in QMI mode */
index 39e0768d734db45f1bc8f873bc4e3036e0f4f087..04137ac373b07f261c5f276b4cd4d051c80812d9 100644 (file)
@@ -50,7 +50,7 @@
 #define PLA_TEREDO_WAKE_BASE   0xc0c4
 #define PLA_MAR                        0xcd00
 #define PLA_BACKUP             0xd000
-#define PAL_BDC_CR             0xd1a0
+#define PLA_BDC_CR             0xd1a0
 #define PLA_TEREDO_TIMER       0xd2cc
 #define PLA_REALWOW_TIMER      0xd2e8
 #define PLA_SUSPEND_FLAG       0xd38a
 #define TEREDO_RS_EVENT_MASK   0x00fe
 #define OOB_TEREDO_EN          0x0001
 
-/* PAL_BDC_CR */
+/* PLA_BDC_CR */
 #define ALDPS_PROXY_MODE       0x0001
 
 /* PLA_EFUSE_CMD */
@@ -799,8 +799,11 @@ int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
        ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
                              RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
                              value, index, tmp, size, 500);
+       if (ret < 0)
+               memset(data, 0xff, size);
+       else
+               memcpy(data, tmp, size);
 
-       memcpy(data, tmp, size);
        kfree(tmp);
 
        return ret;
@@ -3191,9 +3194,9 @@ static void r8152b_enter_oob(struct r8152 *tp)
 
        rtl_rx_vlan_en(tp, true);
 
-       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR);
        ocp_data |= ALDPS_PROXY_MODE;
-       ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data);
 
        ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
        ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
@@ -3577,9 +3580,9 @@ static void r8153_enter_oob(struct r8152 *tp)
 
        rtl_rx_vlan_en(tp, true);
 
-       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR);
        ocp_data |= ALDPS_PROXY_MODE;
-       ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data);
 
        ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
        ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
@@ -4018,8 +4021,7 @@ static int rtl8152_close(struct net_device *netdev)
 #ifdef CONFIG_PM_SLEEP
        unregister_pm_notifier(&tp->pm_notifier);
 #endif
-       if (!test_bit(RTL8152_UNPLUG, &tp->flags))
-               napi_disable(&tp->napi);
+       napi_disable(&tp->napi);
        clear_bit(WORK_ENABLE, &tp->flags);
        usb_kill_urb(tp->intr_urb);
        cancel_delayed_work_sync(&tp->schedule);
@@ -5350,7 +5352,6 @@ static int rtl8152_probe(struct usb_interface *intf,
        return 0;
 
 out1:
-       netif_napi_del(&tp->napi);
        usb_set_intfdata(intf, NULL);
 out:
        free_netdev(netdev);
@@ -5365,7 +5366,6 @@ static void rtl8152_disconnect(struct usb_interface *intf)
        if (tp) {
                rtl_set_unplug(tp);
 
-               netif_napi_del(&tp->napi);
                unregister_netdev(tp->netdev);
                cancel_delayed_work_sync(&tp->hw_phy_work);
                tp->rtl_ops.unload(tp);
index 4f3de0ac8b0b44a91f06f1c2dd37fde7bc5e0069..ba98e0971b842df0a6e2c690773eb3ee32986b47 100644 (file)
@@ -1331,7 +1331,7 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
                }
        }
 
-       if (rq->vq->num_free > virtqueue_get_vring_size(rq->vq) / 2) {
+       if (rq->vq->num_free > min((unsigned int)budget, virtqueue_get_vring_size(rq->vq)) / 2) {
                if (!try_fill_recv(vi, rq, GFP_ATOMIC))
                        schedule_delayed_work(&vi->refill, 0);
        }
index 54edf8956a254cd718b4329e57ed2c8884e5ff1e..6e84328bdd402f0b66b71a92e7f894765e20dc1b 100644 (file)
@@ -165,23 +165,29 @@ static int vrf_ip6_local_out(struct net *net, struct sock *sk,
 static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
                                           struct net_device *dev)
 {
-       const struct ipv6hdr *iph = ipv6_hdr(skb);
+       const struct ipv6hdr *iph;
        struct net *net = dev_net(skb->dev);
-       struct flowi6 fl6 = {
-               /* needed to match OIF rule */
-               .flowi6_oif = dev->ifindex,
-               .flowi6_iif = LOOPBACK_IFINDEX,
-               .daddr = iph->daddr,
-               .saddr = iph->saddr,
-               .flowlabel = ip6_flowinfo(iph),
-               .flowi6_mark = skb->mark,
-               .flowi6_proto = iph->nexthdr,
-               .flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF,
-       };
+       struct flowi6 fl6;
        int ret = NET_XMIT_DROP;
        struct dst_entry *dst;
        struct dst_entry *dst_null = &net->ipv6.ip6_null_entry->dst;
 
+       if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct ipv6hdr)))
+               goto err;
+
+       iph = ipv6_hdr(skb);
+
+       memset(&fl6, 0, sizeof(fl6));
+       /* needed to match OIF rule */
+       fl6.flowi6_oif = dev->ifindex;
+       fl6.flowi6_iif = LOOPBACK_IFINDEX;
+       fl6.daddr = iph->daddr;
+       fl6.saddr = iph->saddr;
+       fl6.flowlabel = ip6_flowinfo(iph);
+       fl6.flowi6_mark = skb->mark;
+       fl6.flowi6_proto = iph->nexthdr;
+       fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
+
        dst = ip6_route_output(net, NULL, &fl6);
        if (dst == dst_null)
                goto err;
@@ -237,21 +243,27 @@ static int vrf_ip_local_out(struct net *net, struct sock *sk,
 static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
                                           struct net_device *vrf_dev)
 {
-       struct iphdr *ip4h = ip_hdr(skb);
+       struct iphdr *ip4h;
        int ret = NET_XMIT_DROP;
-       struct flowi4 fl4 = {
-               /* needed to match OIF rule */
-               .flowi4_oif = vrf_dev->ifindex,
-               .flowi4_iif = LOOPBACK_IFINDEX,
-               .flowi4_tos = RT_TOS(ip4h->tos),
-               .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF,
-               .flowi4_proto = ip4h->protocol,
-               .daddr = ip4h->daddr,
-               .saddr = ip4h->saddr,
-       };
+       struct flowi4 fl4;
        struct net *net = dev_net(vrf_dev);
        struct rtable *rt;
 
+       if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct iphdr)))
+               goto err;
+
+       ip4h = ip_hdr(skb);
+
+       memset(&fl4, 0, sizeof(fl4));
+       /* needed to match OIF rule */
+       fl4.flowi4_oif = vrf_dev->ifindex;
+       fl4.flowi4_iif = LOOPBACK_IFINDEX;
+       fl4.flowi4_tos = RT_TOS(ip4h->tos);
+       fl4.flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF;
+       fl4.flowi4_proto = ip4h->protocol;
+       fl4.daddr = ip4h->daddr;
+       fl4.saddr = ip4h->saddr;
+
        rt = ip_route_output_flow(net, &fl4, NULL);
        if (IS_ERR(rt))
                goto err;
index d74349628db2209e99ed5c4e24c172bf1603ed23..0e6a51525d9134d18a87a69362a9af7cdfc32790 100644 (file)
@@ -1115,7 +1115,7 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/
     sc->lmc_cmdmode |= (TULIP_CMD_TXRUN | TULIP_CMD_RXRUN);
     LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
 
-    lmc_trace(dev, "lmc_runnin_reset_out");
+    lmc_trace(dev, "lmc_running_reset_out");
 }
 
 
index a9ac3f37b904f00fdadbcf3ba077fe818475bc7a..e2e679a01b65a2570f8bcd88870929622f3b7264 100644 (file)
@@ -413,6 +413,7 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
                case SDLA_RET_NO_BUFS:
                        if (cmd == SDLA_INFORMATION_WRITE)
                                break;
+                       /* Else, fall through */
 
                default: 
                        netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n",
index e9fc168bb734504e535be77067dd250a8197bffe..489cba9b284d1b3bf633853c2f1f5de57e1533c2 100644 (file)
@@ -351,13 +351,15 @@ int i2400m_barker_db_init(const char *_options)
                        }
                        result = i2400m_barker_db_add(barker);
                        if (result < 0)
-                               goto error_add;
+                               goto error_parse_add;
                }
                kfree(options_orig);
        }
        return 0;
 
+error_parse_add:
 error_parse:
+       kfree(options_orig);
 error_add:
        kfree(i2400m_barker_db);
        return result;
index 6642bcb27761d63e8545865c1e2c91097cf9e5c2..8efb493ceec2fc96cda43cb56cde5e6d19e91015 100644 (file)
@@ -127,6 +127,7 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev,
                        "%d\n", result);
        result = 0;
 error_cmd:
+       kfree(cmd);
        kfree_skb(ack_skb);
 error_msg_to_dev:
 error_alloc:
index d436cc51dfd1c3a19c64f0a49f11a7304c46255a..2fb4258941a55ef05512208937a738a4f3a84399 100644 (file)
@@ -177,6 +177,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
                .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG,
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
+               .policy = wil_rf_sector_policy,
                .doit = wil_rf_sector_get_cfg
        },
        {
@@ -184,6 +185,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
                .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG,
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
+               .policy = wil_rf_sector_policy,
                .doit = wil_rf_sector_set_cfg
        },
        {
@@ -192,6 +194,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
                        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR,
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
+               .policy = wil_rf_sector_policy,
                .doit = wil_rf_sector_get_selected
        },
        {
@@ -200,6 +203,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
                        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR,
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
+               .policy = wil_rf_sector_policy,
                .doit = wil_rf_sector_set_selected
        },
 };
index f6500899fc143d0790fa089066bc4dedc799a45c..d07e7c7355d9d29db0b43fd70618ab8c6188b275 100644 (file)
@@ -112,6 +112,7 @@ const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .policy = VENDOR_CMD_RAW_DATA,
                .doit = brcmf_cfg80211_vndr_cmds_dcmd_handler
        },
 };
index 1f500cddb3a75b799645d67ed7a374e0027da11a..55b713255b8eac22e4a5e31264e088d99c52dc16 100644 (file)
@@ -556,6 +556,30 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
        .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 };
 
+const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
+       .name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
+       .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
+       IWL_DEVICE_22500,
+       /*
+        * This device doesn't support receiving BlockAck with a large bitmap
+        * so we need to restrict the size of transmitted aggregation to the
+        * HT size; mac80211 would otherwise pick the HE max (256) by default.
+        */
+       .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+};
+
+const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
+       .name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
+       .fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
+       IWL_DEVICE_22500,
+       /*
+        * This device doesn't support receiving BlockAck with a large bitmap
+        * so we need to restrict the size of transmitted aggregation to the
+        * HT size; mac80211 would otherwise pick the HE max (256) by default.
+        */
+       .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+};
+
 const struct iwl_cfg iwl22000_2ax_cfg_jf = {
        .name = "Intel(R) Dual Band Wireless AX 22000",
        .fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
index d55312ef58c9c61e257a257b16af8ff74a7c80dc..9b0bb89599fc3325a61c4fe283bace44e73b1448 100644 (file)
@@ -776,7 +776,6 @@ struct iwl_rss_config_cmd {
        u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE];
 } __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */
 
-#define IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE 128
 #define IWL_MULTI_QUEUE_SYNC_SENDER_POS 0
 #define IWL_MULTI_QUEUE_SYNC_SENDER_MSK 0xf
 
@@ -812,10 +811,12 @@ struct iwl_rxq_sync_notification {
  *
  * @IWL_MVM_RXQ_EMPTY: empty sync notification
  * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
+ * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
  */
 enum iwl_mvm_rxq_notif_type {
        IWL_MVM_RXQ_EMPTY,
        IWL_MVM_RXQ_NOTIF_DEL_BA,
+       IWL_MVM_RXQ_NSSN_SYNC,
 };
 
 /**
index e411ac98290dc39b744c781b888969f79bd2cf21..4d81776f576dc370091126d1c706b1532f956909 100644 (file)
@@ -2438,17 +2438,19 @@ static void iwl_fw_dbg_info_apply(struct iwl_fw_runtime *fwrt,
 {
        u32 img_name_len = le32_to_cpu(dbg_info->img_name_len);
        u32 dbg_cfg_name_len = le32_to_cpu(dbg_info->dbg_cfg_name_len);
-       const char err_str[] =
-               "WRT: ext=%d. Invalid %s name length %d, expected %d\n";
 
        if (img_name_len != IWL_FW_INI_MAX_IMG_NAME_LEN) {
-               IWL_WARN(fwrt, err_str, ext, "image", img_name_len,
+               IWL_WARN(fwrt,
+                        "WRT: ext=%d. Invalid image name length %d, expected %d\n",
+                        ext, img_name_len,
                         IWL_FW_INI_MAX_IMG_NAME_LEN);
                return;
        }
 
        if (dbg_cfg_name_len != IWL_FW_INI_MAX_DBG_CFG_NAME_LEN) {
-               IWL_WARN(fwrt, err_str, ext, "debug cfg", dbg_cfg_name_len,
+               IWL_WARN(fwrt,
+                        "WRT: ext=%d. Invalid debug cfg name length %d, expected %d\n",
+                        ext, dbg_cfg_name_len,
                         IWL_FW_INI_MAX_DBG_CFG_NAME_LEN);
                return;
        }
@@ -2775,8 +2777,6 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
                struct iwl_ucode_tlv *tlv = iter;
                void *ini_tlv = (void *)tlv->data;
                u32 type = le32_to_cpu(tlv->type);
-               const char invalid_ap_str[] =
-                       "WRT: ext=%d. Invalid apply point %d for %s\n";
 
                switch (type) {
                case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
@@ -2786,8 +2786,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
                        struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
 
                        if (pnt != IWL_FW_INI_APPLY_EARLY) {
-                               IWL_ERR(fwrt, invalid_ap_str, ext, pnt,
-                                       "buffer allocation");
+                               IWL_ERR(fwrt,
+                                       "WRT: ext=%d. Invalid apply point %d for buffer allocation\n",
+                                       ext, pnt);
                                goto next;
                        }
 
@@ -2797,8 +2798,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
                }
                case IWL_UCODE_TLV_TYPE_HCMD:
                        if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
-                               IWL_ERR(fwrt, invalid_ap_str, ext, pnt,
-                                       "host command");
+                               IWL_ERR(fwrt,
+                                       "WRT: ext=%d. Invalid apply point %d for host command\n",
+                                       ext, pnt);
                                goto next;
                        }
                        iwl_fw_dbg_send_hcmd(fwrt, tlv, ext);
index 1c1bf1b281cd90d82adc31d09dbb2d898a220693..6c04f8223aff323166fb75c27fcfc92a94352236 100644 (file)
@@ -577,6 +577,8 @@ extern const struct iwl_cfg iwl_ax1650i_cfg_quz_hr;
 extern const struct iwl_cfg iwl_ax1650s_cfg_quz_hr;
 extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0;
 extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0;
+extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0;
+extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0;
 extern const struct iwl_cfg killer1650x_2ax_cfg;
 extern const struct iwl_cfg killer1650w_2ax_cfg;
 extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0;
index 57d09049e615ce1f3b1ab7c737f1d50be429f857..38672dd5aae962c8da529c7a4b4cd75a6b140c6f 100644 (file)
@@ -1640,6 +1640,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
        init_completion(&drv->request_firmware_complete);
        INIT_LIST_HEAD(&drv->list);
 
+       iwl_load_fw_dbg_tlv(drv->trans->dev, drv->trans);
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        /* Create the device debugfs entries. */
        drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
@@ -1660,8 +1662,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
 err_fw:
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        debugfs_remove_recursive(drv->dbgfs_drv);
-       iwl_fw_dbg_free(drv->trans);
 #endif
+       iwl_fw_dbg_free(drv->trans);
        kfree(drv);
 err:
        return ERR_PTR(ret);
index 1d608e9e91018447465672734570a38c515e3bf7..5de54d1559dda8e2fb62bf659b24abf9339e56cf 100644 (file)
@@ -755,7 +755,7 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
 
        for (i = 0; i < n_profiles; i++) {
                /* the tables start at element 3 */
-               static int pos = 3;
+               int pos = 3;
 
                /* The EWRD profiles officially go from 2 to 4, but we
                 * save them in sar_profiles[1-3] (because we don't
@@ -880,6 +880,22 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
        return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
 }
 
+static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm)
+{
+       /*
+        * The GEO_TX_POWER_LIMIT command is not supported on earlier
+        * firmware versions.  Unfortunately, we don't have a TLV API
+        * flag to rely on, so rely on the major version which is in
+        * the first byte of ucode_ver.  This was implemented
+        * initially on version 38 and then backported to 36, 29 and
+        * 17.
+        */
+       return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 ||
+              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 36 ||
+              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 ||
+              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17;
+}
+
 int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
 {
        struct iwl_geo_tx_power_profiles_resp *resp;
@@ -909,6 +925,9 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
                .data = { data },
        };
 
+       if (!iwl_mvm_sar_geo_support(mvm))
+               return -EOPNOTSUPP;
+
        ret = iwl_mvm_send_cmd(mvm, &cmd);
        if (ret) {
                IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
@@ -934,13 +953,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
        int ret, i, j;
        u16 cmd_wide_id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
 
-       /*
-        * This command is not supported on earlier firmware versions.
-        * Unfortunately, we don't have a TLV API flag to rely on, so
-        * rely on the major version which is in the first byte of
-        * ucode_ver.
-        */
-       if (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) < 41)
+       if (!iwl_mvm_sar_geo_support(mvm))
                return 0;
 
        ret = iwl_mvm_sar_get_wgds_table(mvm);
index cb22d447fcb8a9d68aa566a1933202dddc1bca9d..fe776e35b9d06bf152ce12eec6a664eee2317e62 100644 (file)
@@ -554,7 +554,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
                cpu_to_le32(vif->bss_conf.use_short_slot ?
                            MAC_FLG_SHORT_SLOT : 0);
 
-       cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
+       cmd->filter_flags = 0;
 
        for (i = 0; i < IEEE80211_NUM_ACS; i++) {
                u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
@@ -623,6 +623,8 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
        /* We need the dtim_period to set the MAC as associated */
        if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
            !force_assoc_off) {
+               struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+               u8 ap_sta_id = mvmvif->ap_sta_id;
                u32 dtim_offs;
 
                /*
@@ -658,6 +660,29 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
                               dtim_offs);
 
                ctxt_sta->is_assoc = cpu_to_le32(1);
+
+               /*
+                * allow multicast data frames only as long as the station is
+                * authorized, i.e., GTK keys are already installed (if needed)
+                */
+               if (ap_sta_id < IWL_MVM_STATION_COUNT) {
+                       struct ieee80211_sta *sta;
+
+                       rcu_read_lock();
+
+                       sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
+                       if (!IS_ERR_OR_NULL(sta)) {
+                               struct iwl_mvm_sta *mvmsta =
+                                       iwl_mvm_sta_from_mac80211(sta);
+
+                               if (mvmsta->sta_state ==
+                                   IEEE80211_STA_AUTHORIZED)
+                                       cmd.filter_flags |=
+                                               cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
+                       }
+
+                       rcu_read_unlock();
+               }
        } else {
                ctxt_sta->is_assoc = cpu_to_le32(0);
 
@@ -703,7 +728,8 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
                                       MAC_FILTER_IN_CONTROL_AND_MGMT |
                                       MAC_FILTER_IN_BEACON |
                                       MAC_FILTER_IN_PROBE_REQUEST |
-                                      MAC_FILTER_IN_CRC32);
+                                      MAC_FILTER_IN_CRC32 |
+                                      MAC_FILTER_ACCEPT_GRP);
        ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
 
        /* Allocate sniffer station */
@@ -727,7 +753,8 @@ static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm,
        iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
 
        cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON |
-                                      MAC_FILTER_IN_PROBE_REQUEST);
+                                      MAC_FILTER_IN_PROBE_REQUEST |
+                                      MAC_FILTER_ACCEPT_GRP);
 
        /* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */
        cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int);
index 55cd49ccbf0b7a309286692cef45cc7bbddd4fa0..a7bc00d1296fec755e8415dd7f226207ff2408a2 100644 (file)
@@ -207,11 +207,11 @@ static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
        },
 };
 
-static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
-                              enum set_key_cmd cmd,
-                              struct ieee80211_vif *vif,
-                              struct ieee80211_sta *sta,
-                              struct ieee80211_key_conf *key);
+static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+                                enum set_key_cmd cmd,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_sta *sta,
+                                struct ieee80211_key_conf *key);
 
 void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
 {
@@ -474,7 +474,19 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
        ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
        ieee80211_hw_set(hw, STA_MMPDU_TXQ);
-       ieee80211_hw_set(hw, TX_AMSDU);
+       /*
+        * On older devices, enabling TX A-MSDU occasionally leads to
+        * something getting messed up, the command read from the FIFO
+        * gets out of sync and isn't a TX command, so that we have an
+        * assert EDC.
+        *
+        * It's not clear where the bug is, but since we didn't used to
+        * support A-MSDU until moving the mac80211 iTXQs, just leave it
+        * for older devices. We also don't see this issue on any newer
+        * devices.
+        */
+       if (mvm->cfg->device_family >= IWL_DEVICE_FAMILY_9000)
+               ieee80211_hw_set(hw, TX_AMSDU);
        ieee80211_hw_set(hw, TX_FRAG_LIST);
 
        if (iwl_mvm_has_tlc_offload(mvm)) {
@@ -2726,7 +2738,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
 
                mvmvif->ap_early_keys[i] = NULL;
 
-               ret = iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
+               ret = __iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
                if (ret)
                        goto out_quota_failed;
        }
@@ -3315,10 +3327,20 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                /* enable beacon filtering */
                WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
 
+               /*
+                * Now that the station is authorized, i.e., keys were already
+                * installed, need to indicate to the FW that
+                * multicast data frames can be forwarded to the driver
+                */
+               iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+
                iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
                                     true);
        } else if (old_state == IEEE80211_STA_AUTHORIZED &&
                   new_state == IEEE80211_STA_ASSOC) {
+               /* Multicast data frames are no longer allowed */
+               iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+
                /* disable beacon filtering */
                ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
                WARN_ON(ret &&
@@ -3494,11 +3516,11 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
        return ret;
 }
 
-static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
-                              enum set_key_cmd cmd,
-                              struct ieee80211_vif *vif,
-                              struct ieee80211_sta *sta,
-                              struct ieee80211_key_conf *key)
+static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+                                enum set_key_cmd cmd,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_sta *sta,
+                                struct ieee80211_key_conf *key)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -3553,8 +3575,6 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
                        return -EOPNOTSUPP;
        }
 
-       mutex_lock(&mvm->mutex);
-
        switch (cmd) {
        case SET_KEY:
                if ((vif->type == NL80211_IFTYPE_ADHOC ||
@@ -3700,7 +3720,22 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
                ret = -EINVAL;
        }
 
+       return ret;
+}
+
+static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+                              enum set_key_cmd cmd,
+                              struct ieee80211_vif *vif,
+                              struct ieee80211_sta *sta,
+                              struct ieee80211_key_conf *key)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       int ret;
+
+       mutex_lock(&mvm->mutex);
+       ret = __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key);
        mutex_unlock(&mvm->mutex);
+
        return ret;
 }
 
@@ -5041,7 +5076,6 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
        u32 qmask = BIT(mvm->trans->num_rx_queues) - 1;
        int ret;
 
-       lockdep_assert_held(&mvm->mutex);
 
        if (!iwl_mvm_has_new_rx_api(mvm))
                return;
@@ -5052,13 +5086,15 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
                atomic_set(&mvm->queue_sync_counter,
                           mvm->trans->num_rx_queues);
 
-       ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, size);
+       ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif,
+                                     size, !notif->sync);
        if (ret) {
                IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
                goto out;
        }
 
        if (notif->sync) {
+               lockdep_assert_held(&mvm->mutex);
                ret = wait_event_timeout(mvm->rx_sync_waitq,
                                         atomic_read(&mvm->queue_sync_counter) == 0 ||
                                         iwl_mvm_is_radio_killed(mvm),
index 48c77af54e9919017d4261a2ac80b10a41a900df..a263cc629d7551d05f8084e8770b1aec6ddfcae6 100644 (file)
@@ -1664,9 +1664,9 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
 void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
                              struct iwl_rx_cmd_buffer *rxb, int queue);
 int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
-                           const u8 *data, u32 count);
-void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
-                           int queue);
+                           const u8 *data, u32 count, bool async);
+void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
+                           struct iwl_rx_cmd_buffer *rxb, int queue);
 void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
 void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
                                   struct iwl_rx_cmd_buffer *rxb);
@@ -1813,7 +1813,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 
 /* rate scaling */
-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync);
+int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq);
 void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg);
 int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
 void rs_update_last_rssi(struct iwl_mvm *mvm,
index 719f793b3487ce28b949d9d4d80185503d2013b7..a9bb43a2f27b2c81e0a02e5e6ae5a7835a0563a2 100644 (file)
@@ -620,7 +620,7 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
        enum iwl_mcc_source src;
        char mcc[3];
        struct ieee80211_regdomain *regd;
-       u32 wgds_tbl_idx;
+       int wgds_tbl_idx;
 
        lockdep_assert_held(&mvm->mutex);
 
index d7d6f3398f86b4516198bc372261bca0b6ca9a1c..4888054dc3d87eb1c7f0a565dde24b1dec3bd305 100644 (file)
@@ -1088,7 +1088,7 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
                iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0);
        else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
                                         RX_QUEUES_NOTIFICATION)))
-               iwl_mvm_rx_queue_notif(mvm, rxb, 0);
+               iwl_mvm_rx_queue_notif(mvm, napi, rxb, 0);
        else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
                iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
        else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
@@ -1812,7 +1812,7 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
                iwl_mvm_rx_frame_release(mvm, napi, rxb, queue);
        else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
                                         RX_QUEUES_NOTIFICATION)))
-               iwl_mvm_rx_queue_notif(mvm, rxb, queue);
+               iwl_mvm_rx_queue_notif(mvm, napi, rxb, queue);
        else if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
                iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, queue);
 }
index 8c9069f28a589c78c0df05c8c36f6fea3e2fa328..d3f04acfbacb9fa360388110423391f6032ea2ca 100644 (file)
@@ -1197,239 +1197,6 @@ static u8 rs_get_tid(struct ieee80211_hdr *hdr)
        return tid;
 }
 
-void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                         int tid, struct ieee80211_tx_info *info, bool ndp)
-{
-       int legacy_success;
-       int retries;
-       int i;
-       struct iwl_lq_cmd *table;
-       u32 lq_hwrate;
-       struct rs_rate lq_rate, tx_resp_rate;
-       struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
-       u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
-       u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
-       u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
-       u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
-       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-       struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
-
-       /* Treat uninitialized rate scaling data same as non-existing. */
-       if (!lq_sta) {
-               IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
-               return;
-       } else if (!lq_sta->pers.drv) {
-               IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
-               return;
-       }
-
-       /* This packet was aggregated but doesn't carry status info */
-       if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
-           !(info->flags & IEEE80211_TX_STAT_AMPDU))
-               return;
-
-       if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band,
-                                   &tx_resp_rate)) {
-               WARN_ON_ONCE(1);
-               return;
-       }
-
-#ifdef CONFIG_MAC80211_DEBUGFS
-       /* Disable last tx check if we are debugging with fixed rate but
-        * update tx stats */
-       if (lq_sta->pers.dbg_fixed_rate) {
-               int index = tx_resp_rate.index;
-               enum rs_column column;
-               int attempts, success;
-
-               column = rs_get_column_from_rate(&tx_resp_rate);
-               if (WARN_ONCE(column == RS_COLUMN_INVALID,
-                             "Can't map rate 0x%x to column",
-                             tx_resp_hwrate))
-                       return;
-
-               if (info->flags & IEEE80211_TX_STAT_AMPDU) {
-                       attempts = info->status.ampdu_len;
-                       success = info->status.ampdu_ack_len;
-               } else {
-                       attempts = info->status.rates[0].count;
-                       success = !!(info->flags & IEEE80211_TX_STAT_ACK);
-               }
-
-               lq_sta->pers.tx_stats[column][index].total += attempts;
-               lq_sta->pers.tx_stats[column][index].success += success;
-
-               IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n",
-                              tx_resp_hwrate, success, attempts);
-               return;
-       }
-#endif
-
-       if (time_after(jiffies,
-                      (unsigned long)(lq_sta->last_tx +
-                                      (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
-               IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
-               iwl_mvm_rs_rate_init(mvm, sta, info->band, true);
-               return;
-       }
-       lq_sta->last_tx = jiffies;
-
-       /* Ignore this Tx frame response if its initial rate doesn't match
-        * that of latest Link Quality command.  There may be stragglers
-        * from a previous Link Quality command, but we're no longer interested
-        * in those; they're either from the "active" mode while we're trying
-        * to check "search" mode, or a prior "search" mode after we've moved
-        * to a new "search" mode (which might become the new "active" mode).
-        */
-       table = &lq_sta->lq;
-       lq_hwrate = le32_to_cpu(table->rs_table[0]);
-       if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) {
-               WARN_ON_ONCE(1);
-               return;
-       }
-
-       /* Here we actually compare this rate to the latest LQ command */
-       if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
-               IWL_DEBUG_RATE(mvm,
-                              "tx resp color 0x%x does not match 0x%x\n",
-                              lq_color, LQ_FLAG_COLOR_GET(table->flags));
-
-               /*
-                * Since rates mis-match, the last LQ command may have failed.
-                * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
-                * ... driver.
-                */
-               lq_sta->missed_rate_counter++;
-               if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) {
-                       lq_sta->missed_rate_counter = 0;
-                       IWL_DEBUG_RATE(mvm,
-                                      "Too many rates mismatch. Send sync LQ. rs_state %d\n",
-                                      lq_sta->rs_state);
-                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
-               }
-               /* Regardless, ignore this status info for outdated rate */
-               return;
-       } else
-               /* Rate did match, so reset the missed_rate_counter */
-               lq_sta->missed_rate_counter = 0;
-
-       if (!lq_sta->search_better_tbl) {
-               curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-       } else {
-               curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-               other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       }
-
-       if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) {
-               IWL_DEBUG_RATE(mvm,
-                              "Neither active nor search matches tx rate\n");
-               tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE");
-               tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-               rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH");
-               rs_dump_rate(mvm, &lq_rate, "ACTUAL");
-
-               /*
-                * no matching table found, let's by-pass the data collection
-                * and continue to perform rate scale to find the rate table
-                */
-               rs_stay_in_table(lq_sta, true);
-               goto done;
-       }
-
-       /*
-        * Updating the frame history depends on whether packets were
-        * aggregated.
-        *
-        * For aggregation, all packets were transmitted at the same rate, the
-        * first index into rate scale table.
-        */
-       if (info->flags & IEEE80211_TX_STAT_AMPDU) {
-               rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index,
-                                   info->status.ampdu_len,
-                                   info->status.ampdu_ack_len,
-                                   reduced_txp);
-
-               /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat
-                * it as a single frame loss as we don't want the success ratio
-                * to dip too quickly because a BA wasn't received.
-                * For TPC, there's no need for this optimisation since we want
-                * to recover very quickly from a bad power reduction and,
-                * therefore we'd like the success ratio to get an immediate hit
-                * when failing to get a BA, so we'd switch back to a lower or
-                * zero power reduction. When FW transmits agg with a rate
-                * different from the initial rate, it will not use reduced txp
-                * and will send BA notification twice (one empty with reduced
-                * txp equal to the value from LQ and one with reduced txp 0).
-                * We need to update counters for each txp level accordingly.
-                */
-               if (info->status.ampdu_ack_len == 0)
-                       info->status.ampdu_len = 1;
-
-               rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl, tx_resp_rate.index,
-                                   info->status.ampdu_len,
-                                   info->status.ampdu_ack_len);
-
-               /* Update success/fail counts if not searching for new mode */
-               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
-                       lq_sta->total_success += info->status.ampdu_ack_len;
-                       lq_sta->total_failed += (info->status.ampdu_len -
-                                       info->status.ampdu_ack_len);
-               }
-       } else {
-               /* For legacy, update frame history with for each Tx retry. */
-               retries = info->status.rates[0].count - 1;
-               /* HW doesn't send more than 15 retries */
-               retries = min(retries, 15);
-
-               /* The last transmission may have been successful */
-               legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
-               /* Collect data for each rate used during failed TX attempts */
-               for (i = 0; i <= retries; ++i) {
-                       lq_hwrate = le32_to_cpu(table->rs_table[i]);
-                       if (rs_rate_from_ucode_rate(lq_hwrate, info->band,
-                                                   &lq_rate)) {
-                               WARN_ON_ONCE(1);
-                               return;
-                       }
-
-                       /*
-                        * Only collect stats if retried rate is in the same RS
-                        * table as active/search.
-                        */
-                       if (rs_rate_column_match(&lq_rate, &curr_tbl->rate))
-                               tmp_tbl = curr_tbl;
-                       else if (rs_rate_column_match(&lq_rate,
-                                                     &other_tbl->rate))
-                               tmp_tbl = other_tbl;
-                       else
-                               continue;
-
-                       rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,
-                                           tx_resp_rate.index, 1,
-                                           i < retries ? 0 : legacy_success,
-                                           reduced_txp);
-                       rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl,
-                                           tx_resp_rate.index, 1,
-                                           i < retries ? 0 : legacy_success);
-               }
-
-               /* Update success/fail counts if not searching for new mode */
-               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
-                       lq_sta->total_success += legacy_success;
-                       lq_sta->total_failed += retries + (1 - legacy_success);
-               }
-       }
-       /* The last TX rate is cached in lq_sta; it's set in if/else above */
-       lq_sta->last_rate_n_flags = lq_hwrate;
-       IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
-done:
-       /* See if there's a better rate or modulation mode to try. */
-       if (sta->supp_rates[info->band])
-               rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp);
-}
-
 /*
  * mac80211 sends us Tx status
  */
@@ -1442,8 +1209,9 @@ static void rs_drv_mac80211_tx_status(void *mvm_r,
        struct iwl_op_mode *op_mode = mvm_r;
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
-       if (!iwl_mvm_sta_from_mac80211(sta)->vif)
+       if (!mvmsta->vif)
                return;
 
        if (!ieee80211_is_data(hdr->frame_control) ||
@@ -1584,6 +1352,18 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
        tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);
 }
 
+/* rs uses two tables, one is active and the second is for searching better
+ * configuration. This function, according to the index of the currently
+ * active table returns the search table, which is located at the
+ * index complementary to 1 according to the active table (active = 1,
+ * search = 0 or active = 0, search = 1).
+ * Since lq_info is an arary of size 2, make sure index cannot be out of bounds.
+ */
+static inline u8 rs_search_tbl(u8 active_tbl)
+{
+       return (active_tbl ^ 1) & 1;
+}
+
 static s32 rs_get_best_rate(struct iwl_mvm *mvm,
                            struct iwl_lq_sta *lq_sta,
                            struct iwl_scale_tbl_info *tbl,     /* "search" */
@@ -1794,7 +1574,7 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm,
                               struct iwl_scale_tbl_info *tbl)
 {
        rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate);
-       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
+       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
 }
 
 static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm,
@@ -1931,9 +1711,9 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
                               struct ieee80211_sta *sta,
                               enum rs_column col_id)
 {
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+       struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
        struct iwl_scale_tbl_info *search_tbl =
-                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+               &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
        struct rs_rate *rate = &search_tbl->rate;
        const struct rs_tx_column *column = &rs_tx_columns[col_id];
        const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];
@@ -2341,7 +2121,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        if (!lq_sta->search_better_tbl)
                active_tbl = lq_sta->active_tbl;
        else
-               active_tbl = 1 - lq_sta->active_tbl;
+               active_tbl = rs_search_tbl(lq_sta->active_tbl);
 
        tbl = &(lq_sta->lq_info[active_tbl]);
        rate = &tbl->rate;
@@ -2565,7 +2345,7 @@ lq_update:
                /* If new "search" mode was selected, set up in uCode table */
                if (lq_sta->search_better_tbl) {
                        /* Access the "search" table, clear its history. */
-                       tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+                       tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
                        rs_rate_scale_clear_tbl_windows(mvm, tbl);
 
                        /* Use new "search" start rate */
@@ -2896,7 +2676,7 @@ void rs_update_last_rssi(struct iwl_mvm *mvm,
 static void rs_initialize_lq(struct iwl_mvm *mvm,
                             struct ieee80211_sta *sta,
                             struct iwl_lq_sta *lq_sta,
-                            enum nl80211_band band, bool update)
+                            enum nl80211_band band)
 {
        struct iwl_scale_tbl_info *tbl;
        struct rs_rate *rate;
@@ -2908,7 +2688,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
        if (!lq_sta->search_better_tbl)
                active_tbl = lq_sta->active_tbl;
        else
-               active_tbl = 1 - lq_sta->active_tbl;
+               active_tbl = rs_search_tbl(lq_sta->active_tbl);
 
        tbl = &(lq_sta->lq_info[active_tbl]);
        rate = &tbl->rate;
@@ -2926,7 +2706,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
        rs_set_expected_tpt_table(lq_sta, tbl);
        rs_fill_lq_cmd(mvm, sta, lq_sta, rate);
        /* TODO restore station should remember the lq cmd */
-       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, !update);
+       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
 }
 
 static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
@@ -3175,7 +2955,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
  * Called after adding a new station to initialize rate scaling
  */
 static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                            enum nl80211_band band, bool update)
+                            enum nl80211_band band)
 {
        int i, j;
        struct ieee80211_hw *hw = mvm->hw;
@@ -3186,6 +2966,8 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        struct ieee80211_supported_band *sband;
        unsigned long supp; /* must be unsigned long for for_each_set_bit */
 
+       lockdep_assert_held(&mvmsta->lq_sta.rs_drv.pers.lock);
+
        /* clear all non-persistent lq data */
        memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
 
@@ -3255,7 +3037,7 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        iwl_mvm_reset_frame_stats(mvm);
 #endif
-       rs_initialize_lq(mvm, sta, lq_sta, band, update);
+       rs_initialize_lq(mvm, sta, lq_sta, band);
 }
 
 static void rs_drv_rate_update(void *mvm_r,
@@ -3278,6 +3060,258 @@ static void rs_drv_rate_update(void *mvm_r,
        iwl_mvm_rs_rate_init(mvm, sta, sband->band, true);
 }
 
+static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
+                                  struct ieee80211_sta *sta,
+                                  int tid, struct ieee80211_tx_info *info,
+                                  bool ndp)
+{
+       int legacy_success;
+       int retries;
+       int i;
+       struct iwl_lq_cmd *table;
+       u32 lq_hwrate;
+       struct rs_rate lq_rate, tx_resp_rate;
+       struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
+       u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
+       u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
+       u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
+       u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+       struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
+
+       /* Treat uninitialized rate scaling data same as non-existing. */
+       if (!lq_sta) {
+               IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
+               return;
+       } else if (!lq_sta->pers.drv) {
+               IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
+               return;
+       }
+
+       /* This packet was aggregated but doesn't carry status info */
+       if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+           !(info->flags & IEEE80211_TX_STAT_AMPDU))
+               return;
+
+       if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band,
+                                   &tx_resp_rate)) {
+               WARN_ON_ONCE(1);
+               return;
+       }
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       /* Disable last tx check if we are debugging with fixed rate but
+        * update tx stats
+        */
+       if (lq_sta->pers.dbg_fixed_rate) {
+               int index = tx_resp_rate.index;
+               enum rs_column column;
+               int attempts, success;
+
+               column = rs_get_column_from_rate(&tx_resp_rate);
+               if (WARN_ONCE(column == RS_COLUMN_INVALID,
+                             "Can't map rate 0x%x to column",
+                             tx_resp_hwrate))
+                       return;
+
+               if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+                       attempts = info->status.ampdu_len;
+                       success = info->status.ampdu_ack_len;
+               } else {
+                       attempts = info->status.rates[0].count;
+                       success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+               }
+
+               lq_sta->pers.tx_stats[column][index].total += attempts;
+               lq_sta->pers.tx_stats[column][index].success += success;
+
+               IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n",
+                              tx_resp_hwrate, success, attempts);
+               return;
+       }
+#endif
+
+       if (time_after(jiffies,
+                      (unsigned long)(lq_sta->last_tx +
+                                      (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
+               IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
+               /* reach here only in case of driver RS, call directly
+                * the unlocked version
+                */
+               rs_drv_rate_init(mvm, sta, info->band);
+               return;
+       }
+       lq_sta->last_tx = jiffies;
+
+       /* Ignore this Tx frame response if its initial rate doesn't match
+        * that of latest Link Quality command.  There may be stragglers
+        * from a previous Link Quality command, but we're no longer interested
+        * in those; they're either from the "active" mode while we're trying
+        * to check "search" mode, or a prior "search" mode after we've moved
+        * to a new "search" mode (which might become the new "active" mode).
+        */
+       table = &lq_sta->lq;
+       lq_hwrate = le32_to_cpu(table->rs_table[0]);
+       if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) {
+               WARN_ON_ONCE(1);
+               return;
+       }
+
+       /* Here we actually compare this rate to the latest LQ command */
+       if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
+               IWL_DEBUG_RATE(mvm,
+                              "tx resp color 0x%x does not match 0x%x\n",
+                              lq_color, LQ_FLAG_COLOR_GET(table->flags));
+
+               /* Since rates mis-match, the last LQ command may have failed.
+                * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
+                * ... driver.
+                */
+               lq_sta->missed_rate_counter++;
+               if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) {
+                       lq_sta->missed_rate_counter = 0;
+                       IWL_DEBUG_RATE(mvm,
+                                      "Too many rates mismatch. Send sync LQ. rs_state %d\n",
+                                      lq_sta->rs_state);
+                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
+               }
+               /* Regardless, ignore this status info for outdated rate */
+               return;
+       }
+
+       /* Rate did match, so reset the missed_rate_counter */
+       lq_sta->missed_rate_counter = 0;
+
+       if (!lq_sta->search_better_tbl) {
+               curr_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+               other_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+       } else {
+               curr_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+               other_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+       }
+
+       if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) {
+               IWL_DEBUG_RATE(mvm,
+                              "Neither active nor search matches tx rate\n");
+               tmp_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+               rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE");
+               tmp_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+               rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH");
+               rs_dump_rate(mvm, &lq_rate, "ACTUAL");
+
+               /* no matching table found, let's by-pass the data collection
+                * and continue to perform rate scale to find the rate table
+                */
+               rs_stay_in_table(lq_sta, true);
+               goto done;
+       }
+
+       /* Updating the frame history depends on whether packets were
+        * aggregated.
+        *
+        * For aggregation, all packets were transmitted at the same rate, the
+        * first index into rate scale table.
+        */
+       if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+               rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index,
+                                   info->status.ampdu_len,
+                                   info->status.ampdu_ack_len,
+                                   reduced_txp);
+
+               /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat
+                * it as a single frame loss as we don't want the success ratio
+                * to dip too quickly because a BA wasn't received.
+                * For TPC, there's no need for this optimisation since we want
+                * to recover very quickly from a bad power reduction and,
+                * therefore we'd like the success ratio to get an immediate hit
+                * when failing to get a BA, so we'd switch back to a lower or
+                * zero power reduction. When FW transmits agg with a rate
+                * different from the initial rate, it will not use reduced txp
+                * and will send BA notification twice (one empty with reduced
+                * txp equal to the value from LQ and one with reduced txp 0).
+                * We need to update counters for each txp level accordingly.
+                */
+               if (info->status.ampdu_ack_len == 0)
+                       info->status.ampdu_len = 1;
+
+               rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl,
+                                   tx_resp_rate.index,
+                                   info->status.ampdu_len,
+                                   info->status.ampdu_ack_len);
+
+               /* Update success/fail counts if not searching for new mode */
+               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
+                       lq_sta->total_success += info->status.ampdu_ack_len;
+                       lq_sta->total_failed += (info->status.ampdu_len -
+                                       info->status.ampdu_ack_len);
+               }
+       } else {
+               /* For legacy, update frame history with for each Tx retry. */
+               retries = info->status.rates[0].count - 1;
+               /* HW doesn't send more than 15 retries */
+               retries = min(retries, 15);
+
+               /* The last transmission may have been successful */
+               legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+               /* Collect data for each rate used during failed TX attempts */
+               for (i = 0; i <= retries; ++i) {
+                       lq_hwrate = le32_to_cpu(table->rs_table[i]);
+                       if (rs_rate_from_ucode_rate(lq_hwrate, info->band,
+                                                   &lq_rate)) {
+                               WARN_ON_ONCE(1);
+                               return;
+                       }
+
+                       /* Only collect stats if retried rate is in the same RS
+                        * table as active/search.
+                        */
+                       if (rs_rate_column_match(&lq_rate, &curr_tbl->rate))
+                               tmp_tbl = curr_tbl;
+                       else if (rs_rate_column_match(&lq_rate,
+                                                     &other_tbl->rate))
+                               tmp_tbl = other_tbl;
+                       else
+                               continue;
+
+                       rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,
+                                           tx_resp_rate.index, 1,
+                                           i < retries ? 0 : legacy_success,
+                                           reduced_txp);
+                       rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl,
+                                           tx_resp_rate.index, 1,
+                                           i < retries ? 0 : legacy_success);
+               }
+
+               /* Update success/fail counts if not searching for new mode */
+               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
+                       lq_sta->total_success += legacy_success;
+                       lq_sta->total_failed += retries + (1 - legacy_success);
+               }
+       }
+       /* The last TX rate is cached in lq_sta; it's set in if/else above */
+       lq_sta->last_rate_n_flags = lq_hwrate;
+       IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
+done:
+       /* See if there's a better rate or modulation mode to try. */
+       if (sta->supp_rates[info->band])
+               rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp);
+}
+
+void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+                         int tid, struct ieee80211_tx_info *info, bool ndp)
+{
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+       /* If it's locked we are in middle of init flow
+        * just wait for next tx status to update the lq_sta data
+        */
+       if (!spin_trylock(&mvmsta->lq_sta.rs_drv.pers.lock))
+               return;
+
+       __iwl_mvm_rs_tx_status(mvm, sta, tid, info, ndp);
+       spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
+}
+
 #ifdef CONFIG_MAC80211_DEBUGFS
 static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
                                            struct iwl_lq_cmd *lq_cmd,
@@ -3569,7 +3603,7 @@ static void rs_set_lq_ss_params(struct iwl_mvm *mvm,
 
                bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED;
                bfersta_lq_cmd->ss_params = cpu_to_le32(bfersta_ss_params);
-               iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd, false);
+               iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd);
 
                ss_params |= LQ_SS_BFER_ALLOWED;
                IWL_DEBUG_RATE(mvm,
@@ -3735,7 +3769,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm,
 
        if (lq_sta->pers.dbg_fixed_rate) {
                rs_fill_lq_cmd(mvm, NULL, lq_sta, NULL);
-               iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq, false);
+               iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq);
        }
 }
 
@@ -4132,10 +4166,15 @@ static const struct rate_control_ops rs_mvm_ops_drv = {
 void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                          enum nl80211_band band, bool update)
 {
-       if (iwl_mvm_has_tlc_offload(mvm))
+       if (iwl_mvm_has_tlc_offload(mvm)) {
                rs_fw_rate_init(mvm, sta, band, update);
-       else
-               rs_drv_rate_init(mvm, sta, band, update);
+       } else {
+               struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+               spin_lock(&mvmsta->lq_sta.rs_drv.pers.lock);
+               rs_drv_rate_init(mvm, sta, band);
+               spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
+       }
 }
 
 int iwl_mvm_rate_control_register(void)
@@ -4165,7 +4204,7 @@ static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
                        lq->flags &= ~LQ_FLAG_USE_RTS_MSK;
        }
 
-       return iwl_mvm_send_lq_cmd(mvm, lq, false);
+       return iwl_mvm_send_lq_cmd(mvm, lq);
 }
 
 /**
index f7eb60dbaf202460eaca0cf8695171357073996a..428642e666587d14e7d6d3c7a9f8713c4a8d6713 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
  *
  * Contact Information:
  *  Intel Linux Wireless <linuxwifi@intel.com>
@@ -390,6 +390,7 @@ struct iwl_lq_sta {
                s8 last_rssi;
                struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT];
                struct iwl_mvm *drv;
+               spinlock_t lock; /* for races in reinit/update table */
        } pers;
 };
 
index 64f95050128770cae30a2871f1a3c717b95d7cf8..854edd7d7103b351fe69b23a085d3b2e6b9eb610 100644 (file)
@@ -463,20 +463,22 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
 }
 
 int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
-                           const u8 *data, u32 count)
+                           const u8 *data, u32 count, bool async)
 {
-       struct iwl_rxq_sync_cmd *cmd;
+       u8 buf[sizeof(struct iwl_rxq_sync_cmd) +
+              sizeof(struct iwl_mvm_rss_sync_notif)];
+       struct iwl_rxq_sync_cmd *cmd = (void *)buf;
        u32 data_size = sizeof(*cmd) + count;
        int ret;
 
-       /* should be DWORD aligned */
-       if (WARN_ON(count & 3 || count > IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE))
+       /*
+        * size must be a multiple of DWORD
+        * Ensure we don't overflow buf
+        */
+       if (WARN_ON(count & 3 ||
+                   count > sizeof(struct iwl_mvm_rss_sync_notif)))
                return -EINVAL;
 
-       cmd = kzalloc(data_size, GFP_KERNEL);
-       if (!cmd)
-               return -ENOMEM;
-
        cmd->rxq_mask = cpu_to_le32(rxq_mask);
        cmd->count =  cpu_to_le32(count);
        cmd->flags = 0;
@@ -485,9 +487,8 @@ int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
        ret = iwl_mvm_send_cmd_pdu(mvm,
                                   WIDE_ID(DATA_PATH_GROUP,
                                           TRIGGER_RX_QUEUES_NOTIF_CMD),
-                                  0, data_size, cmd);
+                                  async ? CMD_ASYNC : 0, data_size, cmd);
 
-       kfree(cmd);
        return ret;
 }
 
@@ -503,14 +504,31 @@ static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size)
               !ieee80211_sn_less(sn1, sn2 - buffer_size);
 }
 
+static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
+{
+       struct iwl_mvm_rss_sync_notif notif = {
+               .metadata.type = IWL_MVM_RXQ_NSSN_SYNC,
+               .metadata.sync = 0,
+               .nssn_sync.baid = baid,
+               .nssn_sync.nssn = nssn,
+       };
+
+       iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif, sizeof(notif));
+}
+
 #define RX_REORDER_BUF_TIMEOUT_MQ (HZ / 10)
 
+enum iwl_mvm_release_flags {
+       IWL_MVM_RELEASE_SEND_RSS_SYNC = BIT(0),
+       IWL_MVM_RELEASE_FROM_RSS_SYNC = BIT(1),
+};
+
 static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
                                   struct ieee80211_sta *sta,
                                   struct napi_struct *napi,
                                   struct iwl_mvm_baid_data *baid_data,
                                   struct iwl_mvm_reorder_buffer *reorder_buf,
-                                  u16 nssn)
+                                  u16 nssn, u32 flags)
 {
        struct iwl_mvm_reorder_buf_entry *entries =
                &baid_data->entries[reorder_buf->queue *
@@ -519,6 +537,18 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
 
        lockdep_assert_held(&reorder_buf->lock);
 
+       /*
+        * We keep the NSSN not too far behind, if we are sync'ing it and it
+        * is more than 2048 ahead of us, it must be behind us. Discard it.
+        * This can happen if the queue that hit the 0 / 2048 seqno was lagging
+        * behind and this queue already processed packets. The next if
+        * would have caught cases where this queue would have processed less
+        * than 64 packets, but it may have processed more than 64 packets.
+        */
+       if ((flags & IWL_MVM_RELEASE_FROM_RSS_SYNC) &&
+           ieee80211_sn_less(nssn, ssn))
+               goto set_timer;
+
        /* ignore nssn smaller than head sn - this can happen due to timeout */
        if (iwl_mvm_is_sn_less(nssn, ssn, reorder_buf->buf_size))
                goto set_timer;
@@ -529,6 +559,9 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
                struct sk_buff *skb;
 
                ssn = ieee80211_sn_inc(ssn);
+               if ((flags & IWL_MVM_RELEASE_SEND_RSS_SYNC) &&
+                   (ssn == 2048 || ssn == 0))
+                       iwl_mvm_sync_nssn(mvm, baid_data->baid, ssn);
 
                /*
                 * Empty the list. Will have more than one frame for A-MSDU.
@@ -615,7 +648,8 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)
                             sta_id, sn);
                iwl_mvm_event_frame_timeout_callback(buf->mvm, mvmsta->vif,
                                                     sta, baid_data->tid);
-               iwl_mvm_release_frames(buf->mvm, sta, NULL, baid_data, buf, sn);
+               iwl_mvm_release_frames(buf->mvm, sta, NULL, baid_data,
+                                      buf, sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
                rcu_read_unlock();
        } else {
                /*
@@ -657,7 +691,8 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
        spin_lock_bh(&reorder_buf->lock);
        iwl_mvm_release_frames(mvm, sta, NULL, ba_data, reorder_buf,
                               ieee80211_sn_add(reorder_buf->head_sn,
-                                               reorder_buf->buf_size));
+                                               reorder_buf->buf_size),
+                              0);
        spin_unlock_bh(&reorder_buf->lock);
        del_timer_sync(&reorder_buf->reorder_timer);
 
@@ -665,8 +700,54 @@ out:
        rcu_read_unlock();
 }
 
-void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
-                           int queue)
+static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
+                                             struct napi_struct *napi,
+                                             u8 baid, u16 nssn, int queue,
+                                             u32 flags)
+{
+       struct ieee80211_sta *sta;
+       struct iwl_mvm_reorder_buffer *reorder_buf;
+       struct iwl_mvm_baid_data *ba_data;
+
+       IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
+                    baid, nssn);
+
+       if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
+                        baid >= ARRAY_SIZE(mvm->baid_map)))
+               return;
+
+       rcu_read_lock();
+
+       ba_data = rcu_dereference(mvm->baid_map[baid]);
+       if (WARN_ON_ONCE(!ba_data))
+               goto out;
+
+       sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
+       if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
+               goto out;
+
+       reorder_buf = &ba_data->reorder_buf[queue];
+
+       spin_lock_bh(&reorder_buf->lock);
+       iwl_mvm_release_frames(mvm, sta, napi, ba_data,
+                              reorder_buf, nssn, flags);
+       spin_unlock_bh(&reorder_buf->lock);
+
+out:
+       rcu_read_unlock();
+}
+
+static void iwl_mvm_nssn_sync(struct iwl_mvm *mvm,
+                             struct napi_struct *napi, int queue,
+                             const struct iwl_mvm_nssn_sync_data *data)
+{
+       iwl_mvm_release_frames_from_notif(mvm, napi, data->baid,
+                                         data->nssn, queue,
+                                         IWL_MVM_RELEASE_FROM_RSS_SYNC);
+}
+
+void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
+                           struct iwl_rx_cmd_buffer *rxb, int queue)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_rxq_sync_notification *notif;
@@ -687,6 +768,10 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
        case IWL_MVM_RXQ_NOTIF_DEL_BA:
                iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
                break;
+       case IWL_MVM_RXQ_NSSN_SYNC:
+               iwl_mvm_nssn_sync(mvm, napi, queue,
+                                 (void *)internal_notif->data);
+               break;
        default:
                WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);
        }
@@ -785,7 +870,8 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
        }
 
        if (ieee80211_is_back_req(hdr->frame_control)) {
-               iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer, nssn);
+               iwl_mvm_release_frames(mvm, sta, napi, baid_data,
+                                      buffer, nssn, 0);
                goto drop;
        }
 
@@ -794,7 +880,10 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
         * If the SN is smaller than the NSSN it might need to first go into
         * the reorder buffer, in which case we just release up to it and the
         * rest of the function will take care of storing it and releasing up to
-        * the nssn
+        * the nssn.
+        * This should not happen. This queue has been lagging and it should
+        * have been updated by a IWL_MVM_RXQ_NSSN_SYNC notification. Be nice
+        * and update the other queues.
         */
        if (!iwl_mvm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,
                                buffer->buf_size) ||
@@ -802,7 +891,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
                u16 min_sn = ieee80211_sn_less(sn, nssn) ? sn : nssn;
 
                iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer,
-                                      min_sn);
+                                      min_sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
        }
 
        /* drop any oudated packets */
@@ -813,8 +902,23 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
        if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
                if (iwl_mvm_is_sn_less(buffer->head_sn, nssn,
                                       buffer->buf_size) &&
-                  (!amsdu || last_subframe))
+                  (!amsdu || last_subframe)) {
+                       /*
+                        * If we crossed the 2048 or 0 SN, notify all the
+                        * queues. This is done in order to avoid having a
+                        * head_sn that lags behind for too long. When that
+                        * happens, we can get to a situation where the head_sn
+                        * is within the interval [nssn - buf_size : nssn]
+                        * which will make us think that the nssn is a packet
+                        * that we already freed because of the reordering
+                        * buffer and we will ignore it. So maintain the
+                        * head_sn somewhat updated across all the queues:
+                        * when it crosses 0 and 2048.
+                        */
+                       if (sn == 2048 || sn == 0)
+                               iwl_mvm_sync_nssn(mvm, baid, sn);
                        buffer->head_sn = nssn;
+               }
                /* No need to update AMSDU last SN - we are moving the head */
                spin_unlock_bh(&buffer->lock);
                return false;
@@ -829,8 +933,11 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
         * while technically there is no hole and we can move forward.
         */
        if (!buffer->num_stored && sn == buffer->head_sn) {
-               if (!amsdu || last_subframe)
+               if (!amsdu || last_subframe) {
+                       if (sn == 2048 || sn == 0)
+                               iwl_mvm_sync_nssn(mvm, baid, sn);
                        buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
+               }
                /* No need to update AMSDU last SN - we are moving the head */
                spin_unlock_bh(&buffer->lock);
                return false;
@@ -875,7 +982,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
         * release notification with up to date NSSN.
         */
        if (!amsdu || last_subframe)
-               iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer, nssn);
+               iwl_mvm_release_frames(mvm, sta, napi, baid_data,
+                                      buffer, nssn,
+                                      IWL_MVM_RELEASE_SEND_RSS_SYNC);
 
        spin_unlock_bh(&buffer->lock);
        return true;
@@ -1840,40 +1949,14 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
 out:
        rcu_read_unlock();
 }
+
 void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
                              struct iwl_rx_cmd_buffer *rxb, int queue)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_frame_release *release = (void *)pkt->data;
-       struct ieee80211_sta *sta;
-       struct iwl_mvm_reorder_buffer *reorder_buf;
-       struct iwl_mvm_baid_data *ba_data;
-
-       int baid = release->baid;
-
-       IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
-                    release->baid, le16_to_cpu(release->nssn));
 
-       if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID))
-               return;
-
-       rcu_read_lock();
-
-       ba_data = rcu_dereference(mvm->baid_map[baid]);
-       if (WARN_ON_ONCE(!ba_data))
-               goto out;
-
-       sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
-       if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
-               goto out;
-
-       reorder_buf = &ba_data->reorder_buf[queue];
-
-       spin_lock_bh(&reorder_buf->lock);
-       iwl_mvm_release_frames(mvm, sta, napi, ba_data, reorder_buf,
-                              le16_to_cpu(release->nssn));
-       spin_unlock_bh(&reorder_buf->lock);
-
-out:
-       rcu_read_unlock();
+       iwl_mvm_release_frames_from_notif(mvm, napi, release->baid,
+                                         le16_to_cpu(release->nssn),
+                                         queue, 0);
 }
index f545a737a92dfa8321b83ce00748c1833ec7c854..10f18536dd0d288884aca8068eded9b1bc193dcb 100644 (file)
@@ -1684,6 +1684,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
         */
        if (iwl_mvm_has_tlc_offload(mvm))
                iwl_mvm_rs_add_sta(mvm, mvm_sta);
+       else
+               spin_lock_init(&mvm_sta->lq_sta.rs_drv.pers.lock);
 
        iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant);
 
@@ -2421,7 +2423,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 
 static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid)
 {
-       struct iwl_mvm_delba_notif notif = {
+       struct iwl_mvm_rss_sync_notif notif = {
                .metadata.type = IWL_MVM_RXQ_NOTIF_DEL_BA,
                .metadata.sync = 1,
                .delba.baid = baid,
@@ -2972,7 +2974,7 @@ out:
        IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
                     sta->addr, tid);
 
-       return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.rs_drv.lq, false);
+       return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.rs_drv.lq);
 }
 
 static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
index 4487cc3e07c1ebc6a223d9b0af387ea52db57b27..8d70093847cb1d8f1fcd3ada15f03f2c620597fa 100644 (file)
@@ -343,9 +343,17 @@ struct iwl_mvm_delba_data {
        u32 baid;
 } __packed;
 
-struct iwl_mvm_delba_notif {
+struct iwl_mvm_nssn_sync_data {
+       u32 baid;
+       u32 nssn;
+} __packed;
+
+struct iwl_mvm_rss_sync_notif {
        struct iwl_mvm_internal_rxq_notif metadata;
-       struct iwl_mvm_delba_data delba;
+       union {
+               struct iwl_mvm_delba_data delba;
+               struct iwl_mvm_nssn_sync_data nssn_sync;
+       };
 } __packed;
 
 /**
index a3e5d88f1c07cf5123f1d100ea117bda189c0938..6ac114a393ccf361cac64a891579de27623e6d7e 100644 (file)
@@ -831,6 +831,7 @@ iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
        unsigned int tcp_payload_len;
        unsigned int mss = skb_shinfo(skb)->gso_size;
        bool ipv4 = (skb->protocol == htons(ETH_P_IP));
+       bool qos = ieee80211_is_data_qos(hdr->frame_control);
        u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0;
 
        skb_shinfo(skb)->gso_size = num_subframes * mss;
@@ -864,7 +865,7 @@ iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
                if (tcp_payload_len > mss) {
                        skb_shinfo(tmp)->gso_size = mss;
                } else {
-                       if (ieee80211_is_data_qos(hdr->frame_control)) {
+                       if (qos) {
                                u8 *qc;
 
                                if (ipv4)
index 9ecd5f09615a64a34f220dcad8775568b022cde5..b8e20a01c1923b6de62f7a52bf4e8060ded1c221 100644 (file)
@@ -653,12 +653,12 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
  * this case to clear the state indicating that station creation is in
  * progress.
  */
-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync)
+int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
 {
        struct iwl_host_cmd cmd = {
                .id = LQ_CMD,
                .len = { sizeof(struct iwl_lq_cmd), },
-               .flags = sync ? 0 : CMD_ASYNC,
+               .flags = CMD_ASYNC,
                .data = { lq, },
        };
 
index ea2a03d4bf55c66571cae63c4223625e9d920db7..3b12e7ad35e1dd06b36c6a5ff9c8b20fba5bfbc8 100644 (file)
@@ -604,10 +604,13 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)},
        {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x2526, 0x6010, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x6014, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_160_cfg)},
+       {IWL_PCI_DEVICE(0x2526, 0xE010, iwl9260_2ac_160_cfg)},
+       {IWL_PCI_DEVICE(0x2526, 0xE014, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)},
@@ -1059,7 +1062,28 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        iwl_trans->cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0;
                else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
                        iwl_trans->cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0;
+               else if (iwl_trans->cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)
+                       iwl_trans->cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0;
+               else if (iwl_trans->cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)
+                       iwl_trans->cfg = &killer1650i_2ax_cfg_qu_c0_hr_b0;
        }
+
+       /* same thing for QuZ... */
+       if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
+               if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr)
+                       iwl_trans->cfg = &iwl_ax101_cfg_quz_hr;
+               else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
+                       iwl_trans->cfg = &iwl_ax201_cfg_quz_hr;
+               else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
+                       iwl_trans->cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
+                       iwl_trans->cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
+                       iwl_trans->cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
+                       iwl_trans->cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
+       }
+
 #endif
 
        pci_set_drvdata(pdev, iwl_trans);
index f5df5b370d78b585dd277b61b86c00498b8e5f74..db62c831460350fd01d9bbb4d8ff0e3752d75d7c 100644 (file)
@@ -3602,11 +3602,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                }
        } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
                   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
-                  ((trans->cfg != &iwl_ax200_cfg_cc &&
-                    trans->cfg != &killer1650x_2ax_cfg &&
-                    trans->cfg != &killer1650w_2ax_cfg &&
-                    trans->cfg != &iwl_ax201_cfg_quz_hr) ||
-                   trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
+                  trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) {
                u32 hw_status;
 
                hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS);
index 38d11033898716b3e9c1c5fae581c692d4ae44fe..9ef6b8fe03c1b5cc7bad24564c47f6d07bf367e0 100644 (file)
@@ -99,10 +99,7 @@ void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie,
        u16 len = byte_cnt;
        __le16 bc_ent;
 
-       if (trans_pcie->bc_table_dword)
-               len = DIV_ROUND_UP(len, 4);
-
-       if (WARN_ON(len > 0xFFF || idx >= txq->n_window))
+       if (WARN(idx >= txq->n_window, "%d >= %d\n", idx, txq->n_window))
                return;
 
        filled_tfd_size = offsetof(struct iwl_tfh_tfd, tbs) +
@@ -117,11 +114,20 @@ void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie,
         */
        num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
 
-       bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
-       if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+       if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
+               /* Starting from 22560, the HW expects bytes */
+               WARN_ON(trans_pcie->bc_table_dword);
+               WARN_ON(len > 0x3FFF);
+               bc_ent = cpu_to_le16(len | (num_fetch_chunks << 14));
                scd_bc_tbl_gen3->tfd_offset[idx] = bc_ent;
-       else
+       } else {
+               /* Until 22560, the HW expects DW */
+               WARN_ON(!trans_pcie->bc_table_dword);
+               len = DIV_ROUND_UP(len, 4);
+               WARN_ON(len > 0xFFF);
+               bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
                scd_bc_tbl->tfd_offset[idx] = bc_ent;
+       }
 }
 
 /*
index fa4245d0d4a8f848163c930126cd088f2f5c46b1..2f0ba7ef53b8616a4bf4581b49106cf0094739ad 100644 (file)
@@ -435,6 +435,8 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
                                         DMA_TO_DEVICE);
        }
 
+       meta->tbs = 0;
+
        if (trans->cfg->use_tfh) {
                struct iwl_tfh_tfd *tfd_fh = (void *)tfd;
 
index 519b4ee88c5c3af68141b6bb357917ca610a32af..772e54f0696fdf728254dbc966936a92ca4a209b 100644 (file)
@@ -3617,10 +3617,12 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb,
                hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
                                  cb->nlh->nlmsg_seq, &hwsim_genl_family,
                                  NLM_F_MULTI, HWSIM_CMD_GET_RADIO);
-               if (!hdr)
+               if (hdr) {
+                       genl_dump_check_consistent(cb, hdr);
+                       genlmsg_end(skb, hdr);
+               } else {
                        res = -EMSGSIZE;
-               genl_dump_check_consistent(cb, hdr);
-               genlmsg_end(skb, hdr);
+               }
        }
 
 done:
index 653d347a9a19d3e77eb3fbd1ad5d7da3278d6d4a..580387f9f12a9af3b2f64e5ea760ea1607dafe29 100644 (file)
@@ -241,6 +241,9 @@ static int mwifiex_update_vs_ie(const u8 *ies, int ies_len,
                }
 
                vs_ie = (struct ieee_types_header *)vendor_ie;
+               if (le16_to_cpu(ie->ie_length) + vs_ie->len + 2 >
+                       IEEE_MAX_IE_SIZE)
+                       return -EINVAL;
                memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length),
                       vs_ie, vs_ie->len + 2);
                le16_unaligned_add_cpu(&ie->ie_length, vs_ie->len + 2);
index 3e442c7f78827bf5ce91953af495a7a6cc73a977..095837fba300536c719285183061156f17082028 100644 (file)
@@ -124,6 +124,7 @@ enum {
 
 #define MWIFIEX_MAX_TOTAL_SCAN_TIME    (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
 
+#define WPA_GTK_OUI_OFFSET                             2
 #define RSN_GTK_OUI_OFFSET                             2
 
 #define MWIFIEX_OUI_NOT_PRESENT                        0
index 0d6d41727037a737ed224ca84b6bd370dc0a5b7b..21dda385f6c6816fed5732042b0b135c0e364b68 100644 (file)
@@ -181,7 +181,8 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
        u8 ret = MWIFIEX_OUI_NOT_PRESENT;
 
        if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
-               iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
+               iebody = (struct ie_body *)((u8 *)bss_desc->bcn_wpa_ie->data +
+                                           WPA_GTK_OUI_OFFSET);
                oui = &mwifiex_wpa_oui[cipher][0];
                ret = mwifiex_search_oui_in_ie(iebody, oui);
                if (ret)
index 18f7d9bf30b28edc19acef376675b15d726bcc00..0939a8c8f3ab5cf74a55ae08c3feadc1c486f3ca 100644 (file)
@@ -265,6 +265,8 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
 
        rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
        if (rate_ie) {
+               if (rate_ie->len > MWIFIEX_SUPPORTED_RATES)
+                       return;
                memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
                rate_len = rate_ie->len;
        }
@@ -272,8 +274,11 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
        rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
                                           params->beacon.tail,
                                           params->beacon.tail_len);
-       if (rate_ie)
+       if (rate_ie) {
+               if (rate_ie->len > MWIFIEX_SUPPORTED_RATES - rate_len)
+                       return;
                memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
+       }
 
        return;
 }
@@ -391,6 +396,8 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
                                            params->beacon.tail_len);
        if (vendor_ie) {
                wmm_ie = vendor_ie;
+               if (*(wmm_ie + 1) > sizeof(struct mwifiex_types_wmm_info))
+                       return;
                memcpy(&bss_cfg->wmm_info, wmm_ie +
                       sizeof(struct ieee_types_header), *(wmm_ie + 1));
                priv->wmm_enabled = 1;
index 40c0d536e20d04468569bdaa4575c74cb0aee40c..9d4426f6905f29591b9f66a613a3830acf88ccf1 100644 (file)
@@ -59,6 +59,11 @@ static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
                dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");
        }
 
+       if (is_mt7630(dev)) {
+               dev->mt76.cap.has_5ghz = false;
+               dev_dbg(dev->mt76.dev, "mask out 5GHz support\n");
+       }
+
        if (!mt76x02_field_valid(nic_conf1 & 0xff))
                nic_conf1 &= 0xff00;
 
index 4585e1b756c2096d93321e9d3aa8da1f2ff25d49..6117e6ca08cb7cf6cedb6b46b9a426f1bd0d0b10 100644 (file)
@@ -62,6 +62,19 @@ static void mt76x0e_stop(struct ieee80211_hw *hw)
        mt76x0e_stop_hw(dev);
 }
 
+static int
+mt76x0e_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+               struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+               struct ieee80211_key_conf *key)
+{
+       struct mt76x02_dev *dev = hw->priv;
+
+       if (is_mt7630(dev))
+               return -EOPNOTSUPP;
+
+       return mt76x02_set_key(hw, cmd, vif, sta, key);
+}
+
 static void
 mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
              u32 queues, bool drop)
@@ -78,7 +91,7 @@ static const struct ieee80211_ops mt76x0e_ops = {
        .configure_filter = mt76x02_configure_filter,
        .bss_info_changed = mt76x02_bss_info_changed,
        .sta_state = mt76_sta_state,
-       .set_key = mt76x02_set_key,
+       .set_key = mt76x0e_set_key,
        .conf_tx = mt76x02_conf_tx,
        .sw_scan_start = mt76x02_sw_scan,
        .sw_scan_complete = mt76x02_sw_scan_complete,
index 627ed1fc7b1584414b97f9eef9a5d81543dc9d74..645f4d15fb619635d3f2bdc067eea3e308c889d8 100644 (file)
@@ -136,11 +136,11 @@ static const struct ieee80211_ops mt76x0u_ops = {
        .release_buffered_frames = mt76_release_buffered_frames,
 };
 
-static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
+static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset)
 {
        int err;
 
-       mt76x0_chip_onoff(dev, true, true);
+       mt76x0_chip_onoff(dev, true, reset);
 
        if (!mt76x02_wait_for_mac(&dev->mt76))
                return -ETIMEDOUT;
@@ -173,7 +173,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev)
        if (err < 0)
                goto out_err;
 
-       err = mt76x0u_init_hardware(dev);
+       err = mt76x0u_init_hardware(dev, true);
        if (err < 0)
                goto out_err;
 
@@ -309,7 +309,7 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
        if (ret < 0)
                goto err;
 
-       ret = mt76x0u_init_hardware(dev);
+       ret = mt76x0u_init_hardware(dev, false);
        if (ret)
                goto err;
 
index c9b957ac5733262d9faa5d58261bcfa4d77fe243..f1cdcd61c54a5eeec18fc349e63a5cd832cb17fa 100644 (file)
@@ -1654,13 +1654,18 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 
        offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 
-       rt2800_register_multiread(rt2x00dev, offset,
-                                 &iveiv_entry, sizeof(iveiv_entry));
-       if ((crypto->cipher == CIPHER_TKIP) ||
-           (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
-           (crypto->cipher == CIPHER_AES))
-               iveiv_entry.iv[3] |= 0x20;
-       iveiv_entry.iv[3] |= key->keyidx << 6;
+       if (crypto->cmd == SET_KEY) {
+               rt2800_register_multiread(rt2x00dev, offset,
+                                         &iveiv_entry, sizeof(iveiv_entry));
+               if ((crypto->cipher == CIPHER_TKIP) ||
+                   (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
+                   (crypto->cipher == CIPHER_AES))
+                       iveiv_entry.iv[3] |= 0x20;
+               iveiv_entry.iv[3] |= key->keyidx << 6;
+       } else {
+               memset(&iveiv_entry, 0, sizeof(iveiv_entry));
+       }
+
        rt2800_register_multiwrite(rt2x00dev, offset,
                                   &iveiv_entry, sizeof(iveiv_entry));
 }
@@ -4237,24 +4242,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
        switch (rt2x00dev->default_ant.rx_chain_num) {
        case 3:
                /* Turn on tertiary LNAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN,
-                                  rf->channel > 14);
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN,
-                                  rf->channel <= 14);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);
                /* fall-through */
        case 2:
                /* Turn on secondary LNAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN,
-                                  rf->channel > 14);
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN,
-                                  rf->channel <= 14);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
                /* fall-through */
        case 1:
                /* Turn on primary LNAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN,
-                                  rf->channel > 14);
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN,
-                                  rf->channel <= 14);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
                break;
        }
 
@@ -6094,6 +6093,15 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
                rt2800_delete_wcid_attr(rt2x00dev, i);
        }
 
+       /*
+        * Clear encryption initialization vectors on start, but keep them
+        * for watchdog reset. Otherwise we will have wrong IVs and not be
+        * able to keep connections after reset.
+        */
+       if (!test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags))
+               for (i = 0; i < 256; i++)
+                       rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+
        /*
         * Clear all beacons
         */
index 7e43690a861c41654de8863c77111c99fb475fb7..2b216edd0c7d2cbecb10ca1ec46834910538cbed 100644 (file)
@@ -658,6 +658,7 @@ enum rt2x00_state_flags {
        DEVICE_STATE_ENABLED_RADIO,
        DEVICE_STATE_SCANNING,
        DEVICE_STATE_FLUSHING,
+       DEVICE_STATE_RESET,
 
        /*
         * Driver configuration
index 35414f97a978dfc9250faf8eedc6ddaaec97b56b..9d158237ac6746db6f8808584ee140313915cac2 100644 (file)
@@ -1256,13 +1256,14 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
 
 int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
 {
-       int retval;
+       int retval = 0;
 
        if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
                /*
                 * This is special case for ieee80211_restart_hw(), otherwise
                 * mac80211 never call start() two times in row without stop();
                 */
+               set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
                rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
                rt2x00lib_stop(rt2x00dev);
        }
@@ -1273,14 +1274,14 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
         */
        retval = rt2x00lib_load_firmware(rt2x00dev);
        if (retval)
-               return retval;
+               goto out;
 
        /*
         * Initialize the device.
         */
        retval = rt2x00lib_initialize(rt2x00dev);
        if (retval)
-               return retval;
+               goto out;
 
        rt2x00dev->intf_ap_count = 0;
        rt2x00dev->intf_sta_count = 0;
@@ -1289,11 +1290,13 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
        /* Enable the radio */
        retval = rt2x00lib_enable_radio(rt2x00dev);
        if (retval)
-               return retval;
+               goto out;
 
        set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
 
-       return 0;
+out:
+       clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
+       return retval;
 }
 
 void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
index f5048d4b8cb6d3d32ba0f44f271023cc15544601..760eaffeebd64a100392f5d97da43ae303428520 100644 (file)
@@ -645,7 +645,6 @@ fail_rx:
        kfree(rsi_dev->tx_buffer);
 
 fail_eps:
-       kfree(rsi_dev);
 
        return status;
 }
index 5cf0b32c413b34f269a6f9afe36394961d890cc6..e1bd344c4ebc884386062fa52a79e617f7d3c07b 100644 (file)
@@ -163,6 +163,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
                .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
                .doit = wlcore_vendor_cmd_smart_config_start,
+               .policy = wlcore_vendor_attr_policy,
        },
        {
                .info = {
@@ -172,6 +173,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
                .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
                .doit = wlcore_vendor_cmd_smart_config_stop,
+               .policy = wlcore_vendor_attr_policy,
        },
        {
                .info = {
@@ -181,6 +183,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
                .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
                .doit = wlcore_vendor_cmd_smart_config_set_group_key,
+               .policy = wlcore_vendor_attr_policy,
        },
 };
 
index 1d9940d4e8c7d0b627d428589325c10012971af2..c9262ffeefe4cb3eb8a13dfdcc0b77801adc5876 100644 (file)
@@ -925,6 +925,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
                        skb_shinfo(skb)->nr_frags = MAX_SKB_FRAGS;
                        nskb = xenvif_alloc_skb(0);
                        if (unlikely(nskb == NULL)) {
+                               skb_shinfo(skb)->nr_frags = 0;
                                kfree_skb(skb);
                                xenvif_tx_err(queue, &txreq, extra_count, idx);
                                if (net_ratelimit())
@@ -940,6 +941,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 
                        if (xenvif_set_skb_gso(queue->vif, skb, gso)) {
                                /* Failure in xenvif_set_skb_gso is fatal. */
+                               skb_shinfo(skb)->nr_frags = 0;
                                kfree_skb(skb);
                                kfree_skb(nskb);
                                break;
index e65d027b91fafbbd752970cff0afdc9e8cfb0d7c..529be35ac1782a62e9f18b71905fa597ea52a222 100644 (file)
@@ -244,7 +244,7 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
        /* Reset possible fault of previous session */
        clear_bit(NFCMRVL_PHY_ERROR, &priv->flags);
 
-       if (priv->config.reset_n_io) {
+       if (gpio_is_valid(priv->config.reset_n_io)) {
                nfc_info(priv->dev, "reset the chip\n");
                gpio_set_value(priv->config.reset_n_io, 0);
                usleep_range(5000, 10000);
@@ -255,7 +255,7 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
 
 void nfcmrvl_chip_halt(struct nfcmrvl_private *priv)
 {
-       if (priv->config.reset_n_io)
+       if (gpio_is_valid(priv->config.reset_n_io))
                gpio_set_value(priv->config.reset_n_io, 0);
 }
 
index 9a22056e8d9eea921b59a588318be8c47b6b1046..e5a622ce4b9517d299170f20d35bde2bd5e003da 100644 (file)
@@ -26,7 +26,7 @@
 static unsigned int hci_muxed;
 static unsigned int flow_control;
 static unsigned int break_control;
-static unsigned int reset_n_io;
+static int reset_n_io = -EINVAL;
 
 /*
 ** NFCMRVL NCI OPS
@@ -231,5 +231,5 @@ MODULE_PARM_DESC(break_control, "Tell if UART driver must drive break signal.");
 module_param(hci_muxed, uint, 0);
 MODULE_PARM_DESC(hci_muxed, "Tell if transport is muxed in HCI one.");
 
-module_param(reset_n_io, uint, 0);
+module_param(reset_n_io, int, 0);
 MODULE_PARM_DESC(reset_n_io, "GPIO that is wired to RESET_N signal.");
index 945cc903d8f1123fd63a13c42564a3dfe7465a12..888e298f610b8ed7140c85c5d0355d55007b6cfc 100644 (file)
@@ -305,6 +305,7 @@ static int nfcmrvl_probe(struct usb_interface *intf,
 
        /* No configuration for USB */
        memset(&config, 0, sizeof(config));
+       config.reset_n_io = -EINVAL;
 
        nfc_info(&udev->dev, "intf %p id %p\n", intf, id);
 
index c3e10b6ab3a4d45203a67e36af1cf2d193a39028..f25f1ec5f9e97a10aebc1b308180cb84beb4133e 100644 (file)
@@ -333,6 +333,8 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
 
                transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
                                            skb->len - 2, GFP_KERNEL);
+               if (!transaction)
+                       return -ENOMEM;
 
                transaction->aid_len = skb->data[1];
                memcpy(transaction->aid, &skb->data[2], transaction->aid_len);
index 06fc542fd19876d16c0a6e8e39de654340cc2b5a..6586378cacb05ed6b80bcc8c9c350010f7e88905 100644 (file)
@@ -317,6 +317,8 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
 
                transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
                                                   skb->len - 2, GFP_KERNEL);
+               if (!transaction)
+                       return -ENOMEM;
 
                transaction->aid_len = skb->data[1];
                memcpy(transaction->aid, &skb->data[2],
index e42850095892d41fbbf43dc797d28efd5a3d3537..7eda62a9e0dfa3d95616c85e3339570725b01cd8 100644 (file)
@@ -316,7 +316,7 @@ static int st95hf_echo_command(struct st95hf_context *st95context)
                                          &echo_response);
        if (result) {
                dev_err(&st95context->spicontext.spidev->dev,
-                       "err: echo response receieve error = 0x%x\n", result);
+                       "err: echo response receive error = 0x%x\n", result);
                return result;
        }
 
index 9dddf133658fd9c086ac6c7cab49ae177536222d..0a5e884a920c0a6de68c1f842972d5dffab31694 100644 (file)
@@ -6,11 +6,6 @@
 #include <linux/msi.h>
 #include <linux/pci.h>
 
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION("0.1");
-MODULE_AUTHOR("Logan Gunthorpe <logang@deltatee.com>");
-MODULE_DESCRIPTION("NTB MSI Interrupt Library");
-
 struct ntb_msi {
        u64 base_addr;
        u64 end_addr;
index 62d00fffa4afd6145ee26510231c0e65015777e7..3508a79110c70d17e715d34ef9ac2e8a6775dc84 100644 (file)
@@ -62,14 +62,14 @@ static ssize_t sector_size_store(struct device *dev,
        struct nd_btt *nd_btt = to_nd_btt(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        rc = nd_size_select_store(dev, buf, &nd_btt->lbasize,
                        btt_lbasize_supported);
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc ? rc : len;
 }
@@ -91,11 +91,11 @@ static ssize_t uuid_store(struct device *dev,
        struct nd_btt *nd_btt = to_nd_btt(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        rc = nd_uuid_store(dev, &nd_btt->uuid, buf, len);
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc ? rc : len;
 }
@@ -120,13 +120,13 @@ static ssize_t namespace_store(struct device *dev,
        struct nd_btt *nd_btt = to_nd_btt(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        rc = nd_namespace_store(dev, &nd_btt->ndns, buf, len);
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
@@ -138,14 +138,14 @@ static ssize_t size_show(struct device *dev,
        struct nd_btt *nd_btt = to_nd_btt(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        if (dev->driver)
                rc = sprintf(buf, "%llu\n", nd_btt->size);
        else {
                /* no size to convey if the btt instance is disabled */
                rc = -ENXIO;
        }
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
index 2dca3034fee016a2c1e366b85da3dd7d0ac84211..798c5c4aea9ca3ac77e18a7c62e3cb83c68c3c86 100644 (file)
@@ -26,7 +26,7 @@
 
 int nvdimm_major;
 static int nvdimm_bus_major;
-static struct class *nd_class;
+struct class *nd_class;
 static DEFINE_IDA(nd_ida);
 
 static int to_nd_device_type(struct device *dev)
@@ -73,7 +73,7 @@ static void nvdimm_bus_probe_end(struct nvdimm_bus *nvdimm_bus)
 {
        nvdimm_bus_lock(&nvdimm_bus->dev);
        if (--nvdimm_bus->probe_active == 0)
-               wake_up(&nvdimm_bus->probe_wait);
+               wake_up(&nvdimm_bus->wait);
        nvdimm_bus_unlock(&nvdimm_bus->dev);
 }
 
@@ -91,7 +91,10 @@ static int nvdimm_bus_probe(struct device *dev)
                        dev->driver->name, dev_name(dev));
 
        nvdimm_bus_probe_start(nvdimm_bus);
+       debug_nvdimm_lock(dev);
        rc = nd_drv->probe(dev);
+       debug_nvdimm_unlock(dev);
+
        if (rc == 0)
                nd_region_probe_success(nvdimm_bus, dev);
        else
@@ -113,8 +116,11 @@ static int nvdimm_bus_remove(struct device *dev)
        struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
        int rc = 0;
 
-       if (nd_drv->remove)
+       if (nd_drv->remove) {
+               debug_nvdimm_lock(dev);
                rc = nd_drv->remove(dev);
+               debug_nvdimm_unlock(dev);
+       }
        nd_region_disable(nvdimm_bus, dev);
 
        dev_dbg(&nvdimm_bus->dev, "%s.remove(%s) = %d\n", dev->driver->name,
@@ -140,7 +146,7 @@ static void nvdimm_bus_shutdown(struct device *dev)
 
 void nd_device_notify(struct device *dev, enum nvdimm_event event)
 {
-       device_lock(dev);
+       nd_device_lock(dev);
        if (dev->driver) {
                struct nd_device_driver *nd_drv;
 
@@ -148,7 +154,7 @@ void nd_device_notify(struct device *dev, enum nvdimm_event event)
                if (nd_drv->notify)
                        nd_drv->notify(dev, event);
        }
-       device_unlock(dev);
+       nd_device_unlock(dev);
 }
 EXPORT_SYMBOL(nd_device_notify);
 
@@ -296,7 +302,7 @@ static void nvdimm_bus_release(struct device *dev)
        kfree(nvdimm_bus);
 }
 
-static bool is_nvdimm_bus(struct device *dev)
+bool is_nvdimm_bus(struct device *dev)
 {
        return dev->release == nvdimm_bus_release;
 }
@@ -341,7 +347,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
                return NULL;
        INIT_LIST_HEAD(&nvdimm_bus->list);
        INIT_LIST_HEAD(&nvdimm_bus->mapping_list);
-       init_waitqueue_head(&nvdimm_bus->probe_wait);
+       init_waitqueue_head(&nvdimm_bus->wait);
        nvdimm_bus->id = ida_simple_get(&nd_ida, 0, 0, GFP_KERNEL);
        if (nvdimm_bus->id < 0) {
                kfree(nvdimm_bus);
@@ -426,6 +432,9 @@ static int nd_bus_remove(struct device *dev)
        list_del_init(&nvdimm_bus->list);
        mutex_unlock(&nvdimm_bus_list_mutex);
 
+       wait_event(nvdimm_bus->wait,
+                       atomic_read(&nvdimm_bus->ioctl_active) == 0);
+
        nd_synchronize();
        device_for_each_child(&nvdimm_bus->dev, NULL, child_unregister);
 
@@ -547,13 +556,38 @@ EXPORT_SYMBOL(nd_device_register);
 
 void nd_device_unregister(struct device *dev, enum nd_async_mode mode)
 {
+       bool killed;
+
        switch (mode) {
        case ND_ASYNC:
+               /*
+                * In the async case this is being triggered with the
+                * device lock held and the unregistration work needs to
+                * be moved out of line iff this is thread has won the
+                * race to schedule the deletion.
+                */
+               if (!kill_device(dev))
+                       return;
+
                get_device(dev);
                async_schedule_domain(nd_async_device_unregister, dev,
                                &nd_async_domain);
                break;
        case ND_SYNC:
+               /*
+                * In the sync case the device is being unregistered due
+                * to a state change of the parent. Claim the kill state
+                * to synchronize against other unregistration requests,
+                * or otherwise let the async path handle it if the
+                * unregistration was already queued.
+                */
+               nd_device_lock(dev);
+               killed = kill_device(dev);
+               nd_device_unlock(dev);
+
+               if (!killed)
+                       return;
+
                nd_synchronize();
                device_unregister(dev);
                break;
@@ -859,10 +893,12 @@ void wait_nvdimm_bus_probe_idle(struct device *dev)
        do {
                if (nvdimm_bus->probe_active == 0)
                        break;
-               nvdimm_bus_unlock(&nvdimm_bus->dev);
-               wait_event(nvdimm_bus->probe_wait,
+               nvdimm_bus_unlock(dev);
+               nd_device_unlock(dev);
+               wait_event(nvdimm_bus->wait,
                                nvdimm_bus->probe_active == 0);
-               nvdimm_bus_lock(&nvdimm_bus->dev);
+               nd_device_lock(dev);
+               nvdimm_bus_lock(dev);
        } while (true);
 }
 
@@ -945,20 +981,19 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
                int read_only, unsigned int ioctl_cmd, unsigned long arg)
 {
        struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
-       static char out_env[ND_CMD_MAX_ENVELOPE];
-       static char in_env[ND_CMD_MAX_ENVELOPE];
        const struct nd_cmd_desc *desc = NULL;
        unsigned int cmd = _IOC_NR(ioctl_cmd);
        struct device *dev = &nvdimm_bus->dev;
        void __user *p = (void __user *) arg;
+       char *out_env = NULL, *in_env = NULL;
        const char *cmd_name, *dimm_name;
        u32 in_len = 0, out_len = 0;
        unsigned int func = cmd;
        unsigned long cmd_mask;
        struct nd_cmd_pkg pkg;
        int rc, i, cmd_rc;
+       void *buf = NULL;
        u64 buf_len = 0;
-       void *buf;
 
        if (nvdimm) {
                desc = nd_cmd_dimm_desc(cmd);
@@ -989,7 +1024,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
                case ND_CMD_ARS_START:
                case ND_CMD_CLEAR_ERROR:
                case ND_CMD_CALL:
-                       dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n",
+                       dev_dbg(dev, "'%s' command while read-only.\n",
                                        nvdimm ? nvdimm_cmd_name(cmd)
                                        : nvdimm_bus_cmd_name(cmd));
                        return -EPERM;
@@ -998,6 +1033,9 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
                }
 
        /* process an input envelope */
+       in_env = kzalloc(ND_CMD_MAX_ENVELOPE, GFP_KERNEL);
+       if (!in_env)
+               return -ENOMEM;
        for (i = 0; i < desc->in_num; i++) {
                u32 in_size, copy;
 
@@ -1005,14 +1043,17 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
                if (in_size == UINT_MAX) {
                        dev_err(dev, "%s:%s unknown input size cmd: %s field: %d\n",
                                        __func__, dimm_name, cmd_name, i);
-                       return -ENXIO;
+                       rc = -ENXIO;
+                       goto out;
                }
-               if (in_len < sizeof(in_env))
-                       copy = min_t(u32, sizeof(in_env) - in_len, in_size);
+               if (in_len < ND_CMD_MAX_ENVELOPE)
+                       copy = min_t(u32, ND_CMD_MAX_ENVELOPE - in_len, in_size);
                else
                        copy = 0;
-               if (copy && copy_from_user(&in_env[in_len], p + in_len, copy))
-                       return -EFAULT;
+               if (copy && copy_from_user(&in_env[in_len], p + in_len, copy)) {
+                       rc = -EFAULT;
+                       goto out;
+               }
                in_len += in_size;
        }
 
@@ -1024,6 +1065,12 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
        }
 
        /* process an output envelope */
+       out_env = kzalloc(ND_CMD_MAX_ENVELOPE, GFP_KERNEL);
+       if (!out_env) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
        for (i = 0; i < desc->out_num; i++) {
                u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,
                                (u32 *) in_env, (u32 *) out_env, 0);
@@ -1032,15 +1079,18 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
                if (out_size == UINT_MAX) {
                        dev_dbg(dev, "%s unknown output size cmd: %s field: %d\n",
                                        dimm_name, cmd_name, i);
-                       return -EFAULT;
+                       rc = -EFAULT;
+                       goto out;
                }
-               if (out_len < sizeof(out_env))
-                       copy = min_t(u32, sizeof(out_env) - out_len, out_size);
+               if (out_len < ND_CMD_MAX_ENVELOPE)
+                       copy = min_t(u32, ND_CMD_MAX_ENVELOPE - out_len, out_size);
                else
                        copy = 0;
                if (copy && copy_from_user(&out_env[out_len],
-                                       p + in_len + out_len, copy))
-                       return -EFAULT;
+                                       p + in_len + out_len, copy)) {
+                       rc = -EFAULT;
+                       goto out;
+               }
                out_len += out_size;
        }
 
@@ -1048,19 +1098,23 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
        if (buf_len > ND_IOCTL_MAX_BUFLEN) {
                dev_dbg(dev, "%s cmd: %s buf_len: %llu > %d\n", dimm_name,
                                cmd_name, buf_len, ND_IOCTL_MAX_BUFLEN);
-               return -EINVAL;
+               rc = -EINVAL;
+               goto out;
        }
 
        buf = vmalloc(buf_len);
-       if (!buf)
-               return -ENOMEM;
+       if (!buf) {
+               rc = -ENOMEM;
+               goto out;
+       }
 
        if (copy_from_user(buf, p, buf_len)) {
                rc = -EFAULT;
                goto out;
        }
 
-       nvdimm_bus_lock(&nvdimm_bus->dev);
+       nd_device_lock(dev);
+       nvdimm_bus_lock(dev);
        rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
        if (rc)
                goto out_unlock;
@@ -1075,39 +1129,24 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
                nvdimm_account_cleared_poison(nvdimm_bus, clear_err->address,
                                clear_err->cleared);
        }
-       nvdimm_bus_unlock(&nvdimm_bus->dev);
 
        if (copy_to_user(p, buf, buf_len))
                rc = -EFAULT;
 
-       vfree(buf);
-       return rc;
-
- out_unlock:
-       nvdimm_bus_unlock(&nvdimm_bus->dev);
- out:
+out_unlock:
+       nvdimm_bus_unlock(dev);
+       nd_device_unlock(dev);
+out:
+       kfree(in_env);
+       kfree(out_env);
        vfree(buf);
        return rc;
 }
 
-static long nd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       long id = (long) file->private_data;
-       int rc = -ENXIO, ro;
-       struct nvdimm_bus *nvdimm_bus;
-
-       ro = ((file->f_flags & O_ACCMODE) == O_RDONLY);
-       mutex_lock(&nvdimm_bus_list_mutex);
-       list_for_each_entry(nvdimm_bus, &nvdimm_bus_list, list) {
-               if (nvdimm_bus->id == id) {
-                       rc = __nd_ioctl(nvdimm_bus, NULL, ro, cmd, arg);
-                       break;
-               }
-       }
-       mutex_unlock(&nvdimm_bus_list_mutex);
-
-       return rc;
-}
+enum nd_ioctl_mode {
+       BUS_IOCTL,
+       DIMM_IOCTL,
+};
 
 static int match_dimm(struct device *dev, void *data)
 {
@@ -1122,31 +1161,62 @@ static int match_dimm(struct device *dev, void *data)
        return 0;
 }
 
-static long nvdimm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long nd_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
+               enum nd_ioctl_mode mode)
+
 {
-       int rc = -ENXIO, ro;
-       struct nvdimm_bus *nvdimm_bus;
+       struct nvdimm_bus *nvdimm_bus, *found = NULL;
+       long id = (long) file->private_data;
+       struct nvdimm *nvdimm = NULL;
+       int rc, ro;
 
        ro = ((file->f_flags & O_ACCMODE) == O_RDONLY);
        mutex_lock(&nvdimm_bus_list_mutex);
        list_for_each_entry(nvdimm_bus, &nvdimm_bus_list, list) {
-               struct device *dev = device_find_child(&nvdimm_bus->dev,
-                               file->private_data, match_dimm);
-               struct nvdimm *nvdimm;
-
-               if (!dev)
-                       continue;
+               if (mode == DIMM_IOCTL) {
+                       struct device *dev;
+
+                       dev = device_find_child(&nvdimm_bus->dev,
+                                       file->private_data, match_dimm);
+                       if (!dev)
+                               continue;
+                       nvdimm = to_nvdimm(dev);
+                       found = nvdimm_bus;
+               } else if (nvdimm_bus->id == id) {
+                       found = nvdimm_bus;
+               }
 
-               nvdimm = to_nvdimm(dev);
-               rc = __nd_ioctl(nvdimm_bus, nvdimm, ro, cmd, arg);
-               put_device(dev);
-               break;
+               if (found) {
+                       atomic_inc(&nvdimm_bus->ioctl_active);
+                       break;
+               }
        }
        mutex_unlock(&nvdimm_bus_list_mutex);
 
+       if (!found)
+               return -ENXIO;
+
+       nvdimm_bus = found;
+       rc = __nd_ioctl(nvdimm_bus, nvdimm, ro, cmd, arg);
+
+       if (nvdimm)
+               put_device(&nvdimm->dev);
+       if (atomic_dec_and_test(&nvdimm_bus->ioctl_active))
+               wake_up(&nvdimm_bus->wait);
+
        return rc;
 }
 
+static long bus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       return nd_ioctl(file, cmd, arg, BUS_IOCTL);
+}
+
+static long dimm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       return nd_ioctl(file, cmd, arg, DIMM_IOCTL);
+}
+
 static int nd_open(struct inode *inode, struct file *file)
 {
        long minor = iminor(inode);
@@ -1158,16 +1228,16 @@ static int nd_open(struct inode *inode, struct file *file)
 static const struct file_operations nvdimm_bus_fops = {
        .owner = THIS_MODULE,
        .open = nd_open,
-       .unlocked_ioctl = nd_ioctl,
-       .compat_ioctl = nd_ioctl,
+       .unlocked_ioctl = bus_ioctl,
+       .compat_ioctl = bus_ioctl,
        .llseek = noop_llseek,
 };
 
 static const struct file_operations nvdimm_fops = {
        .owner = THIS_MODULE,
        .open = nd_open,
-       .unlocked_ioctl = nvdimm_ioctl,
-       .compat_ioctl = nvdimm_ioctl,
+       .unlocked_ioctl = dimm_ioctl,
+       .compat_ioctl = dimm_ioctl,
        .llseek = noop_llseek,
 };
 
index 5e1f060547bf2f24d6dcbab66ed23fd914d67447..9204f1e9fd1414d8650bb873969d0c3175b46f24 100644 (file)
@@ -246,7 +246,7 @@ static int nd_uuid_parse(struct device *dev, u8 *uuid_out, const char *buf,
  *
  * Enforce that uuids can only be changed while the device is disabled
  * (driver detached)
- * LOCKING: expects device_lock() is held on entry
+ * LOCKING: expects nd_device_lock() is held on entry
  */
 int nd_uuid_store(struct device *dev, u8 **uuid_out, const char *buf,
                size_t len)
@@ -347,15 +347,15 @@ static DEVICE_ATTR_RO(provider);
 
 static int flush_namespaces(struct device *dev, void *data)
 {
-       device_lock(dev);
-       device_unlock(dev);
+       nd_device_lock(dev);
+       nd_device_unlock(dev);
        return 0;
 }
 
 static int flush_regions_dimms(struct device *dev, void *data)
 {
-       device_lock(dev);
-       device_unlock(dev);
+       nd_device_lock(dev);
+       nd_device_unlock(dev);
        device_for_each_child(dev, NULL, flush_namespaces);
        return 0;
 }
index dfecd6e17043c6d0fc50c294931e31d49e4e2705..29a065e769ea897359778dba417a78d7a54c7053 100644 (file)
@@ -484,12 +484,12 @@ static ssize_t security_store(struct device *dev,
         * done while probing is idle and the DIMM is not in active use
         * in any region.
         */
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        wait_nvdimm_bus_probe_idle(dev);
        rc = __security_store(dev, buf, len);
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
index 2d8d7e554877b4df809745838ca5672180883165..a16e52251a3052a0a75dac512abff13b316c16a0 100644 (file)
@@ -410,7 +410,7 @@ static ssize_t alt_name_store(struct device *dev,
        struct nd_region *nd_region = to_nd_region(dev->parent);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        wait_nvdimm_bus_probe_idle(dev);
        rc = __alt_name_store(dev, buf, len);
@@ -418,7 +418,7 @@ static ssize_t alt_name_store(struct device *dev,
                rc = nd_namespace_label_update(nd_region, dev);
        dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc);
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc < 0 ? rc : len;
 }
@@ -1077,7 +1077,7 @@ static ssize_t size_store(struct device *dev,
        if (rc)
                return rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        wait_nvdimm_bus_probe_idle(dev);
        rc = __size_store(dev, val);
@@ -1103,7 +1103,7 @@ static ssize_t size_store(struct device *dev,
        dev_dbg(dev, "%llx %s (%d)\n", val, rc < 0 ? "fail" : "success", rc);
 
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc < 0 ? rc : len;
 }
@@ -1286,7 +1286,7 @@ static ssize_t uuid_store(struct device *dev,
        } else
                return -ENXIO;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        wait_nvdimm_bus_probe_idle(dev);
        if (to_ndns(dev)->claim)
@@ -1302,7 +1302,7 @@ static ssize_t uuid_store(struct device *dev,
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc < 0 ? rc : len;
 }
@@ -1376,7 +1376,7 @@ static ssize_t sector_size_store(struct device *dev,
        } else
                return -ENXIO;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        if (to_ndns(dev)->claim)
                rc = -EBUSY;
@@ -1387,7 +1387,7 @@ static ssize_t sector_size_store(struct device *dev,
        dev_dbg(dev, "result: %zd %s: %s%s", rc, rc < 0 ? "tried" : "wrote",
                        buf, buf[len - 1] == '\n' ? "" : "\n");
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc ? rc : len;
 }
@@ -1502,9 +1502,9 @@ static ssize_t holder_show(struct device *dev,
        struct nd_namespace_common *ndns = to_ndns(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        rc = sprintf(buf, "%s\n", ndns->claim ? dev_name(ndns->claim) : "");
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
@@ -1541,7 +1541,7 @@ static ssize_t holder_class_store(struct device *dev,
        struct nd_region *nd_region = to_nd_region(dev->parent);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        wait_nvdimm_bus_probe_idle(dev);
        rc = __holder_class_store(dev, buf);
@@ -1549,7 +1549,7 @@ static ssize_t holder_class_store(struct device *dev,
                rc = nd_namespace_label_update(nd_region, dev);
        dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc);
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc < 0 ? rc : len;
 }
@@ -1560,7 +1560,7 @@ static ssize_t holder_class_show(struct device *dev,
        struct nd_namespace_common *ndns = to_ndns(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        if (ndns->claim_class == NVDIMM_CCLASS_NONE)
                rc = sprintf(buf, "\n");
        else if ((ndns->claim_class == NVDIMM_CCLASS_BTT) ||
@@ -1572,7 +1572,7 @@ static ssize_t holder_class_show(struct device *dev,
                rc = sprintf(buf, "dax\n");
        else
                rc = sprintf(buf, "<unknown>\n");
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
@@ -1586,7 +1586,7 @@ static ssize_t mode_show(struct device *dev,
        char *mode;
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        claim = ndns->claim;
        if (claim && is_nd_btt(claim))
                mode = "safe";
@@ -1599,7 +1599,7 @@ static ssize_t mode_show(struct device *dev,
        else
                mode = "raw";
        rc = sprintf(buf, "%s\n", mode);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
@@ -1703,8 +1703,8 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev)
                 * Flush any in-progess probes / removals in the driver
                 * for the raw personality of this namespace.
                 */
-               device_lock(&ndns->dev);
-               device_unlock(&ndns->dev);
+               nd_device_lock(&ndns->dev);
+               nd_device_unlock(&ndns->dev);
                if (ndns->dev.driver) {
                        dev_dbg(&ndns->dev, "is active, can't bind %s\n",
                                        dev_name(dev));
index 391e88de3a2953b1527581c08345eb2f89360fb5..0ac52b6eb00e114677168d5c1e9597d6bb8b6f8b 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/sizes.h>
 #include <linux/mutex.h>
 #include <linux/nd.h>
+#include "nd.h"
 
 extern struct list_head nvdimm_bus_list;
 extern struct mutex nvdimm_bus_list_mutex;
@@ -17,10 +18,11 @@ extern struct workqueue_struct *nvdimm_wq;
 
 struct nvdimm_bus {
        struct nvdimm_bus_descriptor *nd_desc;
-       wait_queue_head_t probe_wait;
+       wait_queue_head_t wait;
        struct list_head list;
        struct device dev;
        int id, probe_active;
+       atomic_t ioctl_active;
        struct list_head mapping_list;
        struct mutex reconfig_mutex;
        struct badrange badrange;
@@ -181,4 +183,71 @@ ssize_t nd_namespace_store(struct device *dev,
                struct nd_namespace_common **_ndns, const char *buf,
                size_t len);
 struct nd_pfn *to_nd_pfn_safe(struct device *dev);
+bool is_nvdimm_bus(struct device *dev);
+
+#ifdef CONFIG_PROVE_LOCKING
+extern struct class *nd_class;
+
+enum {
+       LOCK_BUS,
+       LOCK_NDCTL,
+       LOCK_REGION,
+       LOCK_DIMM = LOCK_REGION,
+       LOCK_NAMESPACE,
+       LOCK_CLAIM,
+};
+
+static inline void debug_nvdimm_lock(struct device *dev)
+{
+       if (is_nd_region(dev))
+               mutex_lock_nested(&dev->lockdep_mutex, LOCK_REGION);
+       else if (is_nvdimm(dev))
+               mutex_lock_nested(&dev->lockdep_mutex, LOCK_DIMM);
+       else if (is_nd_btt(dev) || is_nd_pfn(dev) || is_nd_dax(dev))
+               mutex_lock_nested(&dev->lockdep_mutex, LOCK_CLAIM);
+       else if (dev->parent && (is_nd_region(dev->parent)))
+               mutex_lock_nested(&dev->lockdep_mutex, LOCK_NAMESPACE);
+       else if (is_nvdimm_bus(dev))
+               mutex_lock_nested(&dev->lockdep_mutex, LOCK_BUS);
+       else if (dev->class && dev->class == nd_class)
+               mutex_lock_nested(&dev->lockdep_mutex, LOCK_NDCTL);
+       else
+               dev_WARN(dev, "unknown lock level\n");
+}
+
+static inline void debug_nvdimm_unlock(struct device *dev)
+{
+       mutex_unlock(&dev->lockdep_mutex);
+}
+
+static inline void nd_device_lock(struct device *dev)
+{
+       device_lock(dev);
+       debug_nvdimm_lock(dev);
+}
+
+static inline void nd_device_unlock(struct device *dev)
+{
+       debug_nvdimm_unlock(dev);
+       device_unlock(dev);
+}
+#else
+static inline void nd_device_lock(struct device *dev)
+{
+       device_lock(dev);
+}
+
+static inline void nd_device_unlock(struct device *dev)
+{
+       device_unlock(dev);
+}
+
+static inline void debug_nvdimm_lock(struct device *dev)
+{
+}
+
+static inline void debug_nvdimm_unlock(struct device *dev)
+{
+}
+#endif
 #endif /* __ND_CORE_H__ */
index df2bdbd22450488af1c9c4d68a4a2569c64f143e..cb98b8fe786e2232bbdb1d0a371ce5df0e2e13a3 100644 (file)
@@ -67,7 +67,7 @@ static ssize_t mode_store(struct device *dev,
        struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
        ssize_t rc = 0;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        if (dev->driver)
                rc = -EBUSY;
@@ -89,7 +89,7 @@ static ssize_t mode_store(struct device *dev,
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc ? rc : len;
 }
@@ -132,14 +132,14 @@ static ssize_t align_store(struct device *dev,
        struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        rc = nd_size_select_store(dev, buf, &nd_pfn->align,
                        nd_pfn_supported_alignments());
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc ? rc : len;
 }
@@ -161,11 +161,11 @@ static ssize_t uuid_store(struct device *dev,
        struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        rc = nd_uuid_store(dev, &nd_pfn->uuid, buf, len);
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc ? rc : len;
 }
@@ -190,13 +190,13 @@ static ssize_t namespace_store(struct device *dev,
        struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        rc = nd_namespace_store(dev, &nd_pfn->ndns, buf, len);
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
@@ -208,7 +208,7 @@ static ssize_t resource_show(struct device *dev,
        struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        if (dev->driver) {
                struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
                u64 offset = __le64_to_cpu(pfn_sb->dataoff);
@@ -222,7 +222,7 @@ static ssize_t resource_show(struct device *dev,
                /* no address to convey if the pfn instance is disabled */
                rc = -ENXIO;
        }
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
@@ -234,7 +234,7 @@ static ssize_t size_show(struct device *dev,
        struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        if (dev->driver) {
                struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
                u64 offset = __le64_to_cpu(pfn_sb->dataoff);
@@ -250,7 +250,7 @@ static ssize_t size_show(struct device *dev,
                /* no size to convey if the pfn instance is disabled */
                rc = -ENXIO;
        }
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
@@ -655,6 +655,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
        resource_size_t start, size;
        struct nd_region *nd_region;
        unsigned long npfns, align;
+       u32 end_trunc;
        struct nd_pfn_sb *pfn_sb;
        phys_addr_t offset;
        const char *sig;
@@ -696,6 +697,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
        size = resource_size(&nsio->res);
        npfns = PHYS_PFN(size - SZ_8K);
        align = max(nd_pfn->align, (1UL << SUBSECTION_SHIFT));
+       end_trunc = start + size - ALIGN_DOWN(start + size, align);
        if (nd_pfn->mode == PFN_MODE_PMEM) {
                /*
                 * The altmap should be padded out to the block size used
@@ -714,7 +716,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
                return -ENXIO;
        }
 
-       npfns = PHYS_PFN(size - offset);
+       npfns = PHYS_PFN(size - offset - end_trunc);
        pfn_sb->mode = cpu_to_le32(nd_pfn->mode);
        pfn_sb->dataoff = cpu_to_le64(offset);
        pfn_sb->npfns = cpu_to_le64(npfns);
@@ -723,6 +725,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
        memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16);
        pfn_sb->version_major = cpu_to_le16(1);
        pfn_sb->version_minor = cpu_to_le16(3);
+       pfn_sb->end_trunc = cpu_to_le32(end_trunc);
        pfn_sb->align = cpu_to_le32(nd_pfn->align);
        checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb);
        pfn_sb->checksum = cpu_to_le64(checksum);
index 2bf3acd696132c9d48899fc7cb3fe35e25305875..4c121dd03dd91b75af3ec9b55d84ae8cc3e80fe2 100644 (file)
@@ -522,8 +522,8 @@ static int nd_pmem_remove(struct device *dev)
                nvdimm_namespace_detach_btt(to_nd_btt(dev));
        else {
                /*
-                * Note, this assumes device_lock() context to not race
-                * nd_pmem_notify()
+                * Note, this assumes nd_device_lock() context to not
+                * race nd_pmem_notify()
                 */
                sysfs_put(pmem->bb_state);
                pmem->bb_state = NULL;
index ef46cc3a71aefef4b7927dabdb44a4759a5dd98a..37bf8719a2a446dbcdaa97f5d71cff442b7e0098 100644 (file)
@@ -34,17 +34,6 @@ static int nd_region_probe(struct device *dev)
        if (rc)
                return rc;
 
-       rc = nd_region_register_namespaces(nd_region, &err);
-       if (rc < 0)
-               return rc;
-
-       ndrd = dev_get_drvdata(dev);
-       ndrd->ns_active = rc;
-       ndrd->ns_count = rc + err;
-
-       if (rc && err && rc == err)
-               return -ENODEV;
-
        if (is_nd_pmem(&nd_region->dev)) {
                struct resource ndr_res;
 
@@ -60,6 +49,17 @@ static int nd_region_probe(struct device *dev)
                nvdimm_badblocks_populate(nd_region, &nd_region->bb, &ndr_res);
        }
 
+       rc = nd_region_register_namespaces(nd_region, &err);
+       if (rc < 0)
+               return rc;
+
+       ndrd = dev_get_drvdata(dev);
+       ndrd->ns_active = rc;
+       ndrd->ns_count = rc + err;
+
+       if (rc && err && rc == err)
+               return -ENODEV;
+
        nd_region->btt_seed = nd_btt_create(nd_region);
        nd_region->pfn_seed = nd_pfn_create(nd_region);
        nd_region->dax_seed = nd_dax_create(nd_region);
@@ -102,7 +102,7 @@ static int nd_region_remove(struct device *dev)
        nvdimm_bus_unlock(dev);
 
        /*
-        * Note, this assumes device_lock() context to not race
+        * Note, this assumes nd_device_lock() context to not race
         * nd_region_notify()
         */
        sysfs_put(nd_region->bb_state);
index 56f2227f192a1897575f587af68cbf04368077d4..af30cbe7a8ea26fd5eb643af56e1a9bffaeda7ff 100644 (file)
@@ -331,7 +331,7 @@ static ssize_t set_cookie_show(struct device *dev,
         * the v1.1 namespace label cookie definition. To read all this
         * data we need to wait for probing to settle.
         */
-       device_lock(dev);
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        wait_nvdimm_bus_probe_idle(dev);
        if (nd_region->ndr_mappings) {
@@ -348,7 +348,7 @@ static ssize_t set_cookie_show(struct device *dev,
                }
        }
        nvdimm_bus_unlock(dev);
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        if (rc)
                return rc;
@@ -424,10 +424,12 @@ static ssize_t available_size_show(struct device *dev,
         * memory nvdimm_bus_lock() is dropped, but that's userspace's
         * problem to not race itself.
         */
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        wait_nvdimm_bus_probe_idle(dev);
        available = nd_region_available_dpa(nd_region);
        nvdimm_bus_unlock(dev);
+       nd_device_unlock(dev);
 
        return sprintf(buf, "%llu\n", available);
 }
@@ -439,10 +441,12 @@ static ssize_t max_available_extent_show(struct device *dev,
        struct nd_region *nd_region = to_nd_region(dev);
        unsigned long long available = 0;
 
+       nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        wait_nvdimm_bus_probe_idle(dev);
        available = nd_region_allocatable_dpa(nd_region);
        nvdimm_bus_unlock(dev);
+       nd_device_unlock(dev);
 
        return sprintf(buf, "%llu\n", available);
 }
@@ -561,12 +565,12 @@ static ssize_t region_badblocks_show(struct device *dev,
        struct nd_region *nd_region = to_nd_region(dev);
        ssize_t rc;
 
-       device_lock(dev);
+       nd_device_lock(dev);
        if (dev->driver)
                rc = badblocks_show(&nd_region->bb, buf, 0);
        else
                rc = -ENXIO;
-       device_unlock(dev);
+       nd_device_unlock(dev);
 
        return rc;
 }
index cc09b81fc7f434ccb46ee2afed2def35bb4ccbe5..d3d6b7bd690335d072d265e8646d090bdc2ab2e4 100644 (file)
@@ -1286,6 +1286,9 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
         */
        if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
                mutex_lock(&ctrl->scan_lock);
+               mutex_lock(&ctrl->subsys->lock);
+               nvme_mpath_start_freeze(ctrl->subsys);
+               nvme_mpath_wait_freeze(ctrl->subsys);
                nvme_start_freeze(ctrl);
                nvme_wait_freeze(ctrl);
        }
@@ -1316,6 +1319,8 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
                nvme_update_formats(ctrl);
        if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
                nvme_unfreeze(ctrl);
+               nvme_mpath_unfreeze(ctrl->subsys);
+               mutex_unlock(&ctrl->subsys->lock);
                mutex_unlock(&ctrl->scan_lock);
        }
        if (effects & NVME_CMD_EFFECTS_CCC)
@@ -1715,6 +1720,7 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
        if (ns->head->disk) {
                nvme_update_disk_info(ns->head->disk, ns, id);
                blk_queue_stack_limits(ns->head->disk->queue, ns->queue);
+               revalidate_disk(ns->head->disk);
        }
 #endif
 }
@@ -2251,6 +2257,16 @@ static const struct nvme_core_quirk_entry core_quirks[] = {
                .vid = 0x1179,
                .mn = "THNSF5256GPUK TOSHIBA",
                .quirks = NVME_QUIRK_NO_APST,
+       },
+       {
+               /*
+                * This LiteON CL1-3D*-Q11 firmware version has a race
+                * condition associated with actions related to suspend to idle
+                * LiteON has resolved the problem in future firmware
+                */
+               .vid = 0x14a4,
+               .fr = "22301111",
+               .quirks = NVME_QUIRK_SIMPLE_SUSPEND,
        }
 };
 
@@ -2311,17 +2327,15 @@ static void nvme_init_subnqn(struct nvme_subsystem *subsys, struct nvme_ctrl *ct
        memset(subsys->subnqn + off, 0, sizeof(subsys->subnqn) - off);
 }
 
-static void __nvme_release_subsystem(struct nvme_subsystem *subsys)
+static void nvme_release_subsystem(struct device *dev)
 {
+       struct nvme_subsystem *subsys =
+               container_of(dev, struct nvme_subsystem, dev);
+
        ida_simple_remove(&nvme_subsystems_ida, subsys->instance);
        kfree(subsys);
 }
 
-static void nvme_release_subsystem(struct device *dev)
-{
-       __nvme_release_subsystem(container_of(dev, struct nvme_subsystem, dev));
-}
-
 static void nvme_destroy_subsystem(struct kref *ref)
 {
        struct nvme_subsystem *subsys =
@@ -2477,7 +2491,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        mutex_lock(&nvme_subsystems_lock);
        found = __nvme_find_get_subsystem(subsys->subnqn);
        if (found) {
-               __nvme_release_subsystem(subsys);
+               put_device(&subsys->dev);
                subsys = found;
 
                if (!nvme_validate_cntlid(subsys, ctrl, id)) {
@@ -2489,6 +2503,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
                if (ret) {
                        dev_err(ctrl->device,
                                "failed to register subsystem device.\n");
+                       put_device(&subsys->dev);
                        goto out_unlock;
                }
                ida_init(&subsys->ns_ida);
@@ -2511,7 +2526,6 @@ out_put_subsystem:
        nvme_put_subsystem(subsys);
 out_unlock:
        mutex_unlock(&nvme_subsystems_lock);
-       put_device(&subsys->dev);
        return ret;
 }
 
@@ -2593,6 +2607,9 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                        goto out_free;
        }
 
+       if (!(ctrl->ops->flags & NVME_F_FABRICS))
+               ctrl->cntlid = le16_to_cpu(id->cntlid);
+
        if (!ctrl->identified) {
                int i;
 
@@ -2693,7 +2710,6 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                        goto out_free;
                }
        } else {
-               ctrl->cntlid = le16_to_cpu(id->cntlid);
                ctrl->hmpre = le32_to_cpu(id->hmpre);
                ctrl->hmmin = le32_to_cpu(id->hmmin);
                ctrl->hmminds = le32_to_cpu(id->hmminds);
@@ -3573,6 +3589,13 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
        struct nvme_ns *ns, *next;
        LIST_HEAD(ns_list);
 
+       /*
+        * make sure to requeue I/O to all namespaces as these
+        * might result from the scan itself and must complete
+        * for the scan_work to make progress
+        */
+       nvme_mpath_clear_ctrl_paths(ctrl);
+
        /* prevent racing with ns scanning */
        flush_work(&ctrl->scan_work);
 
index a9a9276779708e2beca5497131cbfc547518e58e..af831d3d15d072339b20ef297b197bae939b4d55 100644 (file)
@@ -12,9 +12,34 @@ module_param(multipath, bool, 0444);
 MODULE_PARM_DESC(multipath,
        "turn on native support for multiple controllers per subsystem");
 
-inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
+void nvme_mpath_unfreeze(struct nvme_subsystem *subsys)
 {
-       return multipath && ctrl->subsys && (ctrl->subsys->cmic & (1 << 3));
+       struct nvme_ns_head *h;
+
+       lockdep_assert_held(&subsys->lock);
+       list_for_each_entry(h, &subsys->nsheads, entry)
+               if (h->disk)
+                       blk_mq_unfreeze_queue(h->disk->queue);
+}
+
+void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
+{
+       struct nvme_ns_head *h;
+
+       lockdep_assert_held(&subsys->lock);
+       list_for_each_entry(h, &subsys->nsheads, entry)
+               if (h->disk)
+                       blk_mq_freeze_queue_wait(h->disk->queue);
+}
+
+void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
+{
+       struct nvme_ns_head *h;
+
+       lockdep_assert_held(&subsys->lock);
+       list_for_each_entry(h, &subsys->nsheads, entry)
+               if (h->disk)
+                       blk_freeze_queue_start(h->disk->queue);
 }
 
 /*
@@ -109,18 +134,34 @@ static const char *nvme_ana_state_names[] = {
        [NVME_ANA_CHANGE]               = "change",
 };
 
-void nvme_mpath_clear_current_path(struct nvme_ns *ns)
+bool nvme_mpath_clear_current_path(struct nvme_ns *ns)
 {
        struct nvme_ns_head *head = ns->head;
+       bool changed = false;
        int node;
 
        if (!head)
-               return;
+               goto out;
 
        for_each_node(node) {
-               if (ns == rcu_access_pointer(head->current_path[node]))
+               if (ns == rcu_access_pointer(head->current_path[node])) {
                        rcu_assign_pointer(head->current_path[node], NULL);
+                       changed = true;
+               }
        }
+out:
+       return changed;
+}
+
+void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
+{
+       struct nvme_ns *ns;
+
+       mutex_lock(&ctrl->scan_lock);
+       list_for_each_entry(ns, &ctrl->namespaces, list)
+               if (nvme_mpath_clear_current_path(ns))
+                       kblockd_schedule_work(&ns->head->requeue_work);
+       mutex_unlock(&ctrl->scan_lock);
 }
 
 static bool nvme_path_is_disabled(struct nvme_ns *ns)
@@ -231,6 +272,24 @@ inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
        return ns;
 }
 
+static bool nvme_available_path(struct nvme_ns_head *head)
+{
+       struct nvme_ns *ns;
+
+       list_for_each_entry_rcu(ns, &head->list, siblings) {
+               switch (ns->ctrl->state) {
+               case NVME_CTRL_LIVE:
+               case NVME_CTRL_RESETTING:
+               case NVME_CTRL_CONNECTING:
+                       /* fallthru */
+                       return true;
+               default:
+                       break;
+               }
+       }
+       return false;
+}
+
 static blk_qc_t nvme_ns_head_make_request(struct request_queue *q,
                struct bio *bio)
 {
@@ -257,14 +316,14 @@ static blk_qc_t nvme_ns_head_make_request(struct request_queue *q,
                                      disk_devt(ns->head->disk),
                                      bio->bi_iter.bi_sector);
                ret = direct_make_request(bio);
-       } else if (!list_empty_careful(&head->list)) {
-               dev_warn_ratelimited(dev, "no path available - requeuing I/O\n");
+       } else if (nvme_available_path(head)) {
+               dev_warn_ratelimited(dev, "no usable path - requeuing I/O\n");
 
                spin_lock_irq(&head->requeue_lock);
                bio_list_add(&head->requeue_list, bio);
                spin_unlock_irq(&head->requeue_lock);
        } else {
-               dev_warn_ratelimited(dev, "no path - failing I/O\n");
+               dev_warn_ratelimited(dev, "no available path - failing I/O\n");
 
                bio->bi_status = BLK_STS_IOERR;
                bio_endio(bio);
@@ -369,6 +428,7 @@ static void nvme_mpath_set_live(struct nvme_ns *ns)
                srcu_read_unlock(&head->srcu, srcu_idx);
        }
 
+       synchronize_srcu(&ns->head->srcu);
        kblockd_schedule_work(&ns->head->requeue_work);
 }
 
@@ -622,7 +682,8 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
 {
        int error;
 
-       if (!nvme_ctrl_use_ana(ctrl))
+       /* check if multipath is enabled and we have the capability */
+       if (!multipath || !ctrl->subsys || !(ctrl->subsys->cmic & (1 << 3)))
                return 0;
 
        ctrl->anacap = id->anacap;
index 716a876119c83a911bcc323c84edfc059bf3b7eb..2d678fb968c745598e20a6b4ca3a839ae425dd5c 100644 (file)
@@ -92,6 +92,11 @@ enum nvme_quirks {
         * Broken Write Zeroes.
         */
        NVME_QUIRK_DISABLE_WRITE_ZEROES         = (1 << 9),
+
+       /*
+        * Force simple suspend/resume path.
+        */
+       NVME_QUIRK_SIMPLE_SUSPEND               = (1 << 10),
 };
 
 /*
@@ -485,7 +490,14 @@ extern const struct attribute_group *nvme_ns_id_attr_groups[];
 extern const struct block_device_operations nvme_ns_head_ops;
 
 #ifdef CONFIG_NVME_MULTIPATH
-bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl);
+static inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
+{
+       return ctrl->ana_log_buf != NULL;
+}
+
+void nvme_mpath_unfreeze(struct nvme_subsystem *subsys);
+void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys);
+void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
 void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
                        struct nvme_ctrl *ctrl, int *flags);
 void nvme_failover_req(struct request *req);
@@ -496,7 +508,8 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head);
 int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id);
 void nvme_mpath_uninit(struct nvme_ctrl *ctrl);
 void nvme_mpath_stop(struct nvme_ctrl *ctrl);
-void nvme_mpath_clear_current_path(struct nvme_ns *ns);
+bool nvme_mpath_clear_current_path(struct nvme_ns *ns);
+void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl);
 struct nvme_ns *nvme_find_path(struct nvme_ns_head *head);
 
 static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
@@ -544,7 +557,11 @@ static inline void nvme_mpath_add_disk(struct nvme_ns *ns,
 static inline void nvme_mpath_remove_disk(struct nvme_ns_head *head)
 {
 }
-static inline void nvme_mpath_clear_current_path(struct nvme_ns *ns)
+static inline bool nvme_mpath_clear_current_path(struct nvme_ns *ns)
+{
+       return false;
+}
+static inline void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
 {
 }
 static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
@@ -564,6 +581,15 @@ static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
 static inline void nvme_mpath_stop(struct nvme_ctrl *ctrl)
 {
 }
+static inline void nvme_mpath_unfreeze(struct nvme_subsystem *subsys)
+{
+}
+static inline void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
+{
+}
+static inline void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
+{
+}
 #endif /* CONFIG_NVME_MULTIPATH */
 
 #ifdef CONFIG_NVM
index bb970ca82517b1213cb4922225822edb78e23b4d..732d5b63ec0540b1a40566136c4118f34482f5aa 100644 (file)
@@ -2254,9 +2254,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
        if (!dev->ctrl.tagset) {
                dev->tagset.ops = &nvme_mq_ops;
                dev->tagset.nr_hw_queues = dev->online_queues - 1;
-               dev->tagset.nr_maps = 1; /* default */
-               if (dev->io_queues[HCTX_TYPE_READ])
-                       dev->tagset.nr_maps++;
+               dev->tagset.nr_maps = 2; /* default + read */
                if (dev->io_queues[HCTX_TYPE_POLL])
                        dev->tagset.nr_maps++;
                dev->tagset.timeout = NVME_IO_TIMEOUT;
@@ -2697,7 +2695,7 @@ static void nvme_async_probe(void *data, async_cookie_t cookie)
 {
        struct nvme_dev *dev = data;
 
-       nvme_reset_ctrl_sync(&dev->ctrl);
+       flush_work(&dev->ctrl.reset_work);
        flush_work(&dev->ctrl.scan_work);
        nvme_put_ctrl(&dev->ctrl);
 }
@@ -2763,6 +2761,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
 
+       nvme_reset_ctrl(&dev->ctrl);
        nvme_get_ctrl(&dev->ctrl);
        async_schedule(nvme_async_probe, dev);
 
@@ -2848,7 +2847,7 @@ static int nvme_resume(struct device *dev)
        struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev));
        struct nvme_ctrl *ctrl = &ndev->ctrl;
 
-       if (pm_resume_via_firmware() || !ctrl->npss ||
+       if (ndev->last_ps == U32_MAX ||
            nvme_set_power_state(ctrl, ndev->last_ps) != 0)
                nvme_reset_ctrl(ctrl);
        return 0;
@@ -2861,6 +2860,8 @@ static int nvme_suspend(struct device *dev)
        struct nvme_ctrl *ctrl = &ndev->ctrl;
        int ret = -EBUSY;
 
+       ndev->last_ps = U32_MAX;
+
        /*
         * The platform does not remove power for a kernel managed suspend so
         * use host managed nvme power settings for lowest idle power if
@@ -2868,8 +2869,15 @@ static int nvme_suspend(struct device *dev)
         * shutdown.  But if the firmware is involved after the suspend or the
         * device does not support any non-default power states, shut down the
         * device fully.
+        *
+        * If ASPM is not enabled for the device, shut down the device and allow
+        * the PCI bus layer to put it into D3 in order to take the PCIe link
+        * down, so as to allow the platform to achieve its minimum low-power
+        * state (which may not be possible if the link is up).
         */
-       if (pm_suspend_via_firmware() || !ctrl->npss) {
+       if (pm_suspend_via_firmware() || !ctrl->npss ||
+           !pcie_aspm_enabled(pdev) ||
+           (ndev->ctrl.quirks & NVME_QUIRK_SIMPLE_SUSPEND)) {
                nvme_dev_disable(ndev, true);
                return 0;
        }
@@ -2882,7 +2890,6 @@ static int nvme_suspend(struct device *dev)
            ctrl->state != NVME_CTRL_ADMIN_ONLY)
                goto unfreeze;
 
-       ndev->last_ps = 0;
        ret = nvme_get_power_state(ctrl, &ndev->last_ps);
        if (ret < 0)
                goto unfreeze;
@@ -3029,6 +3036,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_LIGHTNVM, },
        { PCI_DEVICE(0x1d1d, 0x2601),   /* CNEX Granby */
                .driver_data = NVME_QUIRK_LIGHTNVM, },
+       { PCI_DEVICE(0x10ec, 0x5762),   /* ADATA SX6000LNP */
+               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
index a249db528d543dcad37e9b5162cc4b196a2f41e1..1a6449bc547b91ab7460b817fd6aada3ca5b5acd 100644 (file)
@@ -562,13 +562,17 @@ out_destroy_cm_id:
        return ret;
 }
 
+static void __nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
+{
+       rdma_disconnect(queue->cm_id);
+       ib_drain_qp(queue->qp);
+}
+
 static void nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
 {
        if (!test_and_clear_bit(NVME_RDMA_Q_LIVE, &queue->flags))
                return;
-
-       rdma_disconnect(queue->cm_id);
-       ib_drain_qp(queue->qp);
+       __nvme_rdma_stop_queue(queue);
 }
 
 static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue)
@@ -607,11 +611,13 @@ static int nvme_rdma_start_queue(struct nvme_rdma_ctrl *ctrl, int idx)
        else
                ret = nvmf_connect_admin_queue(&ctrl->ctrl);
 
-       if (!ret)
+       if (!ret) {
                set_bit(NVME_RDMA_Q_LIVE, &queue->flags);
-       else
+       } else {
+               __nvme_rdma_stop_queue(queue);
                dev_info(ctrl->ctrl.device,
                        "failed to connect queue: %d ret=%d\n", idx, ret);
+       }
        return ret;
 }
 
index cd52b9f153766602036eb9e7322f845551fff855..98613a45bd3b408e343b8e89f9605475f1cb47b9 100644 (file)
@@ -675,6 +675,7 @@ static void nvmet_port_subsys_drop_link(struct config_item *parent,
 
 found:
        list_del(&p->entry);
+       nvmet_port_del_ctrls(port, subsys);
        nvmet_port_disc_changed(port, subsys);
 
        if (list_empty(&port->subsystems))
index dad0243c7c96cfd5f84d5e996b09dcc5fa78d07b..3a67e244e5685a35f65e24e322f85b9557bba37d 100644 (file)
@@ -46,6 +46,9 @@ inline u16 errno_to_nvme_status(struct nvmet_req *req, int errno)
        u16 status;
 
        switch (errno) {
+       case 0:
+               status = NVME_SC_SUCCESS;
+               break;
        case -ENOSPC:
                req->error_loc = offsetof(struct nvme_rw_command, length);
                status = NVME_SC_CAP_EXCEEDED | NVME_SC_DNR;
@@ -280,6 +283,18 @@ void nvmet_unregister_transport(const struct nvmet_fabrics_ops *ops)
 }
 EXPORT_SYMBOL_GPL(nvmet_unregister_transport);
 
+void nvmet_port_del_ctrls(struct nvmet_port *port, struct nvmet_subsys *subsys)
+{
+       struct nvmet_ctrl *ctrl;
+
+       mutex_lock(&subsys->lock);
+       list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
+               if (ctrl->port == port)
+                       ctrl->ops->delete_ctrl(ctrl);
+       }
+       mutex_unlock(&subsys->lock);
+}
+
 int nvmet_enable_port(struct nvmet_port *port)
 {
        const struct nvmet_fabrics_ops *ops;
index b16dc3981c698749a1a5f85e7066e68c946dfed4..0940c5024a3456457a732c6ae97195e346fd097d 100644 (file)
@@ -654,6 +654,14 @@ static void nvme_loop_remove_port(struct nvmet_port *port)
        mutex_lock(&nvme_loop_ports_mutex);
        list_del_init(&port->entry);
        mutex_unlock(&nvme_loop_ports_mutex);
+
+       /*
+        * Ensure any ctrls that are in the process of being
+        * deleted are in fact deleted before we return
+        * and free the port. This is to prevent active
+        * ctrls from using a port after it's freed.
+        */
+       flush_workqueue(nvme_delete_wq);
 }
 
 static const struct nvmet_fabrics_ops nvme_loop_ops = {
index 6ee66c6107391899898f812a4b4347b284d6c333..c51f8dd01dc487a1395e3a3ff5350cf260046118 100644 (file)
@@ -418,6 +418,9 @@ void nvmet_port_send_ana_event(struct nvmet_port *port);
 int nvmet_register_transport(const struct nvmet_fabrics_ops *ops);
 void nvmet_unregister_transport(const struct nvmet_fabrics_ops *ops);
 
+void nvmet_port_del_ctrls(struct nvmet_port *port,
+                         struct nvmet_subsys *subsys);
+
 int nvmet_enable_port(struct nvmet_port *port);
 void nvmet_disable_port(struct nvmet_port *port);
 
index 6f303b91f6e70d7a438879cfcfe3294936aaa4e0..9e0c429cd08a263c917f66113425630f3902f235 100644 (file)
@@ -224,10 +224,17 @@ int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
        if (!config->base_dev)
                return -EINVAL;
 
-       if (nvmem->read_only)
-               nvmem->eeprom = bin_attr_ro_root_nvmem;
-       else
-               nvmem->eeprom = bin_attr_rw_root_nvmem;
+       if (nvmem->read_only) {
+               if (config->root_only)
+                       nvmem->eeprom = bin_attr_ro_root_nvmem;
+               else
+                       nvmem->eeprom = bin_attr_ro_nvmem;
+       } else {
+               if (config->root_only)
+                       nvmem->eeprom = bin_attr_rw_root_nvmem;
+               else
+                       nvmem->eeprom = bin_attr_rw_nvmem;
+       }
        nvmem->eeprom.attr.name = "eeprom";
        nvmem->eeprom.size = nvmem->size;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
index 7f84bb4903caaf4d63847689972ff2c005cb9279..a296eaf52a5b23c377349b59688ffa62ec66db4d 100644 (file)
@@ -277,7 +277,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw);
  * of_irq_parse_one - Resolve an interrupt for a device
  * @device: the device whose interrupt is to be resolved
  * @index: index of the interrupt to resolve
- * @out_irq: structure of_irq filled by this function
+ * @out_irq: structure of_phandle_args filled by this function
  *
  * This function resolves an interrupt for a node by walking the interrupt tree,
  * finding which interrupt controller node it is attached to, and returning the
index c1b67dd7cd6eed61c75e9fe4234565dd9c329c5b..83c766233181096887f7d4a204214012b8223166 100644 (file)
@@ -206,16 +206,22 @@ static int adjust_local_phandle_references(struct device_node *local_fixups,
        for_each_child_of_node(local_fixups, child) {
 
                for_each_child_of_node(overlay, overlay_child)
-                       if (!node_name_cmp(child, overlay_child))
+                       if (!node_name_cmp(child, overlay_child)) {
+                               of_node_put(overlay_child);
                                break;
+                       }
 
-               if (!overlay_child)
+               if (!overlay_child) {
+                       of_node_put(child);
                        return -EINVAL;
+               }
 
                err = adjust_local_phandle_references(child, overlay_child,
                                phandle_delta);
-               if (err)
+               if (err) {
+                       of_node_put(child);
                        return err;
+               }
        }
 
        return 0;
index 29ed5ec1ac27bf1c1d0b2d4028123a992594a513..1b27b5af3d552f8622b075c80dd365561347ec6e 100644 (file)
@@ -1025,10 +1025,15 @@ static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
        if (state == PCI_D0) {
                pci_platform_power_transition(dev, PCI_D0);
                /*
-                * Mandatory power management transition delays are
-                * handled in the PCIe portdrv resume hooks.
+                * Mandatory power management transition delays, see
+                * PCI Express Base Specification Revision 2.0 Section
+                * 6.6.1: Conventional Reset.  Do not delay for
+                * devices powered on/off by corresponding bridge,
+                * because have already delayed for the bridge.
                 */
                if (dev->runtime_d3cold) {
+                       if (dev->d3cold_delay && !dev->imm_ready)
+                               msleep(dev->d3cold_delay);
                        /*
                         * When powering on a bridge from D3cold, the
                         * whole hierarchy may be powered on into
@@ -4602,16 +4607,14 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
 
        return pci_dev_wait(dev, "PM D3->D0", PCIE_RESET_READY_POLL_MS);
 }
-
 /**
- * pcie_wait_for_link_delay - Wait until link is active or inactive
+ * pcie_wait_for_link - Wait until link is active or inactive
  * @pdev: Bridge device
  * @active: waiting for active or inactive?
- * @delay: Delay to wait after link has become active (in ms)
  *
  * Use this to wait till link becomes active or inactive.
  */
-bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay)
+bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
 {
        int timeout = 1000;
        bool ret;
@@ -4648,25 +4651,13 @@ bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay)
                timeout -= 10;
        }
        if (active && ret)
-               msleep(delay);
+               msleep(100);
        else if (ret != active)
                pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
                        active ? "set" : "cleared");
        return ret == active;
 }
 
-/**
- * pcie_wait_for_link - Wait until link is active or inactive
- * @pdev: Bridge device
- * @active: waiting for active or inactive?
- *
- * Use this to wait till link becomes active or inactive.
- */
-bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
-{
-       return pcie_wait_for_link_delay(pdev, active, 100);
-}
-
 void pci_reset_secondary_bus(struct pci_dev *dev)
 {
        u16 ctrl;
index 1be03a97cb92c1ce9486a4b6ea0f037f7c18067f..d22d1b80770198c5b3fa334b563efd90ae2e7e47 100644 (file)
@@ -497,7 +497,6 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
 void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state,
                      u32 service);
 
-bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay);
 bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
 #ifdef CONFIG_PCIEASPM
 void pcie_aspm_init_link_state(struct pci_dev *pdev);
index e44af7f4d37ff48c050daeaeab33326ec1a52067..464f8f92653f461e907e3a77062658e1a33a57ec 100644 (file)
@@ -1170,6 +1170,26 @@ static int pcie_aspm_get_policy(char *buffer, const struct kernel_param *kp)
 module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
        NULL, 0644);
 
+/**
+ * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device.
+ * @pdev: Target device.
+ */
+bool pcie_aspm_enabled(struct pci_dev *pdev)
+{
+       struct pci_dev *bridge = pci_upstream_bridge(pdev);
+       bool ret;
+
+       if (!bridge)
+               return false;
+
+       mutex_lock(&aspm_lock);
+       ret = bridge->link_state ? !!bridge->link_state->aspm_enabled : false;
+       mutex_unlock(&aspm_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pcie_aspm_enabled);
+
 #ifdef CONFIG_PCIEASPM_DEBUG
 static ssize_t link_state_show(struct device *dev,
                struct device_attribute *attr,
index 308c3e0c4a34012ebda42d5e86d342c8a42edd68..1b330129089fea765919e7ae477298473edb843c 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
@@ -379,67 +378,6 @@ static int pm_iter(struct device *dev, void *data)
        return 0;
 }
 
-static int get_downstream_delay(struct pci_bus *bus)
-{
-       struct pci_dev *pdev;
-       int min_delay = 100;
-       int max_delay = 0;
-
-       list_for_each_entry(pdev, &bus->devices, bus_list) {
-               if (!pdev->imm_ready)
-                       min_delay = 0;
-               else if (pdev->d3cold_delay < min_delay)
-                       min_delay = pdev->d3cold_delay;
-               if (pdev->d3cold_delay > max_delay)
-                       max_delay = pdev->d3cold_delay;
-       }
-
-       return max(min_delay, max_delay);
-}
-
-/*
- * wait_for_downstream_link - Wait for downstream link to establish
- * @pdev: PCIe port whose downstream link is waited
- *
- * Handle delays according to PCIe 4.0 section 6.6.1 before configuration
- * access to the downstream component is permitted.
- *
- * This blocks PCI core resume of the hierarchy below this port until the
- * link is trained. Should be called before resuming port services to
- * prevent pciehp from starting to tear-down the hierarchy too soon.
- */
-static void wait_for_downstream_link(struct pci_dev *pdev)
-{
-       int delay;
-
-       if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
-           pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
-               return;
-
-       if (pci_dev_is_disconnected(pdev))
-               return;
-
-       if (!pdev->subordinate || list_empty(&pdev->subordinate->devices) ||
-           !pdev->bridge_d3)
-               return;
-
-       delay = get_downstream_delay(pdev->subordinate);
-       if (!delay)
-               return;
-
-       dev_dbg(&pdev->dev, "waiting downstream link for %d ms\n", delay);
-
-       /*
-        * If downstream port does not support speeds greater than 5 GT/s
-        * need to wait 100ms. For higher speeds (gen3) we need to wait
-        * first for the data link layer to become active.
-        */
-       if (pcie_get_speed_cap(pdev) <= PCIE_SPEED_5_0GT)
-               msleep(delay);
-       else
-               pcie_wait_for_link_delay(pdev, true, delay);
-}
-
 /**
  * pcie_port_device_suspend - suspend port services associated with a PCIe port
  * @dev: PCI Express port to handle
@@ -453,8 +391,6 @@ int pcie_port_device_suspend(struct device *dev)
 int pcie_port_device_resume_noirq(struct device *dev)
 {
        size_t off = offsetof(struct pcie_port_service_driver, resume_noirq);
-
-       wait_for_downstream_link(to_pci_dev(dev));
        return device_for_each_child(dev, &off, pm_iter);
 }
 
@@ -485,8 +421,6 @@ int pcie_port_device_runtime_suspend(struct device *dev)
 int pcie_port_device_runtime_resume(struct device *dev)
 {
        size_t off = offsetof(struct pcie_port_service_driver, runtime_resume);
-
-       wait_for_downstream_link(to_pci_dev(dev));
        return device_for_each_child(dev, &off, pm_iter);
 }
 #endif /* PM */
index 208aacf393297835f89101585b48ae5074a9f290..44c4ae1abd00557e080bf9ca37458c31a7ba7504 100644 (file)
@@ -5256,7 +5256,7 @@ static void quirk_reset_lenovo_thinkpad_p50_nvgpu(struct pci_dev *pdev)
         */
        if (ioread32(map + 0x2240c) & 0x2) {
                pci_info(pdev, FW_BUG "GPU left initialized by EFI, resetting\n");
-               ret = pci_reset_function(pdev);
+               ret = pci_reset_bus(pdev);
                if (ret < 0)
                        pci_err(pdev, "Failed to reset GPU: %d\n", ret);
        }
index eb6168e6ac434289aeecbf333b1d92f5b9060a84..590e594092f25f080314d08316dd26b2b2831f8b 100644 (file)
@@ -255,8 +255,10 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
        switch (state->Vcc) {
        case 50:
                ++v;
+               /* fall through */
        case 33:
                ++v;
+               /* fall through */
        case 0:
                break;
        default:
@@ -267,9 +269,11 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
        switch (state->Vpp) {
        case 12:
                ++p;
+               /* fall through */
        case 33:
        case 50:
                ++p;
+               /* fall through */
        case 0:
                break;
        default:
index 2d06b8095a19cf92f9d5dcd2dc93375c5d27ea2a..df352b334ea77ab20f9ba7b400fca3e27321f129 100644 (file)
@@ -723,8 +723,8 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
                cpu_pm_pmu_setup(armpmu, cmd);
                break;
        case CPU_PM_EXIT:
-               cpu_pm_pmu_setup(armpmu, cmd);
        case CPU_PM_ENTER_FAILED:
+               cpu_pm_pmu_setup(armpmu, cmd);
                armpmu->start(armpmu);
                break;
        default:
index 384396cbb22d21a00bf6f71f6fe7881bbfabf475..22256576b69a22a1b2d421ac44818e945d11e9ab 100644 (file)
@@ -2412,7 +2412,7 @@ static const struct aspeed_pin_config aspeed_g4_configs[] = {
        { PIN_CONFIG_INPUT_DEBOUNCE, { C14, B14 }, SCUA8, 27 },
 };
 
-static int aspeed_g4_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static int aspeed_g4_sig_expr_set(struct aspeed_pinmux_data *ctx,
                                  const struct aspeed_sig_expr *expr,
                                  bool enable)
 {
index 053101f795a29938ec059a395fcee3b498cbf757..ff84d1afd229d34f50be3564277222221342582a 100644 (file)
@@ -2507,6 +2507,88 @@ static struct aspeed_pin_config aspeed_g5_configs[] = {
        { PIN_CONFIG_INPUT_DEBOUNCE, { A20, B19 }, SCUA8, 27 },
 };
 
+static struct regmap *aspeed_g5_acquire_regmap(struct aspeed_pinmux_data *ctx,
+                                              int ip)
+{
+       if (ip == ASPEED_IP_SCU) {
+               WARN(!ctx->maps[ip], "Missing SCU syscon!");
+               return ctx->maps[ip];
+       }
+
+       if (ip >= ASPEED_NR_PINMUX_IPS)
+               return ERR_PTR(-EINVAL);
+
+       if (likely(ctx->maps[ip]))
+               return ctx->maps[ip];
+
+       if (ip == ASPEED_IP_GFX) {
+               struct device_node *node;
+               struct regmap *map;
+
+               node = of_parse_phandle(ctx->dev->of_node,
+                                       "aspeed,external-nodes", 0);
+               if (node) {
+                       map = syscon_node_to_regmap(node);
+                       of_node_put(node);
+                       if (IS_ERR(map))
+                               return map;
+               } else
+                       return ERR_PTR(-ENODEV);
+
+               ctx->maps[ASPEED_IP_GFX] = map;
+               dev_dbg(ctx->dev, "Acquired GFX regmap");
+               return map;
+       }
+
+       if (ip == ASPEED_IP_LPC) {
+               struct device_node *node;
+               struct regmap *map;
+
+               node = of_parse_phandle(ctx->dev->of_node,
+                                       "aspeed,external-nodes", 1);
+               if (node) {
+                       map = syscon_node_to_regmap(node->parent);
+                       of_node_put(node);
+                       if (IS_ERR(map))
+                               return map;
+               } else
+                       return ERR_PTR(-ENODEV);
+
+               ctx->maps[ASPEED_IP_LPC] = map;
+               dev_dbg(ctx->dev, "Acquired LPC regmap");
+               return map;
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+
+static int aspeed_g5_sig_expr_eval(struct aspeed_pinmux_data *ctx,
+                                  const struct aspeed_sig_expr *expr,
+                                  bool enabled)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < expr->ndescs; i++) {
+               const struct aspeed_sig_desc *desc = &expr->descs[i];
+               struct regmap *map;
+
+               map = aspeed_g5_acquire_regmap(ctx, desc->ip);
+               if (IS_ERR(map)) {
+                       dev_err(ctx->dev,
+                               "Failed to acquire regmap for IP block %d\n",
+                               desc->ip);
+                       return PTR_ERR(map);
+               }
+
+               ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]);
+               if (ret <= 0)
+                       return ret;
+       }
+
+       return 1;
+}
+
 /**
  * Configure a pin's signal by applying an expression's descriptor state for
  * all descriptors in the expression.
@@ -2520,7 +2602,7 @@ static struct aspeed_pin_config aspeed_g5_configs[] = {
  * Return: 0 if the expression is configured as requested and a negative error
  * code otherwise
  */
-static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static int aspeed_g5_sig_expr_set(struct aspeed_pinmux_data *ctx,
                                  const struct aspeed_sig_expr *expr,
                                  bool enable)
 {
@@ -2531,9 +2613,15 @@ static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
                const struct aspeed_sig_desc *desc = &expr->descs[i];
                u32 pattern = enable ? desc->enable : desc->disable;
                u32 val = (pattern << __ffs(desc->mask));
+               struct regmap *map;
 
-               if (!ctx->maps[desc->ip])
-                       return -ENODEV;
+               map = aspeed_g5_acquire_regmap(ctx, desc->ip);
+               if (IS_ERR(map)) {
+                       dev_err(ctx->dev,
+                               "Failed to acquire regmap for IP block %d\n",
+                               desc->ip);
+                       return PTR_ERR(map);
+               }
 
                /*
                 * Strap registers are configured in hardware or by early-boot
@@ -2586,6 +2674,7 @@ static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
 }
 
 static const struct aspeed_pinmux_ops aspeed_g5_ops = {
+       .eval = aspeed_g5_sig_expr_eval,
        .set = aspeed_g5_sig_expr_set,
 };
 
@@ -2641,34 +2730,11 @@ static struct pinctrl_desc aspeed_g5_pinctrl_desc = {
 static int aspeed_g5_pinctrl_probe(struct platform_device *pdev)
 {
        int i;
-       struct regmap *map;
-       struct device_node *node;
 
        for (i = 0; i < ARRAY_SIZE(aspeed_g5_pins); i++)
                aspeed_g5_pins[i].number = i;
 
-       node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 0);
-       map = syscon_node_to_regmap(node);
-       of_node_put(node);
-       if (IS_ERR(map)) {
-               dev_warn(&pdev->dev, "No GFX phandle found, some mux configurations may fail\n");
-               map = NULL;
-       }
-       aspeed_g5_pinctrl_data.pinmux.maps[ASPEED_IP_GFX] = map;
-
-       node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 1);
-       if (node) {
-               map = syscon_node_to_regmap(node->parent);
-               if (IS_ERR(map)) {
-                       dev_warn(&pdev->dev, "LHC parent is not a syscon, some mux configurations may fail\n");
-                       map = NULL;
-               }
-       } else {
-               dev_warn(&pdev->dev, "No LHC phandle found, some mux configurations may fail\n");
-               map = NULL;
-       }
-       of_node_put(node);
-       aspeed_g5_pinctrl_data.pinmux.maps[ASPEED_IP_LPC] = map;
+       aspeed_g5_pinctrl_data.pinmux.dev = &pdev->dev;
 
        return aspeed_pinctrl_probe(pdev, &aspeed_g5_pinctrl_desc,
                        &aspeed_g5_pinctrl_data);
index 535db3de490b73adbc122402ab6dc3da77be42d4..54933665b5f8b4fe7e321c377dddfeddbdcf85ba 100644 (file)
@@ -71,7 +71,7 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-static int aspeed_sig_expr_enable(const struct aspeed_pinmux_data *ctx,
+static int aspeed_sig_expr_enable(struct aspeed_pinmux_data *ctx,
                                  const struct aspeed_sig_expr *expr)
 {
        int ret;
@@ -86,7 +86,7 @@ static int aspeed_sig_expr_enable(const struct aspeed_pinmux_data *ctx,
        return 0;
 }
 
-static int aspeed_sig_expr_disable(const struct aspeed_pinmux_data *ctx,
+static int aspeed_sig_expr_disable(struct aspeed_pinmux_data *ctx,
                                   const struct aspeed_sig_expr *expr)
 {
        int ret;
@@ -109,7 +109,7 @@ static int aspeed_sig_expr_disable(const struct aspeed_pinmux_data *ctx,
  *
  * Return: 0 if all expressions are disabled, otherwise a negative error code
  */
-static int aspeed_disable_sig(const struct aspeed_pinmux_data *ctx,
+static int aspeed_disable_sig(struct aspeed_pinmux_data *ctx,
                              const struct aspeed_sig_expr **exprs)
 {
        int ret = 0;
@@ -217,8 +217,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
 {
        int i;
        int ret;
-       const struct aspeed_pinctrl_data *pdata =
-               pinctrl_dev_get_drvdata(pctldev);
+       struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
        const struct aspeed_pin_group *pgroup = &pdata->pinmux.groups[group];
        const struct aspeed_pin_function *pfunc =
                &pdata->pinmux.functions[function];
@@ -306,8 +305,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
                               unsigned int offset)
 {
        int ret;
-       const struct aspeed_pinctrl_data *pdata =
-               pinctrl_dev_get_drvdata(pctldev);
+       struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
        const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
        const struct aspeed_sig_expr ***prios, **funcs, *expr;
 
index 5b0fe178ccf21042cbe7e6c76acf7bccde191d8c..57305ca838a7c800fb93cf5377bf1ecb5a9bc562 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "pinmux-aspeed.h"
 
-const char *const aspeed_pinmux_ips[] = {
+static const char *const aspeed_pinmux_ips[] = {
        [ASPEED_IP_SCU] = "SCU",
        [ASPEED_IP_GFX] = "GFX",
        [ASPEED_IP_LPC] = "LPC",
@@ -78,11 +78,14 @@ int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
  * neither the enabled nor disabled state. Thus we must explicitly test for
  * either condition as required.
  */
-int aspeed_sig_expr_eval(const struct aspeed_pinmux_data *ctx,
+int aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
                         const struct aspeed_sig_expr *expr, bool enabled)
 {
-       int i;
        int ret;
+       int i;
+
+       if (ctx->ops->eval)
+               return ctx->ops->eval(ctx, expr, enabled);
 
        for (i = 0; i < expr->ndescs; i++) {
                const struct aspeed_sig_desc *desc = &expr->descs[i];
index 329d54d4866775b5f8e7a58ed5dd84ef34ee3f20..db3457c86f48c5f0314ce917b6c6136560975e86 100644 (file)
@@ -702,11 +702,14 @@ struct aspeed_pin_function {
 struct aspeed_pinmux_data;
 
 struct aspeed_pinmux_ops {
-       int (*set)(const struct aspeed_pinmux_data *ctx,
+       int (*eval)(struct aspeed_pinmux_data *ctx,
+                   const struct aspeed_sig_expr *expr, bool enabled);
+       int (*set)(struct aspeed_pinmux_data *ctx,
                   const struct aspeed_sig_expr *expr, bool enabled);
 };
 
 struct aspeed_pinmux_data {
+       struct device *dev;
        struct regmap *maps[ASPEED_NR_PINMUX_IPS];
 
        const struct aspeed_pinmux_ops *ops;
@@ -721,11 +724,10 @@ struct aspeed_pinmux_data {
 int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc, bool enabled,
                         struct regmap *map);
 
-int aspeed_sig_expr_eval(const struct aspeed_pinmux_data *ctx,
-                        const struct aspeed_sig_expr *expr,
-                        bool enabled);
+int aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
+                        const struct aspeed_sig_expr *expr, bool enabled);
 
-static inline int aspeed_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static inline int aspeed_sig_expr_set(struct aspeed_pinmux_data *ctx,
                                      const struct aspeed_sig_expr *expr,
                                      bool enabled)
 {
index e504d255d5ce270967f0a082537f16bf2923aeff..430731cdf8277ba247656ecdb90ce187efe2ddf8 100644 (file)
@@ -707,7 +707,7 @@ static int cros_ec_ishtp_reset(struct ishtp_cl_device *cl_device)
  */
 static int __maybe_unused cros_ec_ishtp_suspend(struct device *device)
 {
-       struct ishtp_cl_device *cl_device = dev_get_drvdata(device);
+       struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
        struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
        struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 
@@ -722,7 +722,7 @@ static int __maybe_unused cros_ec_ishtp_suspend(struct device *device)
  */
 static int __maybe_unused cros_ec_ishtp_resume(struct device *device)
 {
-       struct ishtp_cl_device *cl_device = dev_get_drvdata(device);
+       struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
        struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
        struct ishtp_cl_data *client_data = ishtp_get_client_data(cros_ish_cl);
 
index 48d6f0d875839f76fd0536bbe91079dc876b5bee..83ed1fbf73cfddaf6aaee0a28b9e843c5ac6f1f1 100644 (file)
@@ -736,6 +736,12 @@ static const struct of_device_id olpc_xo175_ec_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, olpc_xo175_ec_of_match);
 
+static const struct spi_device_id olpc_xo175_ec_id_table[] = {
+       { "xo1.75-ec", 0 },
+       {}
+};
+MODULE_DEVICE_TABLE(spi, olpc_xo175_ec_id_table);
+
 static struct spi_driver olpc_xo175_ec_spi_driver = {
        .driver = {
                .name   = "olpc-xo175-ec",
index 235c0b89f824bc8969f2d7d055dd5ac8bbc841aa..c510d0d724759c77c81bda4319f138c60e80c875 100644 (file)
@@ -812,6 +812,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
        INTEL_CPU_FAM6(KABYLAKE_DESKTOP, spt_reg_map),
        INTEL_CPU_FAM6(CANNONLAKE_MOBILE, cnp_reg_map),
        INTEL_CPU_FAM6(ICELAKE_MOBILE, icl_reg_map),
+       INTEL_CPU_FAM6(ICELAKE_NNPI, icl_reg_map),
        {}
 };
 
index b0d3110ae378d798660a30f15661a843eb6cefa4..e4c68efac0c253e3419f43b3abc17437c3bb8bd6 100644 (file)
@@ -93,7 +93,7 @@ static struct gpiod_lookup_table gpios_led_table = {
 
 static struct gpio_keys_button apu2_keys_buttons[] = {
        {
-               .code                   = KEY_SETUP,
+               .code                   = KEY_RESTART,
                .active_low             = 1,
                .desc                   = "front button",
                .type                   = EV_KEY,
@@ -255,6 +255,4 @@ MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LED/keys driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(dmi, apu_gpio_dmi_table);
 MODULE_ALIAS("platform:pcengines-apuv2");
-MODULE_SOFTDEP("pre: platform:" AMD_FCH_GPIO_DRIVER_NAME);
-MODULE_SOFTDEP("pre: platform:leds-gpio");
-MODULE_SOFTDEP("pre: platform:gpio_keys_polled");
+MODULE_SOFTDEP("pre: platform:" AMD_FCH_GPIO_DRIVER_NAME " platform:leds-gpio platform:gpio_keys_polled");
index 30de448de802232485703e4b9dfbdb94f831385d..86d88aec94a11a02017afd0f4a396d3b2bffa7dd 100644 (file)
@@ -742,6 +742,7 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
                                                USB_CH_IP_CUR_LVL_1P5;
                        break;
                }
+               /* Else, fall through */
        case USB_STAT_HM_IDGND:
                dev_err(di->dev, "USB Type - Charging not allowed\n");
                di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05;
index 9fd6dd342169c3f75dd22f09203c758aacbf5ac8..6df481896b5fc65b7bb0fa016f706f8cdde8eee7 100644 (file)
@@ -1454,7 +1454,7 @@ static void __exit rapl_exit(void)
        unregister_pm_notifier(&rapl_pm_notifier);
 }
 
-module_init(rapl_init);
+fs_initcall(rapl_init);
 module_exit(rapl_exit);
 
 MODULE_DESCRIPTION("Intel Runtime Average Power Limit (RAPL) common code");
index 540e8aafc990b3d797f419882779b756f9548203..f808c5fa9838ce3b7cd8272b27c1aa38841c9f90 100644 (file)
@@ -671,7 +671,7 @@ static int __init powercap_init(void)
        return class_register(&powercap_class);
 }
 
-device_initcall(powercap_init);
+fs_initcall(powercap_init);
 
 MODULE_DESCRIPTION("PowerCap sysfs Driver");
 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
index c3ab07ab31a96df3072b94240fc241558a0da925..8edfac17364e9141ba4fd7fed8d1a3e0f4df6d1a 100644 (file)
@@ -882,8 +882,11 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
                return of_pwm_get(dev, dev->of_node, con_id);
 
        /* then lookup via ACPI */
-       if (dev && is_acpi_node(dev->fwnode))
-               return acpi_pwm_get(dev->fwnode);
+       if (dev && is_acpi_node(dev->fwnode)) {
+               pwm = acpi_pwm_get(dev->fwnode);
+               if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT)
+                       return pwm;
+       }
 
        /*
         * We look up the provider in the static table typically provided by
index 584284938ac9b23584e25bfa67a8456311093371..d2f804dbc785da98d871984c1e3c7e392426b46b 100644 (file)
@@ -169,16 +169,16 @@ static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode)
                reg = ACT8945A_DCDC3_CTRL;
                break;
        case ACT8945A_ID_LDO1:
-               reg = ACT8945A_LDO1_SUS;
+               reg = ACT8945A_LDO1_CTRL;
                break;
        case ACT8945A_ID_LDO2:
-               reg = ACT8945A_LDO2_SUS;
+               reg = ACT8945A_LDO2_CTRL;
                break;
        case ACT8945A_ID_LDO3:
-               reg = ACT8945A_LDO3_SUS;
+               reg = ACT8945A_LDO3_CTRL;
                break;
        case ACT8945A_ID_LDO4:
-               reg = ACT8945A_LDO4_SUS;
+               reg = ACT8945A_LDO4_CTRL;
                break;
        default:
                return -EINVAL;
index 152053361862d4c5c8595ed4931d0bafd002bdd1..989506bd90b193bc696abf90096e0c4ae1a37efa 100644 (file)
 #define AXP803_DCDC5_1140mV_STEPS      35
 #define AXP803_DCDC5_1140mV_END                \
        (AXP803_DCDC5_1140mV_START + AXP803_DCDC5_1140mV_STEPS)
-#define AXP803_DCDC5_NUM_VOLTAGES      68
+#define AXP803_DCDC5_NUM_VOLTAGES      69
 
 #define AXP803_DCDC6_600mV_START       0x00
 #define AXP803_DCDC6_600mV_STEPS       50
 #define AXP803_DCDC6_600mV_END         \
        (AXP803_DCDC6_600mV_START + AXP803_DCDC6_600mV_STEPS)
 #define AXP803_DCDC6_1120mV_START      0x33
-#define AXP803_DCDC6_1120mV_STEPS      14
+#define AXP803_DCDC6_1120mV_STEPS      20
 #define AXP803_DCDC6_1120mV_END                \
        (AXP803_DCDC6_1120mV_START + AXP803_DCDC6_1120mV_STEPS)
 #define AXP803_DCDC6_NUM_VOLTAGES      72
 #define AXP806_DCDCA_600mV_END         \
        (AXP806_DCDCA_600mV_START + AXP806_DCDCA_600mV_STEPS)
 #define AXP806_DCDCA_1120mV_START      0x33
-#define AXP806_DCDCA_1120mV_STEPS      14
+#define AXP806_DCDCA_1120mV_STEPS      20
 #define AXP806_DCDCA_1120mV_END                \
        (AXP806_DCDCA_1120mV_START + AXP806_DCDCA_1120mV_STEPS)
 #define AXP806_DCDCA_NUM_VOLTAGES      72
@@ -774,8 +774,8 @@ static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
                               AXP806_DCDCD_600mV_END,
                               20000),
        REGULATOR_LINEAR_RANGE(1600000,
-                              AXP806_DCDCD_600mV_START,
-                              AXP806_DCDCD_600mV_END,
+                              AXP806_DCDCD_1600mV_START,
+                              AXP806_DCDCD_1600mV_END,
                               100000),
 };
 
index 5d067f7c2116601a5ff558e194963a82a3869d9d..0c440c5e28327c80b596f0996c3ef6b122021a6d 100644 (file)
@@ -163,7 +163,7 @@ static int lp87565_regulator_probe(struct platform_device *pdev)
        struct lp87565 *lp87565 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
        struct regulator_dev *rdev;
-       int i, min_idx = LP87565_BUCK_0, max_idx = LP87565_BUCK_3;
+       int i, min_idx, max_idx;
 
        platform_set_drvdata(pdev, lp87565);
 
@@ -182,9 +182,9 @@ static int lp87565_regulator_probe(struct platform_device *pdev)
                max_idx = LP87565_BUCK_3210;
                break;
        default:
-               dev_err(lp87565->dev, "Invalid lp config %d\n",
-                       lp87565->dev_type);
-               return -EINVAL;
+               min_idx = LP87565_BUCK_0;
+               max_idx = LP87565_BUCK_3;
+               break;
        }
 
        for (i = min_idx; i <= max_idx; i++) {
index 397918ebba550a5c120481052ba586db7cb9f055..9112faa6a9a0e12830e8f931e83fcd56070e1ac5 100644 (file)
@@ -416,8 +416,10 @@ device_node *regulator_of_get_init_node(struct device *dev,
                if (!name)
                        name = child->name;
 
-               if (!strcmp(desc->of_match, name))
+               if (!strcmp(desc->of_match, name)) {
+                       of_node_put(search);
                        return of_node_get(child);
+               }
        }
 
        of_node_put(search);
index 04b732991d6955f3cf917644725be7fff756acd3..4d859fef55e681e81701fb023f0842b23f2413ff 100644 (file)
@@ -205,7 +205,7 @@ static int slg51000_of_parse_cb(struct device_node *np,
        ena_gpiod = devm_gpiod_get_from_of_node(chip->dev, np,
                                                "enable-gpios", 0,
                                                gflags, "gpio-en-ldo");
-       if (ena_gpiod) {
+       if (!IS_ERR(ena_gpiod)) {
                config->ena_gpiod = ena_gpiod;
                devm_gpiod_unhinge(chip->dev, config->ena_gpiod);
        }
@@ -459,7 +459,7 @@ static int slg51000_i2c_probe(struct i2c_client *client,
                                               GPIOD_OUT_HIGH
                                               | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
                                               "slg51000-cs");
-       if (cs_gpiod) {
+       if (!IS_ERR(cs_gpiod)) {
                dev_info(dev, "Found chip selector property\n");
                chip->cs_gpiod = cs_gpiod;
        }
index 6fa15b2d6fb33ef7353a8e5c3b37fe0f61ab825b..866b4dd01da9ea0911da113969f3c2a453aff6d0 100644 (file)
@@ -359,6 +359,17 @@ static const u16 VINTANA2_VSEL_table[] = {
        2500, 2750,
 };
 
+/* 600mV to 1450mV in 12.5 mV steps */
+static const struct regulator_linear_range VDD1_ranges[] = {
+       REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500)
+};
+
+/* 600mV to 1450mV in 12.5 mV steps, everything above = 1500mV */
+static const struct regulator_linear_range VDD2_ranges[] = {
+       REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500),
+       REGULATOR_LINEAR_RANGE(1500000, 69, 69, 12500)
+};
+
 static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
@@ -427,6 +438,8 @@ static int twl4030smps_get_voltage(struct regulator_dev *rdev)
 }
 
 static const struct regulator_ops twl4030smps_ops = {
+       .list_voltage   = regulator_list_voltage_linear_range,
+
        .set_voltage    = twl4030smps_set_voltage,
        .get_voltage    = twl4030smps_get_voltage,
 };
@@ -466,7 +479,8 @@ static const struct twlreg_info TWL4030_INFO_##label = { \
                }, \
        }
 
-#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \
+#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf, \
+               n_volt) \
 static const struct twlreg_info TWL4030_INFO_##label = { \
        .base = offset, \
        .id = num, \
@@ -479,6 +493,9 @@ static const struct twlreg_info TWL4030_INFO_##label = { \
                .owner = THIS_MODULE, \
                .enable_time = turnon_delay, \
                .of_map_mode = twl4030reg_map_mode, \
+               .n_voltages = n_volt, \
+               .n_linear_ranges = ARRAY_SIZE(label ## _ranges), \
+               .linear_ranges = label ## _ranges, \
                }, \
        }
 
@@ -518,8 +535,8 @@ TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00);
 TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08);
 TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08);
 TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08);
-TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08);
-TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08);
+TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08, 68);
+TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08, 69);
 /* VUSBCP is managed *only* by the USB subchip */
 TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08);
 TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);
index b9ce93e9df89295eb72132fcfc81d0257aaa1723..99f86612f7751ad6d47b7abee8661e8deec2b0b2 100644 (file)
@@ -383,6 +383,20 @@ suborder_not_supported(struct dasd_ccw_req *cqr)
        char msg_format;
        char msg_no;
 
+       /*
+        * intrc values ENODEV, ENOLINK and EPERM
+        * will be optained from sleep_on to indicate that no
+        * IO operation can be started
+        */
+       if (cqr->intrc == -ENODEV)
+               return 1;
+
+       if (cqr->intrc == -ENOLINK)
+               return 1;
+
+       if (cqr->intrc == -EPERM)
+               return 1;
+
        sense = dasd_get_sense(&cqr->irb);
        if (!sense)
                return 0;
@@ -447,12 +461,8 @@ static int read_unit_address_configuration(struct dasd_device *device,
        lcu->flags &= ~NEED_UAC_UPDATE;
        spin_unlock_irqrestore(&lcu->lock, flags);
 
-       do {
-               rc = dasd_sleep_on(cqr);
-               if (rc && suborder_not_supported(cqr))
-                       return -EOPNOTSUPP;
-       } while (rc && (cqr->retries > 0));
-       if (rc) {
+       rc = dasd_sleep_on(cqr);
+       if (rc && !suborder_not_supported(cqr)) {
                spin_lock_irqsave(&lcu->lock, flags);
                lcu->flags |= NEED_UAC_UPDATE;
                spin_unlock_irqrestore(&lcu->lock, flags);
index 8c9d412b6d33bd14b873446260b26caacd31642c..e7cf0a1d4f716d83f2de606e65f5a4ffcde3f01a 100644 (file)
@@ -398,6 +398,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
                }
                if (dstat == 0x08)
                        break;
+               /* else, fall through */
        case 0x04:
                /* Device end interrupt. */
                if ((raw = req->info) == NULL)
index 8d3370da2dfc294e1286caa337bd9d305fb624c5..3e0b2f63a9d222cf2bd0acb0adb2c104e7ab2a7f 100644 (file)
@@ -677,6 +677,7 @@ tape_generic_remove(struct ccw_device *cdev)
        switch (device->tape_state) {
                case TS_INIT:
                        tape_state_set(device, TS_NOT_OPER);
+                       /* fallthrough */
                case TS_NOT_OPER:
                        /*
                         * Nothing to do.
@@ -949,6 +950,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request)
                                break;
                        if (device->tape_state == TS_UNUSED)
                                break;
+                       /* fallthrough */
                default:
                        if (device->tape_state == TS_BLKUSE)
                                break;
@@ -1116,6 +1118,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                        case -ETIMEDOUT:
                                DBF_LH(1, "(%08x): Request timed out\n",
                                       device->cdev_id);
+                               /* fallthrough */
                        case -EIO:
                                __tape_end_request(device, request, -EIO);
                                break;
index 730c4e68094ba3b9dca68059eed9f0c03ffaea72..4142c85e77d8baa37d7def40b88c35c48e82bd70 100644 (file)
@@ -319,9 +319,7 @@ static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
        int retries = 0, cc;
        unsigned long laob = 0;
 
-       WARN_ON_ONCE(aob && ((queue_type(q) != QDIO_IQDIO_QFMT) ||
-                            !q->u.out.use_cq));
-       if (q->u.out.use_cq && aob != 0) {
+       if (aob) {
                fc = QDIO_SIGA_WRITEQ;
                laob = aob;
        }
@@ -621,9 +619,6 @@ static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q,
 {
        unsigned long phys_aob = 0;
 
-       if (!q->use_cq)
-               return 0;
-
        if (!q->aobs[bufnr]) {
                struct qaob *aob = qdio_allocate_aob();
                q->aobs[bufnr] = aob;
@@ -1308,6 +1303,8 @@ static void qdio_detect_hsicq(struct qdio_irq *irq_ptr)
 
        for_each_output_queue(irq_ptr, q, i) {
                if (use_cq) {
+                       if (multicast_outbound(q))
+                               continue;
                        if (qdio_enable_async_operation(&q->u.out) < 0) {
                                use_cq = 0;
                                continue;
@@ -1553,18 +1550,19 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
                /* One SIGA-W per buffer required for unicast HSI */
                WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
 
-               phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
+               if (q->u.out.use_cq)
+                       phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
 
                rc = qdio_kick_outbound_q(q, phys_aob);
        } else if (need_siga_sync(q)) {
                rc = qdio_siga_sync_q(q);
+       } else if (count < QDIO_MAX_BUFFERS_PER_Q &&
+                  get_buf_state(q, prev_buf(bufnr), &state, 0) > 0 &&
+                  state == SLSB_CU_OUTPUT_PRIMED) {
+               /* The previous buffer is not processed yet, tack on. */
+               qperf_inc(q, fast_requeue);
        } else {
-               /* try to fast requeue buffers */
-               get_buf_state(q, prev_buf(bufnr), &state, 0);
-               if (state != SLSB_CU_OUTPUT_PRIMED)
-                       rc = qdio_kick_outbound_q(q, 0);
-               else
-                       qperf_inc(q, fast_requeue);
+               rc = qdio_kick_outbound_q(q, 0);
        }
 
        /* in case of SIGA errors we must process the error immediately */
index 8c1d2357ef5b8625a88ad5380e6389ec67824b78..7a838e3d7c0fae3a209fdf763a640bd140091c1f 100644 (file)
@@ -70,7 +70,7 @@ static void vfio_ccw_async_region_release(struct vfio_ccw_private *private,
 
 }
 
-const struct vfio_ccw_regops vfio_ccw_async_region_ops = {
+static const struct vfio_ccw_regops vfio_ccw_async_region_ops = {
        .read = vfio_ccw_async_region_read,
        .write = vfio_ccw_async_region_write,
        .release = vfio_ccw_async_region_release,
index 1d4c893ead233bb4f2edef2b0194f33025579d8f..3645d1720c4b572666ca80940308a7ef53e6c866 100644 (file)
@@ -72,8 +72,10 @@ static int pfn_array_alloc(struct pfn_array *pa, u64 iova, unsigned int len)
                                  sizeof(*pa->pa_iova_pfn) +
                                  sizeof(*pa->pa_pfn),
                                  GFP_KERNEL);
-       if (unlikely(!pa->pa_iova_pfn))
+       if (unlikely(!pa->pa_iova_pfn)) {
+               pa->pa_nr = 0;
                return -ENOMEM;
+       }
        pa->pa_pfn = pa->pa_iova_pfn + pa->pa_nr;
 
        pa->pa_iova_pfn[0] = pa->pa_iova >> PAGE_SHIFT;
@@ -421,7 +423,7 @@ static int ccwchain_loop_tic(struct ccwchain *chain,
 static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
 {
        struct ccwchain *chain;
-       int len;
+       int len, ret;
 
        /* Copy 2K (the most we support today) of possible CCWs */
        len = copy_from_iova(cp->mdev, cp->guest_cp, cda,
@@ -448,7 +450,12 @@ static int ccwchain_handle_ccw(u32 cda, struct channel_program *cp)
        memcpy(chain->ch_ccw, cp->guest_cp, len * sizeof(struct ccw1));
 
        /* Loop for tics on this new chain. */
-       return ccwchain_loop_tic(chain, cp);
+       ret = ccwchain_loop_tic(chain, cp);
+
+       if (ret)
+               ccwchain_free(chain);
+
+       return ret;
 }
 
 /* Loop for TICs. */
@@ -642,17 +649,16 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
 
        /* Build a ccwchain for the first CCW segment */
        ret = ccwchain_handle_ccw(orb->cmd.cpa, cp);
-       if (ret)
-               cp_free(cp);
-
-       /* It is safe to force: if not set but idals used
-        * ccwchain_calc_length returns an error.
-        */
-       cp->orb.cmd.c64 = 1;
 
-       if (!ret)
+       if (!ret) {
                cp->initialized = true;
 
+               /* It is safe to force: if it was not set but idals used
+                * ccwchain_calc_length would have returned an error.
+                */
+               cp->orb.cmd.c64 = 1;
+       }
+
        return ret;
 }
 
index 2b90a5ecaeb9ff7d1222a8c6065dd72ce0fb7493..9208c0e56c3304b8f6615e02fae39b4778b23f78 100644 (file)
@@ -88,7 +88,7 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
                     (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
        if (scsw_is_solicited(&irb->scsw)) {
                cp_update_scsw(&private->cp, &irb->scsw);
-               if (is_final)
+               if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING)
                        cp_free(&private->cp);
        }
        mutex_lock(&private->io_mutex);
index 5ea83dc4f1d740e9db1288ed9d8f70423312d5ba..dad2be333d826fd5d49601e6b9c11f11b118b755 100644 (file)
@@ -152,6 +152,7 @@ static struct ap_queue_status ap_sm_recv(struct ap_queue *aq)
                        ap_msg->receive(aq, ap_msg, aq->reply);
                        break;
                }
+               /* fall through */
        case AP_RESPONSE_NO_PENDING_REPLY:
                if (!status.queue_empty || aq->queue_count <= 0)
                        break;
index 12fe9deb265ea7fb97485805eab192ee232a3b56..a36251d138fb7afe25f3a24cc8bee36d33619b2c 100644 (file)
@@ -801,10 +801,7 @@ static int convert_response_ica(struct zcrypt_queue *zq,
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_ica(zq, reply,
                                                  outputdata, outputdatalength);
-               /*
-                * Fall through, no break, incorrect cprb version is an unknown
-                * response
-                */
+               /* fall through - wrong cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zq->online = 0;
                pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
@@ -837,10 +834,7 @@ static int convert_response_xcrb(struct zcrypt_queue *zq,
                }
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_xcrb(zq, reply, xcRB);
-               /*
-                * Fall through, no break, incorrect cprb version is an unknown
-                * response
-                */
+               /* fall through - wrong cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
                xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
                zq->online = 0;
@@ -870,7 +864,7 @@ static int convert_response_ep11_xcrb(struct zcrypt_queue *zq,
                        return convert_error(zq, reply);
                if (msg->cprbx.cprb_ver_id == 0x04)
                        return convert_type86_ep11_xcrb(zq, reply, xcRB);
-       /* Fall through, no break, incorrect cprb version is an unknown resp.*/
+               /* fall through - wrong cprb version is an unknown resp */
        default: /* Unknown response type, this should NEVER EVER happen */
                zq->online = 0;
                pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
@@ -900,10 +894,7 @@ static int convert_response_rng(struct zcrypt_queue *zq,
                        return -EINVAL;
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_rng(zq, reply, data);
-               /*
-                * Fall through, no break, incorrect cprb version is an unknown
-                * response
-                */
+               /* fall through - wrong cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zq->online = 0;
                pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
index 1b4ee570b712f272363255472caa8fd13662d2d8..4a8a5373cb35142fca9662f8a91358bfd85935e0 100644 (file)
@@ -1704,6 +1704,7 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
                        grp->changed_side = 2;
                        break;
                }
+               /* Else, fall through */
        case MPCG_STATE_XID0IOWAIX:
        case MPCG_STATE_XID7INITW:
        case MPCG_STATE_XID7INITX:
index e02f295d38a9bf060ab2054b67a516713b90eb79..1534420a02433759ae836d904b18973367517be5 100644 (file)
@@ -357,6 +357,7 @@ int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
                /*fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);*/
                if (callback)
                        grp->send_qllc_disc = 1;
+               /* Else, fall through */
        case MPCG_STATE_XID0IOWAIT:
                fsm_deltimer(&grp->timer);
                grp->outstanding_xid2 = 0;
@@ -1469,6 +1470,7 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
                if ((fsm_getstate(rch->fsm) == CH_XID0_PENDING) &&
                   (fsm_getstate(wch->fsm) == CH_XID0_PENDING))
                        break;
+               /* Else, fall through */
        default:
                fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
        }
@@ -2089,6 +2091,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
                        grp->estconnfunc = NULL;
                        break;
                }
+               /* Else, fall through */
        case MPCG_STATE_FLOWC:
        case MPCG_STATE_READY:
                grp->send_qllc_disc = 2;
index c7ee07ce3615d93a9d02b5a507ca0ef008a9698f..28db887d38edc809669b32fb146fcd8d64185f92 100644 (file)
@@ -629,6 +629,7 @@ struct qeth_seqno {
 struct qeth_reply {
        struct list_head list;
        struct completion received;
+       spinlock_t lock;
        int (*callback)(struct qeth_card *, struct qeth_reply *,
                unsigned long);
        u32 seqno;
index 4d0caeebc80210d3a130a2ec19574e0e1824b1bb..6502b148541e3337e9044ed52d66f2d35fc9cce4 100644 (file)
@@ -544,6 +544,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
        if (reply) {
                refcount_set(&reply->refcnt, 1);
                init_completion(&reply->received);
+               spin_lock_init(&reply->lock);
        }
        return reply;
 }
@@ -799,6 +800,13 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
 
        if (!reply->callback) {
                rc = 0;
+               goto no_callback;
+       }
+
+       spin_lock_irqsave(&reply->lock, flags);
+       if (reply->rc) {
+               /* Bail out when the requestor has already left: */
+               rc = reply->rc;
        } else {
                if (cmd) {
                        reply->offset = (u16)((char *)cmd - (char *)iob->data);
@@ -807,7 +815,9 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
                        rc = reply->callback(card, reply, (unsigned long)iob);
                }
        }
+       spin_unlock_irqrestore(&reply->lock, flags);
 
+no_callback:
        if (rc <= 0)
                qeth_notify_reply(reply, rc);
        qeth_put_reply(reply);
@@ -1749,6 +1759,16 @@ static int qeth_send_control_data(struct qeth_card *card,
                rc = (timeout == -ERESTARTSYS) ? -EINTR : -ETIME;
 
        qeth_dequeue_reply(card, reply);
+
+       if (reply_cb) {
+               /* Wait until the callback for a late reply has completed: */
+               spin_lock_irq(&reply->lock);
+               if (rc)
+                       /* Zap any callback that's still pending: */
+                       reply->rc = rc;
+               spin_unlock_irq(&reply->lock);
+       }
+
        if (!rc)
                rc = reply->rc;
        qeth_put_reply(reply);
@@ -4354,6 +4374,10 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
            get_user(req_len, &ureq->hdr.req_len))
                return -EFAULT;
 
+       /* Sanitize user input, to avoid overflows in iob size calculation: */
+       if (req_len > QETH_BUFSIZE)
+               return -EINVAL;
+
        iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL, req_len);
        if (!iob)
                return -ENOMEM;
index fd64bc3f406243cbcc311147a1b84a2ab91c4a72..cbead3d1b2fd2c4b47d6c2586fc4e123a5e41b13 100644 (file)
@@ -333,7 +333,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
                                card->osn_info.data_cb(skb);
                                break;
                        }
-                       /* else unknown */
+                       /* Else, fall through */
                default:
                        dev_kfree_skb_any(skb);
                        QETH_CARD_TEXT(card, 3, "inbunkno");
index 1a55e5942d36807d98f0f62b7791f9d884dc2db1..957889a42d2eaedf6a343aeb2e11e111a47ff72a 100644 (file)
@@ -145,6 +145,8 @@ struct airq_info {
        struct airq_iv *aiv;
 };
 static struct airq_info *airq_areas[MAX_AIRQ_AREAS];
+static DEFINE_MUTEX(airq_areas_lock);
+
 static u8 *summary_indicators;
 
 static inline u8 *get_summary_indicator(struct airq_info *info)
@@ -265,9 +267,11 @@ static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
        unsigned long bit, flags;
 
        for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
+               mutex_lock(&airq_areas_lock);
                if (!airq_areas[i])
                        airq_areas[i] = new_airq_info(i);
                info = airq_areas[i];
+               mutex_unlock(&airq_areas_lock);
                if (!info)
                        return 0;
                write_lock_irqsave(&info->lock, flags);
index 75f66f8ad3ead620f519b8daf134259f3aa9f172..1b92f3c19ff32f84403f05cead17ae6a0423608f 100644 (file)
@@ -1523,10 +1523,10 @@ config SCSI_VIRTIO
 
 source "drivers/scsi/csiostor/Kconfig"
 
-endif # SCSI_LOWLEVEL
-
 source "drivers/scsi/pcmcia/Kconfig"
 
+endif # SCSI_LOWLEVEL
+
 source "drivers/scsi/device_handler/Kconfig"
 
 endmenu
index aea4fd73c8627b1f6ddde32a07f73c0b3693b574..6c68c23036383406d65f328ba4bfeac88aa2521b 100644 (file)
@@ -603,6 +603,7 @@ static void fas216_handlesync(FAS216_Info *info, char *msg)
                msgqueue_flush(&info->scsi.msgs);
                msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
                info->scsi.phase = PHASE_MSGOUT_EXPECT;
+               /* fall through */
 
        case async:
                dev->period = info->ifcfg.asyncperiod / 4;
@@ -915,6 +916,7 @@ static void fas216_disconnect_intr(FAS216_Info *info)
                        fas216_done(info, DID_ABORT);
                        break;
                }
+               /* else, fall through */
 
        default:                                /* huh?                                 */
                printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",
@@ -1411,6 +1413,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
        case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out     -> Status       */
        case STATE(STAT_STATUS, PHASE_DATAIN):  /* Data In      -> Status       */
                fas216_stoptransfer(info);
+               /* fall through */
+
        case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status       */
        case STATE(STAT_STATUS, PHASE_MSGOUT):  /* Message Out  -> Status       */
        case STATE(STAT_STATUS, PHASE_COMMAND): /* Command      -> Status       */
@@ -1422,6 +1426,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
        case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out     -> Message In   */
        case STATE(STAT_MESGIN, PHASE_DATAIN):  /* Data In      -> Message In   */
                fas216_stoptransfer(info);
+               /* fall through */
+
        case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command      -> Message In   */
        case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In   */
        case STATE(STAT_MESGIN, PHASE_MSGOUT):  /* Message Out  -> Message In   */
@@ -1575,6 +1581,7 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned
                        fas216_message(info);
                        break;
                }
+               /* else, fall through */
 
        default:
                fas216_log(info, 0, "internal phase %s for function done?"
@@ -1957,6 +1964,7 @@ static void fas216_kick(FAS216_Info *info)
        switch (where_from) {
        case TYPE_QUEUE:
                fas216_allocate_tag(info, SCpnt);
+               /* fall through */
        case TYPE_OTHER:
                fas216_start_command(info, SCpnt);
                break;
index f0066f8a17864ab94a5fe86ff15093f77be784f6..4971104b1817b5acc42fcd03e040ced92f63c179 100644 (file)
@@ -40,6 +40,7 @@
 #define ALUA_FAILOVER_TIMEOUT          60
 #define ALUA_FAILOVER_RETRIES          5
 #define ALUA_RTPG_DELAY_MSECS          5
+#define ALUA_RTPG_RETRY_DELAY          2
 
 /* device handler flags */
 #define ALUA_OPTIMIZE_STPG             0x01
@@ -682,7 +683,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
        case SCSI_ACCESS_STATE_TRANSITIONING:
                if (time_before(jiffies, pg->expiry)) {
                        /* State transition, retry */
-                       pg->interval = 2;
+                       pg->interval = ALUA_RTPG_RETRY_DELAY;
                        err = SCSI_DH_RETRY;
                } else {
                        struct alua_dh_data *h;
@@ -807,6 +808,8 @@ static void alua_rtpg_work(struct work_struct *work)
                                spin_lock_irqsave(&pg->lock, flags);
                                pg->flags &= ~ALUA_PG_RUNNING;
                                pg->flags |= ALUA_PG_RUN_RTPG;
+                               if (!pg->interval)
+                                       pg->interval = ALUA_RTPG_RETRY_DELAY;
                                spin_unlock_irqrestore(&pg->lock, flags);
                                queue_delayed_work(kaluad_wq, &pg->rtpg_work,
                                                   pg->interval * HZ);
@@ -818,6 +821,8 @@ static void alua_rtpg_work(struct work_struct *work)
                spin_lock_irqsave(&pg->lock, flags);
                if (err == SCSI_DH_RETRY || pg->flags & ALUA_PG_RUN_RTPG) {
                        pg->flags &= ~ALUA_PG_RUNNING;
+                       if (!pg->interval && !(pg->flags & ALUA_PG_RUN_RTPG))
+                               pg->interval = ALUA_RTPG_RETRY_DELAY;
                        pg->flags |= ALUA_PG_RUN_RTPG;
                        spin_unlock_irqrestore(&pg->lock, flags);
                        queue_delayed_work(kaluad_wq, &pg->rtpg_work,
index 590ec8009f52e7186cfe9206f80ef8b8560effa7..1791a393795daffec93ae58aefb23ee3b9131527 100644 (file)
@@ -1019,7 +1019,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
 {
        struct fcoe_fcf *fcf;
        struct fcoe_fcf new;
-       unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
+       unsigned long sol_tov = msecs_to_jiffies(FCOE_CTLR_SOL_TOV);
        int first = 0;
        int mtu_valid;
        int found = 0;
@@ -2005,7 +2005,7 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
  */
 static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
 {
-       return (struct fcoe_rport *)(rdata + 1);
+       return container_of(rdata, struct fcoe_rport, rdata);
 }
 
 /**
@@ -2269,7 +2269,7 @@ static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
  */
 static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
                              struct sk_buff *skb,
-                             struct fc_rport_priv *rdata)
+                             struct fcoe_rport *frport)
 {
        struct fip_header *fiph;
        struct fip_desc *desc = NULL;
@@ -2277,16 +2277,12 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
        struct fip_wwn_desc *wwn = NULL;
        struct fip_vn_desc *vn = NULL;
        struct fip_size_desc *size = NULL;
-       struct fcoe_rport *frport;
        size_t rlen;
        size_t dlen;
        u32 desc_mask = 0;
        u32 dtype;
        u8 sub;
 
-       memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
-       frport = fcoe_ctlr_rport(rdata);
-
        fiph = (struct fip_header *)skb->data;
        frport->flags = ntohs(fiph->fip_flags);
 
@@ -2349,15 +2345,17 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
                        if (dlen != sizeof(struct fip_wwn_desc))
                                goto len_err;
                        wwn = (struct fip_wwn_desc *)desc;
-                       rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
+                       frport->rdata.ids.node_name =
+                               get_unaligned_be64(&wwn->fd_wwn);
                        break;
                case FIP_DT_VN_ID:
                        if (dlen != sizeof(struct fip_vn_desc))
                                goto len_err;
                        vn = (struct fip_vn_desc *)desc;
                        memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
-                       rdata->ids.port_id = ntoh24(vn->fd_fc_id);
-                       rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
+                       frport->rdata.ids.port_id = ntoh24(vn->fd_fc_id);
+                       frport->rdata.ids.port_name =
+                               get_unaligned_be64(&vn->fd_wwpn);
                        break;
                case FIP_DT_FC4F:
                        if (dlen != sizeof(struct fip_fc4_feat))
@@ -2403,16 +2401,14 @@ static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip)
 /**
  * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request.
  * @fip: The FCoE controller
- * @rdata: parsed remote port with frport from the probe request
+ * @frport: parsed FCoE rport from the probe request
  *
  * Called with ctlr_mutex held.
  */
 static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
-                                  struct fc_rport_priv *rdata)
+                                  struct fcoe_rport *frport)
 {
-       struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
-
-       if (rdata->ids.port_id != fip->port_id)
+       if (frport->rdata.ids.port_id != fip->port_id)
                return;
 
        switch (fip->state) {
@@ -2432,7 +2428,7 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
                 * Probe's REC bit is not set.
                 * If we don't reply, we will change our address.
                 */
-               if (fip->lp->wwpn > rdata->ids.port_name &&
+               if (fip->lp->wwpn > frport->rdata.ids.port_name &&
                    !(frport->flags & FIP_FL_REC_OR_P2P)) {
                        LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
                                        "port_id collision\n");
@@ -2456,14 +2452,14 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
 /**
  * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply.
  * @fip: The FCoE controller
- * @rdata: parsed remote port with frport from the probe request
+ * @frport: parsed FCoE rport from the probe request
  *
  * Called with ctlr_mutex held.
  */
 static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
-                                  struct fc_rport_priv *rdata)
+                                    struct fcoe_rport *frport)
 {
-       if (rdata->ids.port_id != fip->port_id)
+       if (frport->rdata.ids.port_id != fip->port_id)
                return;
        switch (fip->state) {
        case FIP_ST_VNMP_START:
@@ -2486,11 +2482,11 @@ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
 /**
  * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply.
  * @fip: The FCoE controller
- * @new: newly-parsed remote port with frport as a template for new rdata
+ * @new: newly-parsed FCoE rport as a template for new rdata
  *
  * Called with ctlr_mutex held.
  */
-static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
+static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fcoe_rport *new)
 {
        struct fc_lport *lport = fip->lp;
        struct fc_rport_priv *rdata;
@@ -2498,7 +2494,7 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
        struct fcoe_rport *frport;
        u32 port_id;
 
-       port_id = new->ids.port_id;
+       port_id = new->rdata.ids.port_id;
        if (port_id == fip->port_id)
                return;
 
@@ -2515,22 +2511,28 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
        rdata->disc_id = lport->disc.disc_id;
 
        ids = &rdata->ids;
-       if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
-           (ids->node_name != -1 && ids->node_name != new->ids.node_name)) {
+       if ((ids->port_name != -1 &&
+            ids->port_name != new->rdata.ids.port_name) ||
+           (ids->node_name != -1 &&
+            ids->node_name != new->rdata.ids.node_name)) {
                mutex_unlock(&rdata->rp_mutex);
                LIBFCOE_FIP_DBG(fip, "vn_add rport logoff %6.6x\n", port_id);
                fc_rport_logoff(rdata);
                mutex_lock(&rdata->rp_mutex);
        }
-       ids->port_name = new->ids.port_name;
-       ids->node_name = new->ids.node_name;
+       ids->port_name = new->rdata.ids.port_name;
+       ids->node_name = new->rdata.ids.node_name;
        mutex_unlock(&rdata->rp_mutex);
 
        frport = fcoe_ctlr_rport(rdata);
        LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s state %d\n",
                        port_id, frport->fcoe_len ? "old" : "new",
                        rdata->rp_state);
-       *frport = *fcoe_ctlr_rport(new);
+       frport->fcoe_len = new->fcoe_len;
+       frport->flags = new->flags;
+       frport->login_count = new->login_count;
+       memcpy(frport->enode_mac, new->enode_mac, ETH_ALEN);
+       memcpy(frport->vn_mac, new->vn_mac, ETH_ALEN);
        frport->time = 0;
 }
 
@@ -2562,16 +2564,14 @@ static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac)
 /**
  * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification
  * @fip: The FCoE controller
- * @new: newly-parsed remote port with frport as a template for new rdata
+ * @new: newly-parsed FCoE rport as a template for new rdata
  *
  * Called with ctlr_mutex held.
  */
 static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
-                                     struct fc_rport_priv *new)
+                                     struct fcoe_rport *new)
 {
-       struct fcoe_rport *frport = fcoe_ctlr_rport(new);
-
-       if (frport->flags & FIP_FL_REC_OR_P2P) {
+       if (new->flags & FIP_FL_REC_OR_P2P) {
                LIBFCOE_FIP_DBG(fip, "send probe req for P2P/REC\n");
                fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
                return;
@@ -2580,7 +2580,7 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
        case FIP_ST_VNMP_START:
        case FIP_ST_VNMP_PROBE1:
        case FIP_ST_VNMP_PROBE2:
-               if (new->ids.port_id == fip->port_id) {
+               if (new->rdata.ids.port_id == fip->port_id) {
                        LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
                                        "restart, state %d\n",
                                        fip->state);
@@ -2589,8 +2589,8 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
                break;
        case FIP_ST_VNMP_CLAIM:
        case FIP_ST_VNMP_UP:
-               if (new->ids.port_id == fip->port_id) {
-                       if (new->ids.port_name > fip->lp->wwpn) {
+               if (new->rdata.ids.port_id == fip->port_id) {
+                       if (new->rdata.ids.port_name > fip->lp->wwpn) {
                                LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
                                                "restart, port_id collision\n");
                                fcoe_ctlr_vn_restart(fip);
@@ -2602,15 +2602,16 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
                        break;
                }
                LIBFCOE_FIP_DBG(fip, "vn_claim_notify: send reply to %x\n",
-                               new->ids.port_id);
-               fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
-                                 min((u32)frport->fcoe_len,
+                               new->rdata.ids.port_id);
+               fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, new->enode_mac,
+                                 min((u32)new->fcoe_len,
                                      fcoe_ctlr_fcoe_size(fip)));
                fcoe_ctlr_vn_add(fip, new);
                break;
        default:
                LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
-                               "ignoring claim from %x\n", new->ids.port_id);
+                               "ignoring claim from %x\n",
+                               new->rdata.ids.port_id);
                break;
        }
 }
@@ -2618,15 +2619,15 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
 /**
  * fcoe_ctlr_vn_claim_resp() - handle received Claim Response
  * @fip: The FCoE controller that received the frame
- * @new: newly-parsed remote port with frport from the Claim Response
+ * @new: newly-parsed FCoE rport from the Claim Response
  *
  * Called with ctlr_mutex held.
  */
 static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
-                                   struct fc_rport_priv *new)
+                                   struct fcoe_rport *new)
 {
        LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n",
-                       new->ids.port_id, fcoe_ctlr_state(fip->state));
+                       new->rdata.ids.port_id, fcoe_ctlr_state(fip->state));
        if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM)
                fcoe_ctlr_vn_add(fip, new);
 }
@@ -2634,28 +2635,28 @@ static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
 /**
  * fcoe_ctlr_vn_beacon() - handle received beacon.
  * @fip: The FCoE controller that received the frame
- * @new: newly-parsed remote port with frport from the Beacon
+ * @new: newly-parsed FCoE rport from the Beacon
  *
  * Called with ctlr_mutex held.
  */
 static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
-                               struct fc_rport_priv *new)
+                               struct fcoe_rport *new)
 {
        struct fc_lport *lport = fip->lp;
        struct fc_rport_priv *rdata;
        struct fcoe_rport *frport;
 
-       frport = fcoe_ctlr_rport(new);
-       if (frport->flags & FIP_FL_REC_OR_P2P) {
+       if (new->flags & FIP_FL_REC_OR_P2P) {
                LIBFCOE_FIP_DBG(fip, "p2p beacon while in vn2vn mode\n");
                fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
                return;
        }
-       rdata = fc_rport_lookup(lport, new->ids.port_id);
+       rdata = fc_rport_lookup(lport, new->rdata.ids.port_id);
        if (rdata) {
-               if (rdata->ids.node_name == new->ids.node_name &&
-                   rdata->ids.port_name == new->ids.port_name) {
+               if (rdata->ids.node_name == new->rdata.ids.node_name &&
+                   rdata->ids.port_name == new->rdata.ids.port_name) {
                        frport = fcoe_ctlr_rport(rdata);
+
                        LIBFCOE_FIP_DBG(fip, "beacon from rport %x\n",
                                        rdata->ids.port_id);
                        if (!frport->time && fip->state == FIP_ST_VNMP_UP) {
@@ -2678,7 +2679,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
         * Don't add the neighbor yet.
         */
        LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n",
-                       new->ids.port_id);
+                       new->rdata.ids.port_id);
        if (time_after(jiffies,
                       fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT)))
                fcoe_ctlr_vn_send_claim(fip);
@@ -2738,10 +2739,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
 {
        struct fip_header *fiph;
        enum fip_vn2vn_subcode sub;
-       struct {
-               struct fc_rport_priv rdata;
-               struct fcoe_rport frport;
-       } buf;
+       struct fcoe_rport frport = { };
        int rc, vlan_id = 0;
 
        fiph = (struct fip_header *)skb->data;
@@ -2757,7 +2755,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
                goto drop;
        }
 
-       rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
+       rc = fcoe_ctlr_vn_parse(fip, skb, &frport);
        if (rc) {
                LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
                goto drop;
@@ -2766,19 +2764,19 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
        mutex_lock(&fip->ctlr_mutex);
        switch (sub) {
        case FIP_SC_VN_PROBE_REQ:
-               fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
+               fcoe_ctlr_vn_probe_req(fip, &frport);
                break;
        case FIP_SC_VN_PROBE_REP:
-               fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
+               fcoe_ctlr_vn_probe_reply(fip, &frport);
                break;
        case FIP_SC_VN_CLAIM_NOTIFY:
-               fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
+               fcoe_ctlr_vn_claim_notify(fip, &frport);
                break;
        case FIP_SC_VN_CLAIM_REP:
-               fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
+               fcoe_ctlr_vn_claim_resp(fip, &frport);
                break;
        case FIP_SC_VN_BEACON:
-               fcoe_ctlr_vn_beacon(fip, &buf.rdata);
+               fcoe_ctlr_vn_beacon(fip, &frport);
                break;
        default:
                LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
@@ -2802,22 +2800,18 @@ drop:
  */
 static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
                              struct sk_buff *skb,
-                             struct fc_rport_priv *rdata)
+                             struct fcoe_rport *frport)
 {
        struct fip_header *fiph;
        struct fip_desc *desc = NULL;
        struct fip_mac_desc *macd = NULL;
        struct fip_wwn_desc *wwn = NULL;
-       struct fcoe_rport *frport;
        size_t rlen;
        size_t dlen;
        u32 desc_mask = 0;
        u32 dtype;
        u8 sub;
 
-       memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
-       frport = fcoe_ctlr_rport(rdata);
-
        fiph = (struct fip_header *)skb->data;
        frport->flags = ntohs(fiph->fip_flags);
 
@@ -2871,7 +2865,8 @@ static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
                        if (dlen != sizeof(struct fip_wwn_desc))
                                goto len_err;
                        wwn = (struct fip_wwn_desc *)desc;
-                       rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
+                       frport->rdata.ids.node_name =
+                               get_unaligned_be64(&wwn->fd_wwn);
                        break;
                default:
                        LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
@@ -2957,13 +2952,13 @@ static void fcoe_ctlr_vlan_send(struct fcoe_ctlr *fip,
 /**
  * fcoe_ctlr_vlan_disk_reply() - send FIP VLAN Discovery Notification.
  * @fip: The FCoE controller
+ * @frport: The newly-parsed FCoE rport from the Discovery Request
  *
  * Called with ctlr_mutex held.
  */
 static void fcoe_ctlr_vlan_disc_reply(struct fcoe_ctlr *fip,
-                                     struct fc_rport_priv *rdata)
+                                     struct fcoe_rport *frport)
 {
-       struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
        enum fip_vlan_subcode sub = FIP_SC_VL_NOTE;
 
        if (fip->mode == FIP_MODE_VN2VN)
@@ -2982,22 +2977,19 @@ static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
 {
        struct fip_header *fiph;
        enum fip_vlan_subcode sub;
-       struct {
-               struct fc_rport_priv rdata;
-               struct fcoe_rport frport;
-       } buf;
+       struct fcoe_rport frport = { };
        int rc;
 
        fiph = (struct fip_header *)skb->data;
        sub = fiph->fip_subcode;
-       rc = fcoe_ctlr_vlan_parse(fip, skb, &buf.rdata);
+       rc = fcoe_ctlr_vlan_parse(fip, skb, &frport);
        if (rc) {
                LIBFCOE_FIP_DBG(fip, "vlan_recv vlan_parse error %d\n", rc);
                goto drop;
        }
        mutex_lock(&fip->ctlr_mutex);
        if (sub == FIP_SC_VL_REQ)
-               fcoe_ctlr_vlan_disc_reply(fip, &buf.rdata);
+               fcoe_ctlr_vlan_disc_reply(fip, &frport);
        mutex_unlock(&fip->ctlr_mutex);
 
 drop:
index 43a6b535077546f1d1bbabb77a15abcb7d6a8cbc..1bb6aada93fab71e26f0e6c44569ae470a8c9e8b 100644 (file)
@@ -2334,6 +2334,8 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h,
        case IOACCEL2_SERV_RESPONSE_COMPLETE:
                switch (c2->error_data.status) {
                case IOACCEL2_STATUS_SR_TASK_COMP_GOOD:
+                       if (cmd)
+                               cmd->result = 0;
                        break;
                case IOACCEL2_STATUS_SR_TASK_COMP_CHK_COND:
                        cmd->result |= SAM_STAT_CHECK_CONDITION;
@@ -2483,8 +2485,10 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
 
        /* check for good status */
        if (likely(c2->error_data.serv_response == 0 &&
-                       c2->error_data.status == 0))
+                       c2->error_data.status == 0)) {
+               cmd->result = 0;
                return hpsa_cmd_free_and_done(h, c, cmd);
+       }
 
        /*
         * Any RAID offload error results in retry which will use
@@ -5653,6 +5657,12 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
        if (c == NULL)
                return SCSI_MLQUEUE_DEVICE_BUSY;
 
+       /*
+        * This is necessary because the SML doesn't zero out this field during
+        * error recovery.
+        */
+       cmd->result = 0;
+
        /*
         * Call alternate submit routine for I/O accelerated commands.
         * Retries always go down the normal I/O path.
@@ -6081,8 +6091,6 @@ static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h,
                if (idx != h->last_collision_tag) { /* Print once per tag */
                        dev_warn(&h->pdev->dev,
                                "%s: tag collision (tag=%d)\n", __func__, idx);
-                       if (c->scsi_cmd != NULL)
-                               scsi_print_command(c->scsi_cmd);
                        if (scmd)
                                scsi_print_command(scmd);
                        h->last_collision_tag = idx;
@@ -7798,7 +7806,7 @@ static void hpsa_free_pci_init(struct ctlr_info *h)
        hpsa_disable_interrupt_mode(h);         /* pci_init 2 */
        /*
         * call pci_disable_device before pci_release_regions per
-        * Documentation/PCI/pci.rst
+        * Documentation/driver-api/pci/pci.rst
         */
        pci_disable_device(h->pdev);            /* pci_init 1 */
        pci_release_regions(h->pdev);           /* pci_init 2 */
@@ -7881,7 +7889,7 @@ clean2:   /* intmode+region, pci */
 clean1:
        /*
         * call pci_disable_device before pci_release_regions per
-        * Documentation/PCI/pci.rst
+        * Documentation/driver-api/pci/pci.rst
         */
        pci_disable_device(h->pdev);
        pci_release_regions(h->pdev);
index acd16e0d52cfe801ee539111ae36fb54253ef76a..8cdbac076a1b62a56c880d6a67e54e82f6d05cc9 100644 (file)
@@ -4864,8 +4864,8 @@ static int ibmvfc_remove(struct vio_dev *vdev)
 
        spin_lock_irqsave(vhost->host->host_lock, flags);
        ibmvfc_purge_requests(vhost, DID_ERROR);
-       ibmvfc_free_event_pool(vhost);
        spin_unlock_irqrestore(vhost->host->host_lock, flags);
+       ibmvfc_free_event_pool(vhost);
 
        ibmvfc_free_mem(vhost);
        spin_lock(&ibmvfc_driver_lock);
index e0f3852fdad1543e8d668f828d2555bc78afab3a..da6e97d8dc3bb862a0ad1edd6e613d6af497507a 100644 (file)
@@ -128,6 +128,7 @@ EXPORT_SYMBOL(fc_rport_lookup);
 struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id)
 {
        struct fc_rport_priv *rdata;
+       size_t rport_priv_size = sizeof(*rdata);
 
        lockdep_assert_held(&lport->disc.disc_mutex);
 
@@ -135,7 +136,9 @@ struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id)
        if (rdata)
                return rdata;
 
-       rdata = kzalloc(sizeof(*rdata) + lport->rport_priv_size, GFP_KERNEL);
+       if (lport->rport_priv_size > 0)
+               rport_priv_size = lport->rport_priv_size;
+       rdata = kzalloc(rport_priv_size, GFP_KERNEL);
        if (!rdata)
                return NULL;
 
index abcad097ff2f4985413eac39209183751b1e8b14..f47b4b281b14ab5ed05973faf00c2aa09ec5b7c0 100644 (file)
@@ -459,6 +459,7 @@ static void sas_discover_domain(struct work_struct *work)
                pr_notice("ATA device seen but CONFIG_SCSI_SAS_ATA=N so cannot attach\n");
                /* Fall through */
 #endif
+               /* Fall through - only for the #else condition above. */
        default:
                error = -ENXIO;
                pr_err("unhandled device %d\n", dev->dev_type);
index 2c3bb8a966e5af1cc88412c2eb74a3e527d7a03f..bade2e025ecf2c73b2fdf0869d2e0f8652877c0e 100644 (file)
@@ -824,6 +824,7 @@ struct lpfc_hba {
        uint32_t cfg_cq_poll_threshold;
        uint32_t cfg_cq_max_proc_limit;
        uint32_t cfg_fcp_cpu_map;
+       uint32_t cfg_fcp_mq_threshold;
        uint32_t cfg_hdw_queue;
        uint32_t cfg_irq_chann;
        uint32_t cfg_suppress_rsp;
index ea62322ffe2bb7e711bc87d521903573550be282..d65558619ab057f0670af6187f8f5c353b749c06 100644 (file)
@@ -5708,6 +5708,19 @@ LPFC_ATTR_RW(nvme_oas, 0, 0, 1,
 LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
             "Embed NVME Command in WQE");
 
+/*
+ * lpfc_fcp_mq_threshold: Set the maximum number of Hardware Queues
+ * the driver will advertise it supports to the SCSI layer.
+ *
+ *      0    = Set nr_hw_queues by the number of CPUs or HW queues.
+ *      1,128 = Manually specify the maximum nr_hw_queue value to be set,
+ *
+ * Value range is [0,256]. Default value is 8.
+ */
+LPFC_ATTR_R(fcp_mq_threshold, LPFC_FCP_MQ_THRESHOLD_DEF,
+           LPFC_FCP_MQ_THRESHOLD_MIN, LPFC_FCP_MQ_THRESHOLD_MAX,
+           "Set the number of SCSI Queues advertised");
+
 /*
  * lpfc_hdw_queue: Set the number of Hardware Queues the driver
  * will advertise it supports to the NVME and  SCSI layers. This also
@@ -6030,6 +6043,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_cq_poll_threshold,
        &dev_attr_lpfc_cq_max_proc_limit,
        &dev_attr_lpfc_fcp_cpu_map,
+       &dev_attr_lpfc_fcp_mq_threshold,
        &dev_attr_lpfc_hdw_queue,
        &dev_attr_lpfc_irq_chann,
        &dev_attr_lpfc_suppress_rsp,
@@ -7112,6 +7126,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
        /* Initialize first burst. Target vs Initiator are different. */
        lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
        lpfc_nvmet_fb_size_init(phba, lpfc_nvmet_fb_size);
+       lpfc_fcp_mq_threshold_init(phba, lpfc_fcp_mq_threshold);
        lpfc_hdw_queue_init(phba, lpfc_hdw_queue);
        lpfc_irq_chann_init(phba, lpfc_irq_chann);
        lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
index faf43b1d3dbef626610744daf4d3ecf6220489db..1ac98becb5baf6b64516c47c267a958bee462e77 100644 (file)
@@ -4309,10 +4309,12 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
        shost->max_cmd_len = 16;
 
        if (phba->sli_rev == LPFC_SLI_REV4) {
-               if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ)
-                       shost->nr_hw_queues = phba->cfg_hdw_queue;
-               else
-                       shost->nr_hw_queues = phba->sli4_hba.num_present_cpu;
+               if (!phba->cfg_fcp_mq_threshold ||
+                   phba->cfg_fcp_mq_threshold > phba->cfg_hdw_queue)
+                       phba->cfg_fcp_mq_threshold = phba->cfg_hdw_queue;
+
+               shost->nr_hw_queues = min_t(int, 2 * num_possible_nodes(),
+                                           phba->cfg_fcp_mq_threshold);
 
                shost->dma_boundary =
                        phba->sli4_hba.pc_sli4_params.sge_supp_len-1;
@@ -10776,12 +10778,31 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors)
        /* This loop sets up all CPUs that are affinitized with a
         * irq vector assigned to the driver. All affinitized CPUs
         * will get a link to that vectors IRQ and EQ.
+        *
+        * NULL affinity mask handling:
+        * If irq count is greater than one, log an error message.
+        * If the null mask is received for the first irq, find the
+        * first present cpu, and assign the eq index to ensure at
+        * least one EQ is assigned.
         */
        for (idx = 0; idx <  phba->cfg_irq_chann; idx++) {
                /* Get a CPU mask for all CPUs affinitized to this vector */
                maskp = pci_irq_get_affinity(phba->pcidev, idx);
-               if (!maskp)
-                       continue;
+               if (!maskp) {
+                       if (phba->cfg_irq_chann > 1)
+                               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                               "3329 No affinity mask found "
+                                               "for vector %d (%d)\n",
+                                               idx, phba->cfg_irq_chann);
+                       if (!idx) {
+                               cpu = cpumask_first(cpu_present_mask);
+                               cpup = &phba->sli4_hba.cpu_map[cpu];
+                               cpup->eq = idx;
+                               cpup->irq = pci_irq_vector(phba->pcidev, idx);
+                               cpup->flag |= LPFC_CPU_FIRST_IRQ;
+                       }
+                       break;
+               }
 
                i = 0;
                /* Loop through all CPUs associated with vector idx */
index 3aeca387b22a4d3a253403e269652bb3bf108c94..a81ef0293696d34efe7da7e73ed5e0d738fdc826 100644 (file)
 #define LPFC_HBA_HDWQ_MAX      128
 #define LPFC_HBA_HDWQ_DEF      0
 
+/* FCP MQ queue count limiting */
+#define LPFC_FCP_MQ_THRESHOLD_MIN      0
+#define LPFC_FCP_MQ_THRESHOLD_MAX      256
+#define LPFC_FCP_MQ_THRESHOLD_DEF      8
+
 /* Common buffer size to accomidate SCSI and NVME IO buffers */
 #define LPFC_COMMON_IO_BUF_SZ  768
 
index b2339d04a700263d1164931505c19bf1c2f45bf5..f9f07935556ed2f7862052d613bd953e210b2454 100644 (file)
@@ -3163,6 +3163,7 @@ fw_crash_buffer_show(struct device *cdev,
                (struct megasas_instance *) shost->hostdata;
        u32 size;
        unsigned long dmachunk = CRASH_DMA_BUF_SIZE;
+       unsigned long chunk_left_bytes;
        unsigned long src_addr;
        unsigned long flags;
        u32 buff_offset;
@@ -3186,6 +3187,8 @@ fw_crash_buffer_show(struct device *cdev,
        }
 
        size = (instance->fw_crash_buffer_size * dmachunk) - buff_offset;
+       chunk_left_bytes = dmachunk - (buff_offset % dmachunk);
+       size = (size > chunk_left_bytes) ? chunk_left_bytes : size;
        size = (size >= PAGE_SIZE) ? (PAGE_SIZE - 1) : size;
 
        src_addr = (unsigned long)instance->crash_buf[buff_offset / dmachunk] +
@@ -8763,7 +8766,7 @@ static int __init megasas_init(void)
 
        if ((event_log_level < MFI_EVT_CLASS_DEBUG) ||
            (event_log_level > MFI_EVT_CLASS_DEAD)) {
-               printk(KERN_WARNING "megarid_sas: provided event log level is out of range, setting it to default 2(CLASS_CRITICAL), permissible range is: -2 to 4\n");
+               pr_warn("megaraid_sas: provided event log level is out of range, setting it to default 2(CLASS_CRITICAL), permissible range is: -2 to 4\n");
                event_log_level = MFI_EVT_CLASS_CRITICAL;
        }
 
index a32b3f0fcd155c789c8b428c8a965399a5c4fd1f..120e3c4de8c26757e58b0cae8988ad7aafd3f24b 100644 (file)
@@ -537,7 +537,7 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance)
        return 0;
 }
 
-int
+static int
 megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
 {
        u32 max_mpt_cmd, i, j;
@@ -576,7 +576,8 @@ megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
 
        return 0;
 }
-int
+
+static int
 megasas_alloc_request_fusion(struct megasas_instance *instance)
 {
        struct fusion_context *fusion;
@@ -657,7 +658,7 @@ retry_alloc:
        return 0;
 }
 
-int
+static int
 megasas_alloc_reply_fusion(struct megasas_instance *instance)
 {
        int i, count;
@@ -734,7 +735,7 @@ megasas_alloc_reply_fusion(struct megasas_instance *instance)
        return 0;
 }
 
-int
+static int
 megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
 {
        int i, j, k, msix_count;
@@ -916,7 +917,7 @@ megasas_free_reply_fusion(struct megasas_instance *instance) {
  * and is used as SMID of the cmd.
  * SMID value range is from 1 to max_fw_cmds.
  */
-int
+static int
 megasas_alloc_cmds_fusion(struct megasas_instance *instance)
 {
        int i;
@@ -1736,7 +1737,7 @@ static inline void megasas_free_ioc_init_cmd(struct megasas_instance *instance)
  *
  * This is the main function for initializing firmware.
  */
-u32
+static u32
 megasas_init_adapter_fusion(struct megasas_instance *instance)
 {
        struct fusion_context *fusion;
@@ -1962,7 +1963,7 @@ megasas_fusion_stop_watchdog(struct megasas_instance *instance)
  * @ext_status :       ext status of cmd returned by FW
  */
 
-void
+static void
 map_cmd_status(struct fusion_context *fusion,
                struct scsi_cmnd *scmd, u8 status, u8 ext_status,
                u32 data_length, u8 *sense)
@@ -2375,7 +2376,7 @@ int megasas_make_sgl(struct megasas_instance *instance, struct scsi_cmnd *scp,
  *
  * Used to set the PD LBA in CDB for FP IOs
  */
-void
+static void
 megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
                   struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp,
                   struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
@@ -2714,7 +2715,7 @@ megasas_set_raidflag_cpu_affinity(struct fusion_context *fusion,
  * Prepares the io_request and chain elements (sg_frame) for IO
  * The IO can be for PD (Fast Path) or LD
  */
-void
+static void
 megasas_build_ldio_fusion(struct megasas_instance *instance,
                          struct scsi_cmnd *scp,
                          struct megasas_cmd_fusion *cmd)
@@ -3211,7 +3212,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
  * Invokes helper functions to prepare request frames
  * and sets flags appropriate for IO/Non-IO cmd
  */
-int
+static int
 megasas_build_io_fusion(struct megasas_instance *instance,
                        struct scsi_cmnd *scp,
                        struct megasas_cmd_fusion *cmd)
@@ -3325,9 +3326,9 @@ megasas_get_request_descriptor(struct megasas_instance *instance, u16 index)
 /* megasas_prepate_secondRaid1_IO
  *  It prepares the raid 1 second IO
  */
-void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance,
-                           struct megasas_cmd_fusion *cmd,
-                           struct megasas_cmd_fusion *r1_cmd)
+static void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance,
+                                          struct megasas_cmd_fusion *cmd,
+                                          struct megasas_cmd_fusion *r1_cmd)
 {
        union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc, *req_desc2 = NULL;
        struct fusion_context *fusion;
index 684662888792f6ff0619fcc3c8a6c99a0909e42b..050c0f029ef9eb7c55902901ab667455b256cf42 100644 (file)
@@ -2703,6 +2703,8 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
 {
        u64 required_mask, coherent_mask;
        struct sysinfo s;
+       /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */
+       int dma_mask = (ioc->hba_mpi_version_belonged > MPI2_VERSION) ? 63 : 64;
 
        if (ioc->is_mcpu_endpoint)
                goto try_32bit;
@@ -2712,17 +2714,17 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
                goto try_32bit;
 
        if (ioc->dma_mask)
-               coherent_mask = DMA_BIT_MASK(64);
+               coherent_mask = DMA_BIT_MASK(dma_mask);
        else
                coherent_mask = DMA_BIT_MASK(32);
 
-       if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) ||
+       if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(dma_mask)) ||
            dma_set_coherent_mask(&pdev->dev, coherent_mask))
                goto try_32bit;
 
        ioc->base_add_sg_single = &_base_add_sg_single_64;
        ioc->sge_size = sizeof(Mpi2SGESimple64_t);
-       ioc->dma_mask = 64;
+       ioc->dma_mask = dma_mask;
        goto out;
 
  try_32bit:
@@ -2744,7 +2746,7 @@ static int
 _base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc,
                                      struct pci_dev *pdev)
 {
-       if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+       if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ioc->dma_mask))) {
                if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
                        return -ENODEV;
        }
@@ -4989,7 +4991,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
                total_sz += sz;
        } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));
 
-       if (ioc->dma_mask == 64) {
+       if (ioc->dma_mask > 32) {
                if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
                        ioc_warn(ioc, "no suitable consistent DMA mask for %s\n",
                                 pci_name(ioc->pdev));
index 8d560c562e9c06b5828b62d0c576f67ec978b20e..6b7b390b2e5228c238b4415282331fd19eff32d6 100644 (file)
@@ -2956,6 +2956,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
        dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
            vha->gnl.ldma);
 
+       vha->gnl.l = NULL;
+
        vfree(vha->scan.l);
 
        if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
index 4059655639d909e8799fe991a6f4d0961820215c..da83034d47592cbbbb52b51f54b952b3158c7451 100644 (file)
@@ -4877,7 +4877,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
                ql_log(ql_log_warn, vha, 0xd049,
                    "Failed to allocate ct_sns request.\n");
                kfree(fcport);
-               fcport = NULL;
+               return NULL;
        }
 
        INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
index 2e58cff9d2005b0cab783ab22653cb27e8333ecd..98e60a34afd9c083fa0ed6377c8ef32d4f3fd3c3 100644 (file)
@@ -3440,6 +3440,12 @@ skip_dpc:
        return 0;
 
 probe_failed:
+       if (base_vha->gnl.l) {
+               dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
+                               base_vha->gnl.l, base_vha->gnl.ldma);
+               base_vha->gnl.l = NULL;
+       }
+
        if (base_vha->timer_active)
                qla2x00_stop_timer(base_vha);
        base_vha->flags.online = 0;
@@ -3673,7 +3679,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
        if (!atomic_read(&pdev->enable_cnt)) {
                dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
                    base_vha->gnl.l, base_vha->gnl.ldma);
-
+               base_vha->gnl.l = NULL;
                scsi_host_put(base_vha->host);
                kfree(ha);
                pci_set_drvdata(pdev, NULL);
@@ -3713,6 +3719,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
        dma_free_coherent(&ha->pdev->dev,
                base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
 
+       base_vha->gnl.l = NULL;
+
        vfree(base_vha->scan.l);
 
        if (IS_QLAFX00(ha))
@@ -4816,6 +4824,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
                    "Alloc failed for scan database.\n");
                dma_free_coherent(&ha->pdev->dev, vha->gnl.size,
                    vha->gnl.l, vha->gnl.ldma);
+               vha->gnl.l = NULL;
                scsi_remove_host(vha->host);
                return NULL;
        }
index 9381171c2fc02741df68aa59b9e8a024f608356a..11e64b50497f81949476014f2b31d40d024346ed 100644 (file)
@@ -1784,8 +1784,10 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
                blk_queue_max_integrity_segments(q, shost->sg_prot_tablesize);
        }
 
-       shost->max_sectors = min_t(unsigned int, shost->max_sectors,
-                       dma_max_mapping_size(dev) << SECTOR_SHIFT);
+       if (dev->dma_mask) {
+               shost->max_sectors = min_t(unsigned int, shost->max_sectors,
+                               dma_max_mapping_size(dev) >> SECTOR_SHIFT);
+       }
        blk_queue_max_hw_sectors(q, shost->max_sectors);
        if (shost->unchecked_isa_dma)
                blk_queue_bounce_limit(q, BLK_BOUNCE_ISA);
index e274053109d073ae636b43834cbeb7371fb39256..029da74bb2f5c1a0e43efd5ad7bd7d1dc521ec24 100644 (file)
@@ -7062,6 +7062,9 @@ static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
 static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
                                         struct ufs_vreg *vreg)
 {
+       if (!vreg)
+               return 0;
+
        return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
 }
 
index 62c6ba17991ad614d787d0ff57d9f39f53341982..c9519e62308c595b4fb07a1b1057589cc27e77c1 100644 (file)
@@ -419,7 +419,7 @@ static void qe_upload_microcode(const void *base,
 /*
  * Upload a microcode to the I-RAM at a specific address.
  *
- * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
+ * See Documentation/powerpc/qe_firmware.rst for information on QE microcode
  * uploading.
  *
  * Currently, only version 1 is supported, so the 'version' field must be
index de2e62c3310a37d006d50ec223da1883d97a4a6d..e3eb19b85fa4b358950f702d4a74f35889ee84eb 100644 (file)
@@ -1,4 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
+if ARCH_IXP4XX || COMPILE_TEST
+
 menu "IXP4xx SoC drivers"
 
 config IXP4XX_QMGR
@@ -15,3 +17,5 @@ config IXP4XX_NPE
          and is automatically selected by Ethernet and HSS drivers.
 
 endmenu
+
+endif
index d5cf953b4337020acad2ee5fd83973640f50fe13..7d622ea1274ebc8aeb240041225a7a519df07468 100644 (file)
@@ -630,6 +630,9 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
        struct geni_wrapper *wrapper = se->wrapper;
        u32 val;
 
+       if (!wrapper)
+               return -EINVAL;
+
        *iova = dma_map_single(wrapper->dev, buf, len, DMA_TO_DEVICE);
        if (dma_mapping_error(wrapper->dev, *iova))
                return -EIO;
@@ -663,6 +666,9 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
        struct geni_wrapper *wrapper = se->wrapper;
        u32 val;
 
+       if (!wrapper)
+               return -EINVAL;
+
        *iova = dma_map_single(wrapper->dev, buf, len, DMA_FROM_DEVICE);
        if (dma_mapping_error(wrapper->dev, *iova))
                return -EIO;
index bb77c220b6f82b34c81cdf9f2e43bef82bef10b3..ccc6d53fe788ff754a5a402d65f46985567a176a 100644 (file)
@@ -141,7 +141,7 @@ static int __init am43xx_map_gic(void)
 }
 
 #ifdef CONFIG_SUSPEND
-struct wkup_m3_wakeup_src rtc_wake_src(void)
+static struct wkup_m3_wakeup_src rtc_wake_src(void)
 {
        u32 i;
 
@@ -157,7 +157,7 @@ struct wkup_m3_wakeup_src rtc_wake_src(void)
        return rtc_ext_wakeup;
 }
 
-int am33xx_rtc_only_idle(unsigned long wfi_flags)
+static int am33xx_rtc_only_idle(unsigned long wfi_flags)
 {
        omap_rtc_power_off_program(&omap_rtc->dev);
        am33xx_do_wfi_sram(wfi_flags);
@@ -252,7 +252,7 @@ static int am33xx_pm_begin(suspend_state_t state)
        if (state == PM_SUSPEND_MEM && pm_ops->check_off_mode_enable()) {
                nvmem = devm_nvmem_device_get(&omap_rtc->dev,
                                              "omap_rtc_scratch0");
-               if (nvmem)
+               if (!IS_ERR(nvmem))
                        nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
                                           (void *)&rtc_magic_val);
                rtc_only_idle = 1;
@@ -278,9 +278,12 @@ static void am33xx_pm_end(void)
        struct nvmem_device *nvmem;
 
        nvmem = devm_nvmem_device_get(&omap_rtc->dev, "omap_rtc_scratch0");
+       if (IS_ERR(nvmem))
+               return;
+
        m3_ipc->ops->finish_low_power(m3_ipc);
        if (rtc_only_idle) {
-               if (retrigger_irq)
+               if (retrigger_irq) {
                        /*
                         * 32 bits of Interrupt Set-Pending correspond to 32
                         * 32 interrupts. Compute the bit offset of the
@@ -291,8 +294,10 @@ static void am33xx_pm_end(void)
                        writel_relaxed(1 << (retrigger_irq & 31),
                                       gic_dist_base + GIC_INT_SET_PENDING_BASE
                                       + retrigger_irq / 32 * 4);
-                       nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
-                                          (void *)&val);
+               }
+
+               nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
+                                  (void *)&val);
        }
 
        rtc_only_idle = 0;
@@ -415,7 +420,7 @@ static int am33xx_pm_rtc_setup(void)
 
                nvmem = devm_nvmem_device_get(&omap_rtc->dev,
                                              "omap_rtc_scratch0");
-               if (nvmem) {
+               if (!IS_ERR(nvmem)) {
                        nvmem_device_read(nvmem, RTC_SCRATCH_MAGIC_REG * 4,
                                          4, (void *)&rtc_magic_val);
                        if ((rtc_magic_val & 0xffff) != RTC_REG_BOOT_MAGIC)
index 3a01cfd70fdcdb45b8f6d149136b91421e82eaa1..f518273cfbe3cbcd4cc4ed0c462550a3c9e11d03 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 menuconfig SOUNDWIRE
-       bool "SoundWire support"
+       tristate "SoundWire support"
        help
          SoundWire is a 2-Pin interface with data and clock line ratified
          by the MIPI Alliance. SoundWire is used for transporting data
@@ -17,17 +17,12 @@ if SOUNDWIRE
 
 comment "SoundWire Devices"
 
-config SOUNDWIRE_BUS
-       tristate
-       select REGMAP_SOUNDWIRE
-
 config SOUNDWIRE_CADENCE
        tristate
 
 config SOUNDWIRE_INTEL
        tristate "Intel SoundWire Master driver"
        select SOUNDWIRE_CADENCE
-       select SOUNDWIRE_BUS
        depends on X86 && ACPI && SND_SOC
        help
          SoundWire Intel Master driver.
index fd99a831b92a0baf3a15b4a42db8160034b1468e..45b7e50016539aaad4242a14a7292ff5c4d7b3a6 100644 (file)
@@ -5,7 +5,7 @@
 
 #Bus Objs
 soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o
-obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
+obj-$(CONFIG_SOUNDWIRE) += soundwire-bus.o
 
 #Cadence Objs
 soundwire-cadence-objs := cadence_master.o
index ff4badc9b3dec599e269cda5f1c39b9ef282b305..60e8bdee5c754b83f2170bad9757d5cc5c63aa9d 100644 (file)
@@ -81,8 +81,8 @@
 
 #define CDNS_MCP_INTSET                                0x4C
 
-#define CDNS_SDW_SLAVE_STAT                    0x50
-#define CDNS_MCP_SLAVE_STAT_MASK               BIT(1, 0)
+#define CDNS_MCP_SLAVE_STAT                    0x50
+#define CDNS_MCP_SLAVE_STAT_MASK               GENMASK(1, 0)
 
 #define CDNS_MCP_SLAVE_INTSTAT0                        0x54
 #define CDNS_MCP_SLAVE_INTSTAT1                        0x58
@@ -96,8 +96,8 @@
 #define CDNS_MCP_SLAVE_INTMASK0                        0x5C
 #define CDNS_MCP_SLAVE_INTMASK1                        0x60
 
-#define CDNS_MCP_SLAVE_INTMASK0_MASK           GENMASK(30, 0)
-#define CDNS_MCP_SLAVE_INTMASK1_MASK           GENMASK(16, 0)
+#define CDNS_MCP_SLAVE_INTMASK0_MASK           GENMASK(31, 0)
+#define CDNS_MCP_SLAVE_INTMASK1_MASK           GENMASK(15, 0)
 
 #define CDNS_MCP_PORT_INTSTAT                  0x64
 #define CDNS_MCP_PDI_STAT                      0x6C
index 6f243a90c844d5078faeb442fb620e6ef37e750e..840b1b8ff3dcbf644eff61ad239d9917dcae1406 100644 (file)
@@ -834,7 +834,8 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr,
        bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
 
        /* handle all the 3-wire mode */
-       if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
+       if (spi->mode & SPI_3WIRE && tfr->rx_buf &&
+           tfr->rx_buf != ctlr->dummy_rx)
                cs |= BCM2835_SPI_CS_REN;
        else
                cs &= ~BCM2835_SPI_CS_REN;
index 41a49b93ca60e6979a8ffdebd871dda739695a63..448c00e4065b86cad66e61c0db103f6f604bde80 100644 (file)
@@ -206,7 +206,7 @@ static const struct fsl_qspi_devtype_data imx6sx_data = {
 };
 
 static const struct fsl_qspi_devtype_data imx7d_data = {
-       .rxfifo = SZ_512,
+       .rxfifo = SZ_128,
        .txfifo = SZ_512,
        .ahb_buf_size = SZ_1K,
        .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK,
index eca9d52ecf65c57d342ac4abcb4bd49e9f781972..9eb82150666e88e98b83ba336123ce88267eab5b 100644 (file)
@@ -410,6 +410,12 @@ static int spi_gpio_probe(struct platform_device *pdev)
 
        bb = &spi_gpio->bitbang;
        bb->master = master;
+       /*
+        * There is some additional business, apart from driving the CS GPIO
+        * line, that we need to do on selection. This makes the local
+        * callback for chipselect always get called.
+        */
+       master->flags |= SPI_MASTER_GPIO_SS;
        bb->chipselect = spi_gpio_chipselect;
        bb->set_line_direction = spi_gpio_set_direction;
 
index fc7ab4b2688023b215c273bb8c65cad13533f5f0..bb6a14d1ab0f929d6e4573573be92db15e631acc 100644 (file)
@@ -1457,6 +1457,14 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
        { PCI_VDEVICE(INTEL, 0x02aa), LPSS_CNL_SSP },
        { PCI_VDEVICE(INTEL, 0x02ab), LPSS_CNL_SSP },
        { PCI_VDEVICE(INTEL, 0x02fb), LPSS_CNL_SSP },
+       /* TGL-LP */
+       { PCI_VDEVICE(INTEL, 0xa0aa), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0xa0ab), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0xa0de), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0xa0df), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0xa0fb), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0xa0fd), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0xa0fe), LPSS_CNL_SSP },
        { },
 };
 
@@ -1831,14 +1839,16 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        status = devm_spi_register_controller(&pdev->dev, controller);
        if (status != 0) {
                dev_err(&pdev->dev, "problem registering spi controller\n");
-               goto out_error_clock_enabled;
+               goto out_error_pm_runtime_enabled;
        }
 
        return status;
 
-out_error_clock_enabled:
+out_error_pm_runtime_enabled:
        pm_runtime_put_noidle(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
+
+out_error_clock_enabled:
        clk_disable_unprepare(ssp->clk);
 
 out_error_dma_irq_alloc:
index fd4995fb676eaa73aea38da72b7f219f9c67517e..f85ec5b16b65e3ed59880b029c33c930f036c781 100644 (file)
@@ -8,11 +8,14 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
+#include <linux/sched/signal.h>
 
 #include "ion.h"
 
 static inline struct page *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
 {
+       if (fatal_signal_pending(current))
+               return NULL;
        return alloc_pages(pool->gfp_mask, pool->order);
 }
 
index 2edf3ee91300007c4dff503774bca1f2fe04b57b..caf4d4df4bd3044f68a6e26b0bc5145b20e150ef 100644 (file)
@@ -342,9 +342,9 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
                            unsigned int flags)
 {
-       int divider, base, prescale;
+       unsigned int divider, base, prescale;
 
-       /* This function needs improvment */
+       /* This function needs improvement */
        /* Don't know if divider==0 works. */
 
        for (prescale = 0; prescale < 16; prescale++) {
@@ -358,7 +358,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
                        divider = (*nanosec) / base;
                        break;
                case CMDF_ROUND_UP:
-                       divider = (*nanosec) / base;
+                       divider = DIV_ROUND_UP(*nanosec, base);
                        break;
                }
                if (divider < 65536) {
@@ -368,7 +368,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
        }
 
        prescale = 15;
-       base = timer_base * (1 << prescale);
+       base = timer_base * (prescale + 1);
        divider = 65535;
        *nanosec = divider * base;
        return (prescale << 16) | (divider);
index b6c6d66e4eb1b5eb8806f85cceee764f805e73b0..e2c7646588f8c9d5cee07e9514e677163cae4eea 100644 (file)
@@ -24,7 +24,7 @@
 
 static int init_display(struct fbtft_par *par)
 {
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        par->fbtftops.reset(par);
index d609a2b67db9b6cf56db1ace82b45e1a019e776c..fd32376700e288b944308c09b5718f0329dcfefd 100644 (file)
@@ -77,7 +77,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */
index b090e7ab6fdd60c5b4df0a7ef8568034eb4aff98..85e54a10ed72c4c9d866d59fac20a2f6e41e1527 100644 (file)
@@ -85,7 +85,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        bt &= 0x07;
index b3d0701880fe353cc46092be339d0e848c904387..5a129b1352cc8ec010ec027322ad1b662ceaf0c8 100644 (file)
@@ -29,7 +29,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        /* Initialization sequence from Lib_UTFT */
index bbf75f795234b06c96a246b009bd05015a06efbf..88a5b6925901d39456efd02f7816b567534cb627 100644 (file)
@@ -28,7 +28,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        write_reg(par, 0x00, 0x0001);
index 4cfe9f8535d0fedb2ce877fd347480e3b01fd733..37622c9462aa7da92d25d1016f0c1f68463a86cc 100644 (file)
@@ -81,7 +81,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
        va_start(args, len);
 
        *buf = (u8)va_arg(args, unsigned int);
-       if (!par->gpio.dc)
+       if (par->gpio.dc)
                gpiod_set_value(par->gpio.dc, 0);
        ret = par->fbtftops.write(par, par->buf, sizeof(u8));
        if (ret < 0) {
@@ -104,7 +104,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
                        return;
                }
        }
-       if (!par->gpio.dc)
+       if (par->gpio.dc)
                gpiod_set_value(par->gpio.dc, 1);
        va_end(args);
 }
index 564a38e3444062b7d049470f23abbbd5a375b71c..c77832ae5e5ba5cffea8cf37915530d29eae745b 100644 (file)
@@ -26,7 +26,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        /* Initialization sequence from Lib_UTFT */
index 2ea814d0dca5d45679866540ec7c3a7e57fde45a..63c65dd67b175ca9b28c4121115bac4c001b0cdb 100644 (file)
@@ -135,7 +135,7 @@ int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
        remain = len / 2;
        vmem16 = (u16 *)(par->info->screen_buffer + offset);
 
-       if (!par->gpio.dc)
+       if (par->gpio.dc)
                gpiod_set_value(par->gpio.dc, 1);
 
        /* non buffered write */
index 7cbc1bdd2d8a7ef6c2ca4f6b47fe02797c488e87..cf5700a2ea6688d6e73e07151fe40b5d4e6af7e8 100644 (file)
@@ -76,21 +76,18 @@ static int fbtft_request_one_gpio(struct fbtft_par *par,
                                  struct gpio_desc **gpiop)
 {
        struct device *dev = par->info->device;
-       struct device_node *node = dev->of_node;
        int ret = 0;
 
-       if (of_find_property(node, name, NULL)) {
-               *gpiop = devm_gpiod_get_index(dev, dev->driver->name, index,
-                                             GPIOD_OUT_HIGH);
-               if (IS_ERR(*gpiop)) {
-                       ret = PTR_ERR(*gpiop);
-                       dev_err(dev,
-                               "Failed to request %s GPIO:%d\n", name, ret);
-                       return ret;
-               }
-               fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
-                             __func__, name);
+       *gpiop = devm_gpiod_get_index_optional(dev, name, index,
+                                              GPIOD_OUT_HIGH);
+       if (IS_ERR(*gpiop)) {
+               ret = PTR_ERR(*gpiop);
+               dev_err(dev,
+                       "Failed to request %s GPIO: %d\n", name, ret);
+               return ret;
        }
+       fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
+                     __func__, name);
 
        return ret;
 }
@@ -103,34 +100,34 @@ static int fbtft_request_gpios_dt(struct fbtft_par *par)
        if (!par->info->device->of_node)
                return -EINVAL;
 
-       ret = fbtft_request_one_gpio(par, "reset-gpios", 0, &par->gpio.reset);
+       ret = fbtft_request_one_gpio(par, "reset", 0, &par->gpio.reset);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "dc-gpios", 0, &par->gpio.dc);
+       ret = fbtft_request_one_gpio(par, "dc", 0, &par->gpio.dc);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "rd-gpios", 0, &par->gpio.rd);
+       ret = fbtft_request_one_gpio(par, "rd", 0, &par->gpio.rd);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "wr-gpios", 0, &par->gpio.wr);
+       ret = fbtft_request_one_gpio(par, "wr", 0, &par->gpio.wr);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "cs-gpios", 0, &par->gpio.cs);
+       ret = fbtft_request_one_gpio(par, "cs", 0, &par->gpio.cs);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "latch-gpios", 0, &par->gpio.latch);
+       ret = fbtft_request_one_gpio(par, "latch", 0, &par->gpio.latch);
        if (ret)
                return ret;
        for (i = 0; i < 16; i++) {
-               ret = fbtft_request_one_gpio(par, "db-gpios", i,
+               ret = fbtft_request_one_gpio(par, "db", i,
                                             &par->gpio.db[i]);
                if (ret)
                        return ret;
-               ret = fbtft_request_one_gpio(par, "led-gpios", i,
+               ret = fbtft_request_one_gpio(par, "led", i,
                                             &par->gpio.led[i]);
                if (ret)
                        return ret;
-               ret = fbtft_request_one_gpio(par, "aux-gpios", i,
+               ret = fbtft_request_one_gpio(par, "aux", i,
                                             &par->gpio.aux[i]);
                if (ret)
                        return ret;
@@ -234,9 +231,9 @@ static void fbtft_reset(struct fbtft_par *par)
        if (!par->gpio.reset)
                return;
        fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
-       gpiod_set_value_cansleep(par->gpio.reset, 0);
-       usleep_range(20, 40);
        gpiod_set_value_cansleep(par->gpio.reset, 1);
+       usleep_range(20, 40);
+       gpiod_set_value_cansleep(par->gpio.reset, 0);
        msleep(120);
 }
 
@@ -921,7 +918,7 @@ static int fbtft_init_display_dt(struct fbtft_par *par)
                return -EINVAL;
 
        par->fbtftops.reset(par);
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        while (p) {
@@ -1012,7 +1009,7 @@ int fbtft_init_display(struct fbtft_par *par)
        }
 
        par->fbtftops.reset(par);
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        i = 0;
index 2be45ee9d061747ad3a2a98f31ba67d9f6214827..464648ee20368627fd0d8a2f98df24888d186df4 100644 (file)
@@ -532,7 +532,7 @@ static ssize_t sysfs_show(struct device *device, struct device_attribute *attr,
                break;
        case ATTR_KERNEL_HIB_SIMPLE_PAGE_TABLE_SIZE:
                ret = scnprintf(buf, PAGE_SIZE, "%u\n",
-                               gasket_page_table_num_entries(
+                               gasket_page_table_num_simple_entries(
                                        gasket_dev->page_table[0]));
                break;
        case ATTR_KERNEL_HIB_NUM_ACTIVE_PAGES:
index 9d4f1dab0968dd04d5ed75daf42f240dfe00c71c..40dd573e73c3d4318ab54911951907f5ecaf9f3d 100644 (file)
@@ -1750,7 +1750,8 @@ static int visornic_poll(struct napi_struct *napi, int budget)
 }
 
 /* poll_for_irq        - checks the status of the response queue
- * @v: Void pointer to the visronic devdata struct.
+ * @t: pointer to the 'struct timer_list' from which we can retrieve the
+ *     the visornic devdata struct.
  *
  * Main function of the vnic_incoming thread. Periodically check the response
  * queue and drain it if needed.
index d72fdd333050cd45042237942f794a41f9d7ffa9..736eedef23b69e5d9670b8a701adb06513ec4f46 100644 (file)
@@ -1969,6 +1969,7 @@ void wilc_deinit_host_int(struct net_device *net)
 
        priv->p2p_listen_state = false;
 
+       flush_workqueue(vif->wilc->hif_workqueue);
        mutex_destroy(&priv->scan_req_lock);
        ret = wilc_deinit(vif);
 
index 22dd4c457d6a8eb8fa579fab49f9a5deea81e4ff..c70caf4ea49012006c3a8ac754ff9e1c16399ec7 100644 (file)
@@ -875,10 +875,12 @@ static u8 cxgbit_get_iscsi_dcb_priority(struct net_device *ndev, u16 local_port)
                return 0;
 
        if (caps & DCB_CAP_DCBX_VER_IEEE) {
-               iscsi_dcb_app.selector = IEEE_8021QAZ_APP_SEL_ANY;
-
+               iscsi_dcb_app.selector = IEEE_8021QAZ_APP_SEL_STREAM;
                ret = dcb_ieee_getapp_mask(ndev, &iscsi_dcb_app);
-
+               if (!ret) {
+                       iscsi_dcb_app.selector = IEEE_8021QAZ_APP_SEL_ANY;
+                       ret = dcb_ieee_getapp_mask(ndev, &iscsi_dcb_app);
+               }
        } else if (caps & DCB_CAP_DCBX_VER_CEE) {
                iscsi_dcb_app.selector = DCB_APP_IDTYPE_PORTNUM;
 
index 343b129c2cfab94a236203d27ca317336d84c960..e877b917c15f59fd6121f1c4dcca420aa2092520 100644 (file)
@@ -589,7 +589,8 @@ static void cxgbit_dcb_workfn(struct work_struct *work)
        iscsi_app = &dcb_work->dcb_app;
 
        if (iscsi_app->dcbx & DCB_CAP_DCBX_VER_IEEE) {
-               if (iscsi_app->app.selector != IEEE_8021QAZ_APP_SEL_ANY)
+               if ((iscsi_app->app.selector != IEEE_8021QAZ_APP_SEL_STREAM) &&
+                   (iscsi_app->app.selector != IEEE_8021QAZ_APP_SEL_ANY))
                        goto out;
 
                priority = iscsi_app->app.priority;
index 04eda111920ec4cae3d41184cdfac9afde63922c..661bb9358364df814c16fa60614265bce2c8117a 100644 (file)
@@ -1132,14 +1132,16 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        struct se_cmd *se_cmd = cmd->se_cmd;
        struct tcmu_dev *udev = cmd->tcmu_dev;
        bool read_len_valid = false;
-       uint32_t read_len = se_cmd->data_length;
+       uint32_t read_len;
 
        /*
         * cmd has been completed already from timeout, just reclaim
         * data area space and free cmd
         */
-       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
+       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+               WARN_ON_ONCE(se_cmd);
                goto out;
+       }
 
        list_del_init(&cmd->queue_entry);
 
@@ -1152,6 +1154,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
                goto done;
        }
 
+       read_len = se_cmd->data_length;
        if (se_cmd->data_direction == DMA_FROM_DEVICE &&
            (entry->hdr.uflags & TCMU_UFLAG_READ_LEN) && entry->rsp.read_len) {
                read_len_valid = true;
@@ -1307,6 +1310,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
                 */
                scsi_status = SAM_STAT_CHECK_CONDITION;
                list_del_init(&cmd->queue_entry);
+               cmd->se_cmd = NULL;
        } else {
                list_del_init(&cmd->queue_entry);
                idr_remove(&udev->commands, id);
@@ -2022,6 +2026,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
 
                idr_remove(&udev->commands, i);
                if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+                       WARN_ON(!cmd->se_cmd);
                        list_del_init(&cmd->queue_entry);
                        if (err_level == 1) {
                                /*
index 213ab3cc6b8069a27b2ccd1c51c7a671a8a76b44..d3446acf9bbde5a0bd4a45f369811f45d900c5ea 100644 (file)
@@ -487,6 +487,7 @@ static int proc_thermal_rapl_add(struct pci_dev *pdev,
                                rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep);
        if (ret < 0) {
                powercap_unregister_control_type(rapl_mmio_priv.control_type);
+               rapl_mmio_priv.control_type = NULL;
                return ret;
        }
        rapl_mmio_priv.pcap_rapl_online = ret;
@@ -496,6 +497,9 @@ static int proc_thermal_rapl_add(struct pci_dev *pdev,
 
 static void proc_thermal_rapl_remove(void)
 {
+       if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
+               return;
+
        cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online);
        powercap_unregister_control_type(rapl_mmio_priv.control_type);
 }
index cb4db1b3ca3c0daab51bbc466789dc5d5bc0710f..5fb214e67d736f8745dc3e4fbd7137a49ca373ae 100644 (file)
@@ -47,7 +47,7 @@
  * using the 2.6 Linux kernel kref construct.
  *
  * For direction on installation and usage of this driver please reference
- * Documentation/powerpc/hvcs.txt.
+ * Documentation/powerpc/hvcs.rst.
  */
 
 #include <linux/device.h>
index fd385c8c53a52192d9141ad57270c87be10fed62..3083dbae35f7e4175c8f24b85dca4daac1de859c 100644 (file)
@@ -1035,25 +1035,6 @@ config SERIAL_VT8500_CONSOLE
        depends on SERIAL_VT8500=y
        select SERIAL_CORE_CONSOLE
 
-config SERIAL_NETX
-       tristate "NetX serial port support"
-       depends on ARCH_NETX
-       select SERIAL_CORE
-       help
-         If you have a machine based on a Hilscher NetX SoC you
-         can enable its onboard serial port by enabling this option.
-
-          To compile this driver as a module, choose M here: the
-          module will be called netx-serial.
-
-config SERIAL_NETX_CONSOLE
-       bool "Console on NetX serial port"
-       depends on SERIAL_NETX=y
-       select SERIAL_CORE_CONSOLE
-       help
-         If you have enabled the serial port on the Hilscher NetX SoC
-         you can make it the console by answering Y to this option.
-
 config SERIAL_OMAP
        tristate "OMAP serial port support"
        depends on ARCH_OMAP2PLUS
index 7cd7cabfa6c413688dec0f86840825b4f0041891..15a0fccadf7ef85f550e2a6090c5008143a8a175 100644 (file)
@@ -59,7 +59,6 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
 obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
 obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
 obj-$(CONFIG_SERIAL_QCOM_GENI) += qcom_geni_serial.o
-obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
 obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
 obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
index bfe5e9e034ecf86b3de80476eb90a44a0d228359..c7d51b51898f675917e74e0ff362cad5eb1b9cbe 100644 (file)
@@ -277,10 +277,14 @@ static void kgdboc_pre_exp_handler(void)
        /* Increment the module count when the debugger is active */
        if (!kgdb_connected)
                try_module_get(THIS_MODULE);
+
+       atomic_inc(&ignore_console_lock_warning);
 }
 
 static void kgdboc_post_exp_handler(void)
 {
+       atomic_dec(&ignore_console_lock_warning);
+
        /* decrement the module count when the debugger detaches */
        if (!kgdb_connected)
                module_put(THIS_MODULE);
diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c
deleted file mode 100644 (file)
index b355686..0000000
+++ /dev/null
@@ -1,733 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- */
-
-#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <mach/netx-regs.h>
-
-/* We've been assigned a range on the "Low-density serial ports" major */
-#define SERIAL_NX_MAJOR        204
-#define MINOR_START    170
-
-enum uart_regs {
-       UART_DR              = 0x00,
-       UART_SR              = 0x04,
-       UART_LINE_CR         = 0x08,
-       UART_BAUDDIV_MSB     = 0x0c,
-       UART_BAUDDIV_LSB     = 0x10,
-       UART_CR              = 0x14,
-       UART_FR              = 0x18,
-       UART_IIR             = 0x1c,
-       UART_ILPR            = 0x20,
-       UART_RTS_CR          = 0x24,
-       UART_RTS_LEAD        = 0x28,
-       UART_RTS_TRAIL       = 0x2c,
-       UART_DRV_ENABLE      = 0x30,
-       UART_BRM_CR          = 0x34,
-       UART_RXFIFO_IRQLEVEL = 0x38,
-       UART_TXFIFO_IRQLEVEL = 0x3c,
-};
-
-#define SR_FE (1<<0)
-#define SR_PE (1<<1)
-#define SR_BE (1<<2)
-#define SR_OE (1<<3)
-
-#define LINE_CR_BRK       (1<<0)
-#define LINE_CR_PEN       (1<<1)
-#define LINE_CR_EPS       (1<<2)
-#define LINE_CR_STP2      (1<<3)
-#define LINE_CR_FEN       (1<<4)
-#define LINE_CR_5BIT      (0<<5)
-#define LINE_CR_6BIT      (1<<5)
-#define LINE_CR_7BIT      (2<<5)
-#define LINE_CR_8BIT      (3<<5)
-#define LINE_CR_BITS_MASK (3<<5)
-
-#define CR_UART_EN (1<<0)
-#define CR_SIREN   (1<<1)
-#define CR_SIRLP   (1<<2)
-#define CR_MSIE    (1<<3)
-#define CR_RIE     (1<<4)
-#define CR_TIE     (1<<5)
-#define CR_RTIE    (1<<6)
-#define CR_LBE     (1<<7)
-
-#define FR_CTS  (1<<0)
-#define FR_DSR  (1<<1)
-#define FR_DCD  (1<<2)
-#define FR_BUSY (1<<3)
-#define FR_RXFE (1<<4)
-#define FR_TXFF (1<<5)
-#define FR_RXFF (1<<6)
-#define FR_TXFE (1<<7)
-
-#define IIR_MIS (1<<0)
-#define IIR_RIS (1<<1)
-#define IIR_TIS (1<<2)
-#define IIR_RTIS (1<<3)
-#define IIR_MASK 0xf
-
-#define RTS_CR_AUTO (1<<0)
-#define RTS_CR_RTS  (1<<1)
-#define RTS_CR_COUNT (1<<2)
-#define RTS_CR_MOD2  (1<<3)
-#define RTS_CR_RTS_POL (1<<4)
-#define RTS_CR_CTS_CTR (1<<5)
-#define RTS_CR_CTS_POL (1<<6)
-#define RTS_CR_STICK   (1<<7)
-
-#define UART_PORT_SIZE 0x40
-#define DRIVER_NAME "netx-uart"
-
-struct netx_port {
-       struct uart_port        port;
-};
-
-static void netx_stop_tx(struct uart_port *port)
-{
-       unsigned int val;
-       val = readl(port->membase + UART_CR);
-       writel(val & ~CR_TIE,  port->membase + UART_CR);
-}
-
-static void netx_stop_rx(struct uart_port *port)
-{
-       unsigned int val;
-       val = readl(port->membase + UART_CR);
-       writel(val & ~CR_RIE,  port->membase + UART_CR);
-}
-
-static void netx_enable_ms(struct uart_port *port)
-{
-       unsigned int val;
-       val = readl(port->membase + UART_CR);
-       writel(val | CR_MSIE, port->membase + UART_CR);
-}
-
-static inline void netx_transmit_buffer(struct uart_port *port)
-{
-       struct circ_buf *xmit = &port->state->xmit;
-
-       if (port->x_char) {
-               writel(port->x_char, port->membase + UART_DR);
-               port->icount.tx++;
-               port->x_char = 0;
-               return;
-       }
-
-       if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
-               netx_stop_tx(port);
-               return;
-       }
-
-       do {
-               /* send xmit->buf[xmit->tail]
-                * out the port here */
-               writel(xmit->buf[xmit->tail], port->membase + UART_DR);
-               xmit->tail = (xmit->tail + 1) &
-                        (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (!(readl(port->membase + UART_FR) & FR_TXFF));
-
-       if (uart_circ_empty(xmit))
-               netx_stop_tx(port);
-}
-
-static void netx_start_tx(struct uart_port *port)
-{
-       writel(
-           readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR);
-
-       if (!(readl(port->membase + UART_FR) & FR_TXFF))
-               netx_transmit_buffer(port);
-}
-
-static unsigned int netx_tx_empty(struct uart_port *port)
-{
-       return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT;
-}
-
-static void netx_txint(struct uart_port *port)
-{
-       struct circ_buf *xmit = &port->state->xmit;
-
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               netx_stop_tx(port);
-               return;
-       }
-
-       netx_transmit_buffer(port);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
-}
-
-static void netx_rxint(struct uart_port *port, unsigned long *flags)
-{
-       unsigned char rx, flg, status;
-
-       while (!(readl(port->membase + UART_FR) & FR_RXFE)) {
-               rx = readl(port->membase + UART_DR);
-               flg = TTY_NORMAL;
-               port->icount.rx++;
-               status = readl(port->membase + UART_SR);
-               if (status & SR_BE) {
-                       writel(0, port->membase + UART_SR);
-                       if (uart_handle_break(port))
-                               continue;
-               }
-
-               if (unlikely(status & (SR_FE | SR_PE | SR_OE))) {
-
-                       if (status & SR_PE)
-                               port->icount.parity++;
-                       else if (status & SR_FE)
-                               port->icount.frame++;
-                       if (status & SR_OE)
-                               port->icount.overrun++;
-
-                       status &= port->read_status_mask;
-
-                       if (status & SR_BE)
-                               flg = TTY_BREAK;
-                       else if (status & SR_PE)
-                               flg = TTY_PARITY;
-                       else if (status & SR_FE)
-                               flg = TTY_FRAME;
-               }
-
-               if (uart_handle_sysrq_char(port, rx))
-                       continue;
-
-               uart_insert_char(port, status, SR_OE, rx, flg);
-       }
-
-       spin_unlock_irqrestore(&port->lock, *flags);
-       tty_flip_buffer_push(&port->state->port);
-       spin_lock_irqsave(&port->lock, *flags);
-}
-
-static irqreturn_t netx_int(int irq, void *dev_id)
-{
-       struct uart_port *port = dev_id;
-       unsigned long flags;
-       unsigned char status;
-
-       spin_lock_irqsave(&port->lock,flags);
-
-       status = readl(port->membase + UART_IIR) & IIR_MASK;
-       while (status) {
-               if (status & IIR_RIS)
-                       netx_rxint(port, &flags);
-               if (status & IIR_TIS)
-                       netx_txint(port);
-               if (status & IIR_MIS) {
-                       if (readl(port->membase + UART_FR) & FR_CTS)
-                               uart_handle_cts_change(port, 1);
-                       else
-                               uart_handle_cts_change(port, 0);
-               }
-               writel(0, port->membase + UART_IIR);
-               status = readl(port->membase + UART_IIR) & IIR_MASK;
-       }
-
-       spin_unlock_irqrestore(&port->lock,flags);
-       return IRQ_HANDLED;
-}
-
-static unsigned int netx_get_mctrl(struct uart_port *port)
-{
-       unsigned int ret = TIOCM_DSR | TIOCM_CAR;
-
-       if (readl(port->membase + UART_FR) & FR_CTS)
-               ret |= TIOCM_CTS;
-
-       return ret;
-}
-
-static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-       unsigned int val;
-
-       /* FIXME: Locking needed ? */
-       if (mctrl & TIOCM_RTS) {
-               val = readl(port->membase + UART_RTS_CR);
-               writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);
-       }
-}
-
-static void netx_break_ctl(struct uart_port *port, int break_state)
-{
-       unsigned int line_cr;
-       spin_lock_irq(&port->lock);
-
-       line_cr = readl(port->membase + UART_LINE_CR);
-       if (break_state != 0)
-               line_cr |= LINE_CR_BRK;
-       else
-               line_cr &= ~LINE_CR_BRK;
-       writel(line_cr, port->membase + UART_LINE_CR);
-
-       spin_unlock_irq(&port->lock);
-}
-
-static int netx_startup(struct uart_port *port)
-{
-       int ret;
-
-       ret = request_irq(port->irq, netx_int, 0,
-                            DRIVER_NAME, port);
-       if (ret) {
-               dev_err(port->dev, "unable to grab irq%d\n",port->irq);
-               goto exit;
-       }
-
-       writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN,
-               port->membase + UART_LINE_CR);
-
-       writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN,
-               port->membase + UART_CR);
-
-exit:
-       return ret;
-}
-
-static void netx_shutdown(struct uart_port *port)
-{
-       writel(0, port->membase + UART_CR) ;
-
-       free_irq(port->irq, port);
-}
-
-static void
-netx_set_termios(struct uart_port *port, struct ktermios *termios,
-                  struct ktermios *old)
-{
-       unsigned int baud, quot;
-       unsigned char old_cr;
-       unsigned char line_cr = LINE_CR_FEN;
-       unsigned char rts_cr = 0;
-
-       switch (termios->c_cflag & CSIZE) {
-       case CS5:
-               line_cr |= LINE_CR_5BIT;
-               break;
-       case CS6:
-               line_cr |= LINE_CR_6BIT;
-               break;
-       case CS7:
-               line_cr |= LINE_CR_7BIT;
-               break;
-       case CS8:
-               line_cr |= LINE_CR_8BIT;
-               break;
-       }
-
-       if (termios->c_cflag & CSTOPB)
-               line_cr |= LINE_CR_STP2;
-
-       if (termios->c_cflag & PARENB) {
-               line_cr |= LINE_CR_PEN;
-               if (!(termios->c_cflag & PARODD))
-                       line_cr |= LINE_CR_EPS;
-       }
-
-       if (termios->c_cflag & CRTSCTS)
-               rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL;
-
-       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-       quot = baud * 4096;
-       quot /= 1000;
-       quot *= 256;
-       quot /= 100000;
-
-       spin_lock_irq(&port->lock);
-
-       uart_update_timeout(port, termios->c_cflag, baud);
-
-       old_cr = readl(port->membase + UART_CR);
-
-       /* disable interrupts */
-       writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE),
-               port->membase + UART_CR);
-
-       /* drain transmitter */
-       while (readl(port->membase + UART_FR) & FR_BUSY);
-
-       /* disable UART */
-       writel(old_cr & ~CR_UART_EN, port->membase + UART_CR);
-
-       /* modem status interrupts */
-       old_cr &= ~CR_MSIE;
-       if (UART_ENABLE_MS(port, termios->c_cflag))
-               old_cr |= CR_MSIE;
-
-       writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB);
-       writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB);
-       writel(line_cr, port->membase + UART_LINE_CR);
-
-       writel(rts_cr, port->membase + UART_RTS_CR);
-
-       /*
-        * Characters to ignore
-        */
-       port->ignore_status_mask = 0;
-       if (termios->c_iflag & IGNPAR)
-               port->ignore_status_mask |= SR_PE;
-       if (termios->c_iflag & IGNBRK) {
-               port->ignore_status_mask |= SR_BE;
-               /*
-                * If we're ignoring parity and break indicators,
-                * ignore overruns too (for real raw support).
-                */
-               if (termios->c_iflag & IGNPAR)
-                       port->ignore_status_mask |= SR_PE;
-       }
-
-       port->read_status_mask = 0;
-       if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
-               port->read_status_mask |= SR_BE;
-       if (termios->c_iflag & INPCK)
-               port->read_status_mask |= SR_PE | SR_FE;
-
-       writel(old_cr, port->membase + UART_CR);
-
-       spin_unlock_irq(&port->lock);
-}
-
-static const char *netx_type(struct uart_port *port)
-{
-       return port->type == PORT_NETX ? "NETX" : NULL;
-}
-
-static void netx_release_port(struct uart_port *port)
-{
-       release_mem_region(port->mapbase, UART_PORT_SIZE);
-}
-
-static int netx_request_port(struct uart_port *port)
-{
-       return request_mem_region(port->mapbase, UART_PORT_SIZE,
-                       DRIVER_NAME) != NULL ? 0 : -EBUSY;
-}
-
-static void netx_config_port(struct uart_port *port, int flags)
-{
-       if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0)
-               port->type = PORT_NETX;
-}
-
-static int
-netx_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-       int ret = 0;
-
-       if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX)
-               ret = -EINVAL;
-
-       return ret;
-}
-
-static struct uart_ops netx_pops = {
-       .tx_empty       = netx_tx_empty,
-       .set_mctrl      = netx_set_mctrl,
-       .get_mctrl      = netx_get_mctrl,
-       .stop_tx        = netx_stop_tx,
-       .start_tx       = netx_start_tx,
-       .stop_rx        = netx_stop_rx,
-       .enable_ms      = netx_enable_ms,
-       .break_ctl      = netx_break_ctl,
-       .startup        = netx_startup,
-       .shutdown       = netx_shutdown,
-       .set_termios    = netx_set_termios,
-       .type           = netx_type,
-       .release_port   = netx_release_port,
-       .request_port   = netx_request_port,
-       .config_port    = netx_config_port,
-       .verify_port    = netx_verify_port,
-};
-
-static struct netx_port netx_ports[] = {
-       {
-       .port = {
-               .type = PORT_NETX,
-               .iotype = UPIO_MEM,
-               .membase = (char __iomem *)io_p2v(NETX_PA_UART0),
-               .mapbase = NETX_PA_UART0,
-               .irq = NETX_IRQ_UART0,
-               .uartclk = 100000000,
-               .fifosize = 16,
-               .flags = UPF_BOOT_AUTOCONF,
-               .ops = &netx_pops,
-               .line = 0,
-       },
-       }, {
-       .port = {
-               .type = PORT_NETX,
-               .iotype = UPIO_MEM,
-               .membase = (char __iomem *)io_p2v(NETX_PA_UART1),
-               .mapbase = NETX_PA_UART1,
-               .irq = NETX_IRQ_UART1,
-               .uartclk = 100000000,
-               .fifosize = 16,
-               .flags = UPF_BOOT_AUTOCONF,
-               .ops = &netx_pops,
-               .line = 1,
-       },
-       }, {
-       .port = {
-               .type = PORT_NETX,
-               .iotype = UPIO_MEM,
-               .membase = (char __iomem *)io_p2v(NETX_PA_UART2),
-               .mapbase = NETX_PA_UART2,
-               .irq = NETX_IRQ_UART2,
-               .uartclk = 100000000,
-               .fifosize = 16,
-               .flags = UPF_BOOT_AUTOCONF,
-               .ops = &netx_pops,
-               .line = 2,
-       },
-       }
-};
-
-#ifdef CONFIG_SERIAL_NETX_CONSOLE
-
-static void netx_console_putchar(struct uart_port *port, int ch)
-{
-       while (readl(port->membase + UART_FR) & FR_BUSY);
-       writel(ch, port->membase + UART_DR);
-}
-
-static void
-netx_console_write(struct console *co, const char *s, unsigned int count)
-{
-       struct uart_port *port = &netx_ports[co->index].port;
-       unsigned char cr_save;
-
-       cr_save = readl(port->membase + UART_CR);
-       writel(cr_save | CR_UART_EN, port->membase + UART_CR);
-
-       uart_console_write(port, s, count, netx_console_putchar);
-
-       while (readl(port->membase + UART_FR) & FR_BUSY);
-       writel(cr_save, port->membase + UART_CR);
-}
-
-static void __init
-netx_console_get_options(struct uart_port *port, int *baud,
-                       int *parity, int *bits, int *flow)
-{
-       unsigned char line_cr;
-
-       *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) |
-               readl(port->membase + UART_BAUDDIV_LSB);
-       *baud *= 1000;
-       *baud /= 4096;
-       *baud *= 1000;
-       *baud /= 256;
-       *baud *= 100;
-
-       line_cr = readl(port->membase + UART_LINE_CR);
-       *parity = 'n';
-       if (line_cr & LINE_CR_PEN) {
-               if (line_cr & LINE_CR_EPS)
-                       *parity = 'e';
-               else
-                       *parity = 'o';
-       }
-
-       switch (line_cr & LINE_CR_BITS_MASK) {
-       case LINE_CR_8BIT:
-               *bits = 8;
-               break;
-       case LINE_CR_7BIT:
-               *bits = 7;
-               break;
-       case LINE_CR_6BIT:
-               *bits = 6;
-               break;
-       case LINE_CR_5BIT:
-               *bits = 5;
-               break;
-       }
-
-       if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO)
-               *flow = 'r';
-}
-
-static int __init
-netx_console_setup(struct console *co, char *options)
-{
-       struct netx_port *sport;
-       int baud = 9600;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       /*
-        * Check whether an invalid uart number has been specified, and
-        * if so, search for the first available port that does have
-        * console support.
-        */
-       if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports))
-               co->index = 0;
-       sport = &netx_ports[co->index];
-
-       if (options) {
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-       } else {
-               /* if the UART is enabled, assume it has been correctly setup
-                * by the bootloader and get the options
-                */
-               if (readl(sport->port.membase + UART_CR) & CR_UART_EN) {
-                       netx_console_get_options(&sport->port, &baud,
-                       &parity, &bits, &flow);
-               }
-
-       }
-
-       return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver netx_reg;
-static struct console netx_console = {
-       .name           = "ttyNX",
-       .write          = netx_console_write,
-       .device         = uart_console_device,
-       .setup          = netx_console_setup,
-       .flags          = CON_PRINTBUFFER,
-       .index          = -1,
-       .data           = &netx_reg,
-};
-
-static int __init netx_console_init(void)
-{
-       register_console(&netx_console);
-       return 0;
-}
-console_initcall(netx_console_init);
-
-#define NETX_CONSOLE   &netx_console
-#else
-#define NETX_CONSOLE   NULL
-#endif
-
-static struct uart_driver netx_reg = {
-       .owner          = THIS_MODULE,
-       .driver_name    = DRIVER_NAME,
-       .dev_name       = "ttyNX",
-       .major          = SERIAL_NX_MAJOR,
-       .minor          = MINOR_START,
-       .nr             = ARRAY_SIZE(netx_ports),
-       .cons           = NETX_CONSOLE,
-};
-
-static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct netx_port *sport = platform_get_drvdata(pdev);
-
-       if (sport)
-               uart_suspend_port(&netx_reg, &sport->port);
-
-       return 0;
-}
-
-static int serial_netx_resume(struct platform_device *pdev)
-{
-       struct netx_port *sport = platform_get_drvdata(pdev);
-
-       if (sport)
-               uart_resume_port(&netx_reg, &sport->port);
-
-       return 0;
-}
-
-static int serial_netx_probe(struct platform_device *pdev)
-{
-       struct uart_port *port = &netx_ports[pdev->id].port;
-
-       dev_info(&pdev->dev, "initialising\n");
-
-       port->dev = &pdev->dev;
-
-       writel(1, port->membase + UART_RXFIFO_IRQLEVEL);
-       uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port);
-       platform_set_drvdata(pdev, &netx_ports[pdev->id]);
-
-       return 0;
-}
-
-static int serial_netx_remove(struct platform_device *pdev)
-{
-       struct netx_port *sport = platform_get_drvdata(pdev);
-
-       if (sport)
-               uart_remove_one_port(&netx_reg, &sport->port);
-
-       return 0;
-}
-
-static struct platform_driver serial_netx_driver = {
-       .probe          = serial_netx_probe,
-       .remove         = serial_netx_remove,
-
-       .suspend        = serial_netx_suspend,
-       .resume         = serial_netx_resume,
-
-       .driver         = {
-               .name   = DRIVER_NAME,
-       },
-};
-
-static int __init netx_serial_init(void)
-{
-       int ret;
-
-       printk(KERN_INFO "Serial: NetX driver\n");
-
-       ret = uart_register_driver(&netx_reg);
-       if (ret)
-               return ret;
-
-       ret = platform_driver_register(&serial_netx_driver);
-       if (ret != 0)
-               uart_unregister_driver(&netx_reg);
-
-       return 0;
-}
-
-static void __exit netx_serial_exit(void)
-{
-       platform_driver_unregister(&serial_netx_driver);
-       uart_unregister_driver(&netx_reg);
-}
-
-module_init(netx_serial_init);
-module_exit(netx_serial_exit);
-
-MODULE_AUTHOR("Sascha Hauer");
-MODULE_DESCRIPTION("NetX serial port driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
index 717292c1c0dfc352fc0e71d836fe900332ae09cd..60ff236a3d63df45bea93d32239e29e0ca8b80ec 100644 (file)
@@ -93,8 +93,7 @@ static void __ldsem_wake_readers(struct ld_semaphore *sem)
 
        list_for_each_entry_safe(waiter, next, &sem->read_wait, list) {
                tsk = waiter->task;
-               smp_mb();
-               waiter->task = NULL;
+               smp_store_release(&waiter->task, NULL);
                wake_up_process(tsk);
                put_task_struct(tsk);
        }
@@ -194,7 +193,7 @@ down_read_failed(struct ld_semaphore *sem, long count, long timeout)
        for (;;) {
                set_current_state(TASK_UNINTERRUPTIBLE);
 
-               if (!waiter.task)
+               if (!smp_load_acquire(&waiter.task))
                        break;
                if (!timeout)
                        break;
index ec92f36ab5c4eddf75be9fbca8866f3dec2a5aa9..34aa39d1aed9f4d8a3f5f4e31bf615b67cc6b505 100644 (file)
@@ -3771,7 +3771,11 @@ static ssize_t show_bind(struct device *dev, struct device_attribute *attr,
                         char *buf)
 {
        struct con_driver *con = dev_get_drvdata(dev);
-       int bind = con_is_bound(con->con);
+       int bind;
+
+       console_lock();
+       bind = con_is_bound(con->con);
+       console_unlock();
 
        return snprintf(buf, PAGE_SIZE, "%i\n", bind);
 }
index b5abfe89190cf28070d05c75bd3703b54d06a6b2..df8812c306407168b66ff2307ee172899d0e5492 100644 (file)
@@ -454,9 +454,11 @@ err_clk:
        imx_disable_unprepare_clks(dev);
 disable_hsic_regulator:
        if (data->hsic_pad_regulator)
-               ret = regulator_disable(data->hsic_pad_regulator);
+               /* don't overwrite original ret (cf. EPROBE_DEFER) */
+               regulator_disable(data->hsic_pad_regulator);
        if (pdata.flags & CI_HDRC_PMQOS)
                pm_qos_remove_request(&data->pm_qos_req);
+       data->ci_pdev = NULL;
        return ret;
 }
 
@@ -469,14 +471,17 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
                pm_runtime_disable(&pdev->dev);
                pm_runtime_put_noidle(&pdev->dev);
        }
-       ci_hdrc_remove_device(data->ci_pdev);
+       if (data->ci_pdev)
+               ci_hdrc_remove_device(data->ci_pdev);
        if (data->override_phy_control)
                usb_phy_shutdown(data->phy);
-       imx_disable_unprepare_clks(&pdev->dev);
-       if (data->plat_data->flags & CI_HDRC_PMQOS)
-               pm_qos_remove_request(&data->pm_qos_req);
-       if (data->hsic_pad_regulator)
-               regulator_disable(data->hsic_pad_regulator);
+       if (data->ci_pdev) {
+               imx_disable_unprepare_clks(&pdev->dev);
+               if (data->plat_data->flags & CI_HDRC_PMQOS)
+                       pm_qos_remove_request(&data->pm_qos_req);
+               if (data->hsic_pad_regulator)
+                       regulator_disable(data->hsic_pad_regulator);
+       }
 
        return 0;
 }
index 6a5ee8e6da10574ce9cb96e1bf082e8751a8aac7..67ad40b0a05b5bd6ff563e96e7ab8a0782c43807 100644 (file)
@@ -709,12 +709,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
        struct ci_hdrc    *ci = container_of(gadget, struct ci_hdrc, gadget);
        unsigned long flags;
 
-       spin_lock_irqsave(&ci->lock, flags);
-       ci->gadget.speed = USB_SPEED_UNKNOWN;
-       ci->remote_wakeup = 0;
-       ci->suspended = 0;
-       spin_unlock_irqrestore(&ci->lock, flags);
-
        /* flush all endpoints */
        gadget_for_each_ep(ep, gadget) {
                usb_ep_fifo_flush(ep);
@@ -732,6 +726,12 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
                ci->status = NULL;
        }
 
+       spin_lock_irqsave(&ci->lock, flags);
+       ci->gadget.speed = USB_SPEED_UNKNOWN;
+       ci->remote_wakeup = 0;
+       ci->suspended = 0;
+       spin_unlock_irqrestore(&ci->lock, flags);
+
        return 0;
 }
 
@@ -1303,6 +1303,10 @@ static int ep_disable(struct usb_ep *ep)
                return -EBUSY;
 
        spin_lock_irqsave(hwep->lock, flags);
+       if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+               spin_unlock_irqrestore(hwep->lock, flags);
+               return 0;
+       }
 
        /* only internal SW should disable ctrl endpts */
 
@@ -1392,6 +1396,10 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
                return -EINVAL;
 
        spin_lock_irqsave(hwep->lock, flags);
+       if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+               spin_unlock_irqrestore(hwep->lock, flags);
+               return 0;
+       }
        retval = _ep_queue(ep, req, gfp_flags);
        spin_unlock_irqrestore(hwep->lock, flags);
        return retval;
@@ -1415,8 +1423,8 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
                return -EINVAL;
 
        spin_lock_irqsave(hwep->lock, flags);
-
-       hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
+       if (hwep->ci->gadget.speed != USB_SPEED_UNKNOWN)
+               hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
 
        list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) {
                dma_pool_free(hwep->td_pool, node->ptr, node->dma);
@@ -1487,6 +1495,10 @@ static void ep_fifo_flush(struct usb_ep *ep)
        }
 
        spin_lock_irqsave(hwep->lock, flags);
+       if (hwep->ci->gadget.speed == USB_SPEED_UNKNOWN) {
+               spin_unlock_irqrestore(hwep->lock, flags);
+               return;
+       }
 
        hw_ep_flush(hwep->ci, hwep->num, hwep->dir);
 
@@ -1559,6 +1571,10 @@ static int ci_udc_wakeup(struct usb_gadget *_gadget)
        int ret = 0;
 
        spin_lock_irqsave(&ci->lock, flags);
+       if (ci->gadget.speed == USB_SPEED_UNKNOWN) {
+               spin_unlock_irqrestore(&ci->lock, flags);
+               return 0;
+       }
        if (!ci->remote_wakeup) {
                ret = -EOPNOTSUPP;
                goto out;
index 183b41753c98298236ea0690cd119e231d1ae5f3..62f4fb9b362f14533c86ba324588158517787019 100644 (file)
@@ -1301,10 +1301,6 @@ made_compressed_probe:
        tty_port_init(&acm->port);
        acm->port.ops = &acm_port_ops;
 
-       minor = acm_alloc_minor(acm);
-       if (minor < 0)
-               goto alloc_fail1;
-
        ctrlsize = usb_endpoint_maxp(epctrl);
        readsize = usb_endpoint_maxp(epread) *
                                (quirks == SINGLE_RX_URB ? 1 : 2);
@@ -1312,6 +1308,13 @@ made_compressed_probe:
        acm->writesize = usb_endpoint_maxp(epwrite) * 20;
        acm->control = control_interface;
        acm->data = data_interface;
+
+       usb_get_intf(acm->control); /* undone in destruct() */
+
+       minor = acm_alloc_minor(acm);
+       if (minor < 0)
+               goto alloc_fail1;
+
        acm->minor = minor;
        acm->dev = usb_dev;
        if (h.usb_cdc_acm_descriptor)
@@ -1458,7 +1461,6 @@ skip_countries:
        usb_driver_claim_interface(&acm_driver, data_interface, acm);
        usb_set_intfdata(data_interface, acm);
 
-       usb_get_intf(control_interface);
        tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
                        &control_interface->dev);
        if (IS_ERR(tty_dev)) {
index a7824a51f86d2ee99c2da3410d719f3a6be20235..70afb2ca1eabde070ff163ce7dd96fce5da93f71 100644 (file)
@@ -587,10 +587,20 @@ static int wdm_flush(struct file *file, fl_owner_t id)
 {
        struct wdm_device *desc = file->private_data;
 
-       wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags));
+       wait_event(desc->wait,
+                       /*
+                        * needs both flags. We cannot do with one
+                        * because resetting it would cause a race
+                        * with write() yet we need to signal
+                        * a disconnect
+                        */
+                       !test_bit(WDM_IN_USE, &desc->flags) ||
+                       test_bit(WDM_DISCONNECTING, &desc->flags));
 
        /* cannot dereference desc->intf if WDM_DISCONNECTING */
-       if (desc->werr < 0 && !test_bit(WDM_DISCONNECTING, &desc->flags))
+       if (test_bit(WDM_DISCONNECTING, &desc->flags))
+               return -ENODEV;
+       if (desc->werr < 0)
                dev_err(&desc->intf->dev, "Error in flush path: %d\n",
                        desc->werr);
 
@@ -974,8 +984,6 @@ static void wdm_disconnect(struct usb_interface *intf)
        spin_lock_irqsave(&desc->iuspin, flags);
        set_bit(WDM_DISCONNECTING, &desc->flags);
        set_bit(WDM_READ, &desc->flags);
-       /* to terminate pending flushes */
-       clear_bit(WDM_IN_USE, &desc->flags);
        spin_unlock_irqrestore(&desc->iuspin, flags);
        wake_up_all(&desc->wait);
        mutex_lock(&desc->rlock);
index 4942122b2346d4804f2279fa8eb033296e1dd25b..36858ddd8d9bb2d7b383c9672a9c2c64ee82ecc4 100644 (file)
@@ -2362,8 +2362,11 @@ static int usbtmc_probe(struct usb_interface *intf,
                goto err_put;
        }
 
+       retcode = -EINVAL;
        data->bulk_in = bulk_in->bEndpointAddress;
        data->wMaxPacketSize = usb_endpoint_maxp(bulk_in);
+       if (!data->wMaxPacketSize)
+               goto err_put;
        dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", data->bulk_in);
 
        data->bulk_out = bulk_out->bEndpointAddress;
index 1359b78a624e6b56dcbea6bcf19c3be1960b3848..6cf22c27f2d24e3eb74f631cd2adb07e8c685ce6 100644 (file)
@@ -66,9 +66,7 @@ int hcd_buffer_create(struct usb_hcd *hcd)
        char            name[16];
        int             i, size;
 
-       if (!IS_ENABLED(CONFIG_HAS_DMA) ||
-           (!is_device_dma_capable(hcd->self.sysdev) &&
-            !hcd->localmem_pool))
+       if (hcd->localmem_pool || !hcd_uses_dma(hcd))
                return 0;
 
        for (i = 0; i < HCD_BUFFER_POOLS; i++) {
@@ -129,8 +127,7 @@ void *hcd_buffer_alloc(
                return gen_pool_dma_alloc(hcd->localmem_pool, size, dma);
 
        /* some USB hosts just use PIO */
-       if (!IS_ENABLED(CONFIG_HAS_DMA) ||
-           !is_device_dma_capable(bus->sysdev)) {
+       if (!hcd_uses_dma(hcd)) {
                *dma = ~(dma_addr_t) 0;
                return kmalloc(size, mem_flags);
        }
@@ -160,8 +157,7 @@ void hcd_buffer_free(
                return;
        }
 
-       if (!IS_ENABLED(CONFIG_HAS_DMA) ||
-           !is_device_dma_capable(bus->sysdev)) {
+       if (!hcd_uses_dma(hcd)) {
                kfree(addr);
                return;
        }
index b265ab5405f9ae4b20a49945fc60c787751771fc..9063ede411ae73e9ceffe7430ad578f6c7283878 100644 (file)
@@ -1812,8 +1812,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
        return 0;
 
  error:
-       if (as && as->usbm)
-               dec_usb_memory_use_count(as->usbm, &as->usbm->urb_use_count);
        kfree(isopkt);
        kfree(dr);
        if (as)
index 65de6f73b6725200d8ec5cb2301b7a557cdf8a9c..558890ada0e5bdcf8c573af0cc5be59c52c99ef1 100644 (file)
@@ -193,9 +193,10 @@ int usb_register_dev(struct usb_interface *intf,
                intf->minor = minor;
                break;
        }
-       up_write(&minor_rwsem);
-       if (intf->minor < 0)
+       if (intf->minor < 0) {
+               up_write(&minor_rwsem);
                return -EXFULL;
+       }
 
        /* create a usb class device for this usb interface */
        snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
@@ -203,12 +204,11 @@ int usb_register_dev(struct usb_interface *intf,
                                      MKDEV(USB_MAJOR, minor), class_driver,
                                      "%s", kbasename(name));
        if (IS_ERR(intf->usb_dev)) {
-               down_write(&minor_rwsem);
                usb_minors[minor] = NULL;
                intf->minor = -1;
-               up_write(&minor_rwsem);
                retval = PTR_ERR(intf->usb_dev);
        }
+       up_write(&minor_rwsem);
        return retval;
 }
 EXPORT_SYMBOL_GPL(usb_register_dev);
@@ -234,12 +234,12 @@ void usb_deregister_dev(struct usb_interface *intf,
                return;
 
        dev_dbg(&intf->dev, "removing %d minor\n", intf->minor);
+       device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
 
        down_write(&minor_rwsem);
        usb_minors[intf->minor] = NULL;
        up_write(&minor_rwsem);
 
-       device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
        intf->usb_dev = NULL;
        intf->minor = -1;
        destroy_usb_class();
index 03432467b05fb12810d7cac77d954a11ed0a002a..7537681355f6799c00b73fa6062565257e37d8e3 100644 (file)
@@ -216,17 +216,18 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                /* EHCI, OHCI */
                hcd->rsrc_start = pci_resource_start(dev, 0);
                hcd->rsrc_len = pci_resource_len(dev, 0);
-               if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-                               driver->description)) {
+               if (!devm_request_mem_region(&dev->dev, hcd->rsrc_start,
+                               hcd->rsrc_len, driver->description)) {
                        dev_dbg(&dev->dev, "controller already in use\n");
                        retval = -EBUSY;
                        goto put_hcd;
                }
-               hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+               hcd->regs = devm_ioremap_nocache(&dev->dev, hcd->rsrc_start,
+                               hcd->rsrc_len);
                if (hcd->regs == NULL) {
                        dev_dbg(&dev->dev, "error mapping memory\n");
                        retval = -EFAULT;
-                       goto release_mem_region;
+                       goto put_hcd;
                }
 
        } else {
@@ -240,8 +241,8 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
                        hcd->rsrc_start = pci_resource_start(dev, region);
                        hcd->rsrc_len = pci_resource_len(dev, region);
-                       if (request_region(hcd->rsrc_start, hcd->rsrc_len,
-                                       driver->description))
+                       if (devm_request_region(&dev->dev, hcd->rsrc_start,
+                                       hcd->rsrc_len, driver->description))
                                break;
                }
                if (region == PCI_ROM_RESOURCE) {
@@ -275,20 +276,13 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        }
 
        if (retval != 0)
-               goto unmap_registers;
+               goto put_hcd;
        device_wakeup_enable(hcd->self.controller);
 
        if (pci_dev_run_wake(dev))
                pm_runtime_put_noidle(&dev->dev);
        return retval;
 
-unmap_registers:
-       if (driver->flags & HCD_MEMORY) {
-               iounmap(hcd->regs);
-release_mem_region:
-               release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       } else
-               release_region(hcd->rsrc_start, hcd->rsrc_len);
 put_hcd:
        usb_put_hcd(hcd);
 disable_pci:
@@ -347,14 +341,6 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
                dev_set_drvdata(&dev->dev, NULL);
                up_read(&companions_rwsem);
        }
-
-       if (hcd->driver->flags & HCD_MEMORY) {
-               iounmap(hcd->regs);
-               release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       } else {
-               release_region(hcd->rsrc_start, hcd->rsrc_len);
-       }
-
        usb_put_hcd(hcd);
        pci_disable_device(dev);
 }
index 88533938ce19512aa5cdeaa2469721b39560d063..8592c0344fe81f1458cacf1eaf55bfa516049121 100644 (file)
@@ -103,11 +103,6 @@ static DEFINE_SPINLOCK(hcd_urb_unlink_lock);
 /* wait queue for synchronous unlinks */
 DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
 
-static inline int is_root_hub(struct usb_device *udev)
-{
-       return (udev->parent == NULL);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -880,101 +875,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 }
 
 
-
-/*
- * Show & store the current value of authorized_default
- */
-static ssize_t authorized_default_show(struct device *dev,
-                                      struct device_attribute *attr, char *buf)
-{
-       struct usb_device *rh_usb_dev = to_usb_device(dev);
-       struct usb_bus *usb_bus = rh_usb_dev->bus;
-       struct usb_hcd *hcd;
-
-       hcd = bus_to_hcd(usb_bus);
-       return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
-}
-
-static ssize_t authorized_default_store(struct device *dev,
-                                       struct device_attribute *attr,
-                                       const char *buf, size_t size)
-{
-       ssize_t result;
-       unsigned val;
-       struct usb_device *rh_usb_dev = to_usb_device(dev);
-       struct usb_bus *usb_bus = rh_usb_dev->bus;
-       struct usb_hcd *hcd;
-
-       hcd = bus_to_hcd(usb_bus);
-       result = sscanf(buf, "%u\n", &val);
-       if (result == 1) {
-               hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
-                       val : USB_DEVICE_AUTHORIZE_ALL;
-               result = size;
-       } else {
-               result = -EINVAL;
-       }
-       return result;
-}
-static DEVICE_ATTR_RW(authorized_default);
-
-/*
- * interface_authorized_default_show - show default authorization status
- * for USB interfaces
- *
- * note: interface_authorized_default is the default value
- *       for initializing the authorized attribute of interfaces
- */
-static ssize_t interface_authorized_default_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct usb_device *usb_dev = to_usb_device(dev);
-       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
-
-       return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
-}
-
-/*
- * interface_authorized_default_store - store default authorization status
- * for USB interfaces
- *
- * note: interface_authorized_default is the default value
- *       for initializing the authorized attribute of interfaces
- */
-static ssize_t interface_authorized_default_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct usb_device *usb_dev = to_usb_device(dev);
-       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
-       int rc = count;
-       bool val;
-
-       if (strtobool(buf, &val) != 0)
-               return -EINVAL;
-
-       if (val)
-               set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
-       else
-               clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
-
-       return rc;
-}
-static DEVICE_ATTR_RW(interface_authorized_default);
-
-/* Group all the USB bus attributes */
-static struct attribute *usb_bus_attrs[] = {
-               &dev_attr_authorized_default.attr,
-               &dev_attr_interface_authorized_default.attr,
-               NULL,
-};
-
-static const struct attribute_group usb_bus_attr_group = {
-       .name = NULL,   /* we want them in the same directory */
-       .attrs = usb_bus_attrs,
-};
-
-
-
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -1512,7 +1412,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
        if (usb_endpoint_xfer_control(&urb->ep->desc)) {
                if (hcd->self.uses_pio_for_control)
                        return ret;
-               if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) {
+               if (hcd_uses_dma(hcd)) {
                        if (is_vmalloc_addr(urb->setup_packet)) {
                                WARN_ONCE(1, "setup packet is not dma capable\n");
                                return -EAGAIN;
@@ -1546,7 +1446,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
        dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
        if (urb->transfer_buffer_length != 0
            && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
-               if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) {
+               if (hcd_uses_dma(hcd)) {
                        if (urb->num_sgs) {
                                int n;
 
@@ -2894,32 +2794,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
        if (retval != 0)
                goto err_register_root_hub;
 
-       retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
-       if (retval < 0) {
-               printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
-                      retval);
-               goto error_create_attr_group;
-       }
        if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
                usb_hcd_poll_rh_status(hcd);
 
        return retval;
 
-error_create_attr_group:
-       clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
-       if (HC_IS_RUNNING(hcd->state))
-               hcd->state = HC_STATE_QUIESCING;
-       spin_lock_irq(&hcd_root_hub_lock);
-       hcd->rh_registered = 0;
-       spin_unlock_irq(&hcd_root_hub_lock);
-
-#ifdef CONFIG_PM
-       cancel_work_sync(&hcd->wakeup_work);
-#endif
-       cancel_work_sync(&hcd->died_work);
-       mutex_lock(&usb_bus_idr_lock);
-       usb_disconnect(&rhdev);         /* Sets rhdev to NULL */
-       mutex_unlock(&usb_bus_idr_lock);
 err_register_root_hub:
        hcd->rh_pollable = 0;
        clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
@@ -2963,8 +2842,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
        dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
 
        usb_get_dev(rhdev);
-       sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
-
        clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
        if (HC_IS_RUNNING (hcd->state))
                hcd->state = HC_STATE_QUIESCING;
@@ -3052,8 +2929,8 @@ int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr,
 
        local_mem = devm_memremap(hcd->self.sysdev, phys_addr,
                                  size, MEMREMAP_WC);
-       if (!local_mem)
-               return -ENOMEM;
+       if (IS_ERR(local_mem))
+               return PTR_ERR(local_mem);
 
        /*
         * Here we pass a dma_addr_t but the arg type is a phys_addr_t.
index e844bb7b5676a4525724d25883231af474cdd8e0..5adf489428aad5dd422121678fc86a3b2da8c71e 100644 (file)
@@ -2218,14 +2218,14 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
                                (struct usb_cdc_dmm_desc *)buffer;
                        break;
                case USB_CDC_MDLM_TYPE:
-                       if (elength < sizeof(struct usb_cdc_mdlm_desc *))
+                       if (elength < sizeof(struct usb_cdc_mdlm_desc))
                                goto next_desc;
                        if (desc)
                                return -EINVAL;
                        desc = (struct usb_cdc_mdlm_desc *)buffer;
                        break;
                case USB_CDC_MDLM_DETAIL_TYPE:
-                       if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *))
+                       if (elength < sizeof(struct usb_cdc_mdlm_detail_desc))
                                goto next_desc;
                        if (detail)
                                return -EINVAL;
index 7e88fdfe3cf5c7c23ba7e9878904a8e72db7686c..f19694e69f5c3eda9f58ba317a81b43096d8228d 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/usb.h>
+#include <linux/usb/hcd.h>
 #include <linux/usb/quirks.h>
 #include <linux/of.h>
 #include "usb.h"
@@ -922,6 +923,116 @@ static struct bin_attribute dev_bin_attr_descriptors = {
        .size = 18 + 65535,     /* dev descr + max-size raw descriptor */
 };
 
+/*
+ * Show & store the current value of authorized_default
+ */
+static ssize_t authorized_default_show(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
+{
+       struct usb_device *rh_usb_dev = to_usb_device(dev);
+       struct usb_bus *usb_bus = rh_usb_dev->bus;
+       struct usb_hcd *hcd;
+
+       hcd = bus_to_hcd(usb_bus);
+       return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
+}
+
+static ssize_t authorized_default_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t size)
+{
+       ssize_t result;
+       unsigned int val;
+       struct usb_device *rh_usb_dev = to_usb_device(dev);
+       struct usb_bus *usb_bus = rh_usb_dev->bus;
+       struct usb_hcd *hcd;
+
+       hcd = bus_to_hcd(usb_bus);
+       result = sscanf(buf, "%u\n", &val);
+       if (result == 1) {
+               hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
+                       val : USB_DEVICE_AUTHORIZE_ALL;
+               result = size;
+       } else {
+               result = -EINVAL;
+       }
+       return result;
+}
+static DEVICE_ATTR_RW(authorized_default);
+
+/*
+ * interface_authorized_default_show - show default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ *       for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct usb_device *usb_dev = to_usb_device(dev);
+       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+
+       return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
+}
+
+/*
+ * interface_authorized_default_store - store default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ *       for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct usb_device *usb_dev = to_usb_device(dev);
+       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+       int rc = count;
+       bool val;
+
+       if (strtobool(buf, &val) != 0)
+               return -EINVAL;
+
+       if (val)
+               set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+       else
+               clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+
+       return rc;
+}
+static DEVICE_ATTR_RW(interface_authorized_default);
+
+/* Group all the USB bus attributes */
+static struct attribute *usb_bus_attrs[] = {
+               &dev_attr_authorized_default.attr,
+               &dev_attr_interface_authorized_default.attr,
+               NULL,
+};
+
+static const struct attribute_group usb_bus_attr_group = {
+       .name = NULL,   /* we want them in the same directory */
+       .attrs = usb_bus_attrs,
+};
+
+
+static int add_default_authorized_attributes(struct device *dev)
+{
+       int rc = 0;
+
+       if (is_usb_device(dev))
+               rc = sysfs_create_group(&dev->kobj, &usb_bus_attr_group);
+
+       return rc;
+}
+
+static void remove_default_authorized_attributes(struct device *dev)
+{
+       if (is_usb_device(dev)) {
+               sysfs_remove_group(&dev->kobj, &usb_bus_attr_group);
+       }
+}
+
 int usb_create_sysfs_dev_files(struct usb_device *udev)
 {
        struct device *dev = &udev->dev;
@@ -938,7 +1049,14 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
        retval = add_power_attributes(dev);
        if (retval)
                goto error;
+
+       if (is_root_hub(udev)) {
+               retval = add_default_authorized_attributes(dev);
+               if (retval)
+                       goto error;
+       }
        return retval;
+
 error:
        usb_remove_sysfs_dev_files(udev);
        return retval;
@@ -948,6 +1066,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
 {
        struct device *dev = &udev->dev;
 
+       if (is_root_hub(udev))
+               remove_default_authorized_attributes(dev);
+
        remove_power_attributes(dev);
        remove_persist_attributes(dev);
        device_remove_bin_file(dev, &dev_bin_attr_descriptors);
index bd8d01f85a1371dffa8f32e522ecaa4ae5e8e23e..0c9fde5ad0524b50f1789803dbd00fa8adec4713 100644 (file)
@@ -153,6 +153,11 @@ static inline int is_usb_port(const struct device *dev)
        return dev->type == &usb_port_device_type;
 }
 
+static inline int is_root_hub(struct usb_device *udev)
+{
+       return (udev->parent == NULL);
+}
+
 /* Do the same for device drivers and interface drivers. */
 
 static inline int is_usb_device_driver(struct device_driver *drv)
index ee144ff8af5b1195f08ce0466d0586231f3d0dd3..111787a137eead0bd65e554bc2a9705ad39dbcc9 100644 (file)
@@ -4608,7 +4608,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 
        buf = urb->transfer_buffer;
 
-       if (hcd->self.uses_dma) {
+       if (hcd_uses_dma(hcd)) {
                if (!buf && (urb->transfer_dma & 3)) {
                        dev_err(hsotg->dev,
                                "%s: unaligned transfer with no transfer_buffer",
index 9118b42c70b6312659eafd76f72b97434147ac2c..76883ff4f5bb6f7c4a157716c76354a01f20afc0 100644 (file)
@@ -1976,6 +1976,7 @@ void composite_disconnect(struct usb_gadget *gadget)
         * disconnect callbacks?
         */
        spin_lock_irqsave(&cdev->lock, flags);
+       cdev->suspended = 0;
        if (cdev->config)
                reset_config(cdev);
        if (cdev->driver->disconnect)
index 29cc5693e05cc55dafbd7c00cc57b8476c7cbc41..7c96c4665178e4c60ccc66f7153b29b1d1f4316d 100644 (file)
@@ -261,7 +261,7 @@ struct fsg_common;
 struct fsg_common {
        struct usb_gadget       *gadget;
        struct usb_composite_dev *cdev;
-       struct fsg_dev          *fsg, *new_fsg;
+       struct fsg_dev          *fsg;
        wait_queue_head_t       io_wait;
        wait_queue_head_t       fsg_wait;
 
@@ -290,6 +290,7 @@ struct fsg_common {
        unsigned int            bulk_out_maxpacket;
        enum fsg_state          state;          /* For exception handling */
        unsigned int            exception_req_tag;
+       void                    *exception_arg;
 
        enum data_direction     data_dir;
        u32                     data_size;
@@ -391,7 +392,8 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
 
 /* These routines may be called in process context or in_irq */
 
-static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
+static void __raise_exception(struct fsg_common *common, enum fsg_state new_state,
+                             void *arg)
 {
        unsigned long           flags;
 
@@ -404,6 +406,7 @@ static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
        if (common->state <= new_state) {
                common->exception_req_tag = common->ep0_req_tag;
                common->state = new_state;
+               common->exception_arg = arg;
                if (common->thread_task)
                        send_sig_info(SIGUSR1, SEND_SIG_PRIV,
                                      common->thread_task);
@@ -411,6 +414,10 @@ static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
        spin_unlock_irqrestore(&common->lock, flags);
 }
 
+static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
+{
+       __raise_exception(common, new_state, NULL);
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -2285,16 +2292,16 @@ reset:
 static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
-       fsg->common->new_fsg = fsg;
-       raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+
+       __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, fsg);
        return USB_GADGET_DELAYED_STATUS;
 }
 
 static void fsg_disable(struct usb_function *f)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
-       fsg->common->new_fsg = NULL;
-       raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+
+       __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, NULL);
 }
 
 
@@ -2307,6 +2314,7 @@ static void handle_exception(struct fsg_common *common)
        enum fsg_state          old_state;
        struct fsg_lun          *curlun;
        unsigned int            exception_req_tag;
+       struct fsg_dev          *new_fsg;
 
        /*
         * Clear the existing signals.  Anything but SIGUSR1 is converted
@@ -2360,6 +2368,7 @@ static void handle_exception(struct fsg_common *common)
        common->next_buffhd_to_fill = &common->buffhds[0];
        common->next_buffhd_to_drain = &common->buffhds[0];
        exception_req_tag = common->exception_req_tag;
+       new_fsg = common->exception_arg;
        old_state = common->state;
        common->state = FSG_STATE_NORMAL;
 
@@ -2413,8 +2422,8 @@ static void handle_exception(struct fsg_common *common)
                break;
 
        case FSG_STATE_CONFIG_CHANGE:
-               do_set_interface(common, common->new_fsg);
-               if (common->new_fsg)
+               do_set_interface(common, new_fsg);
+               if (new_fsg)
                        usb_composite_setup_continue(common->cdev);
                break;
 
@@ -2989,8 +2998,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
 
        DBG(fsg, "unbind\n");
        if (fsg->common->fsg == fsg) {
-               fsg->common->new_fsg = NULL;
-               raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+               __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, NULL);
                /* FIXME: make interruptible or killable somehow? */
                wait_event(common->fsg_wait, common->fsg != fsg);
        }
index 5f1b14f3e5a07ba0282cbf0ec56535e1aef95608..bb6af6b5ac975ac54d2ecaf71704e8269a62faf4 100644 (file)
@@ -2265,7 +2265,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
                default:
                        break;
                }
-
+               break;
 
        case USB_REQ_SET_ADDRESS:
                if (reqtype == (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) {
index 87062d22134da38d22dce196f28461ce22d4a0da..1f4c3fbd1df8b37d1d2f8cd82470171be2ae9985 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/sys_soc.h>
 #include <linux/uaccess.h>
 #include <linux/usb/ch9.h>
@@ -2450,9 +2451,9 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
        if (usb3->forced_b_device)
                return -EBUSY;
 
-       if (!strncmp(buf, "host", strlen("host")))
+       if (sysfs_streq(buf, "host"))
                new_mode_is_host = true;
-       else if (!strncmp(buf, "peripheral", strlen("peripheral")))
+       else if (sysfs_streq(buf, "peripheral"))
                new_mode_is_host = false;
        else
                return -EINVAL;
index fe9422d3bcdc4cbb3263bd9b15449785ef4626ac..b0882c13a1d168498e1a15a47b37e3a01842e4a8 100644 (file)
@@ -149,7 +149,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                break;
        case PCI_VENDOR_ID_AMD:
                /* AMD PLL quirk */
-               if (usb_amd_find_chipset_info())
+               if (usb_amd_quirk_pll_check())
                        ehci->amd_pll_fix = 1;
                /* AMD8111 EHCI doesn't work, according to AMD errata */
                if (pdev->device == 0x7463) {
@@ -186,7 +186,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                break;
        case PCI_VENDOR_ID_ATI:
                /* AMD PLL quirk */
-               if (usb_amd_find_chipset_info())
+               if (usb_amd_quirk_pll_check())
                        ehci->amd_pll_fix = 1;
 
                /*
index 77cc36efae9500ea94f7109f5d7abed19812275a..0dbfa5c107035df3e0158a1af07a271c600a2df6 100644 (file)
@@ -1629,6 +1629,10 @@ static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        /* see what we found out */
                        temp = check_reset_complete(fotg210, wIndex, status_reg,
                                        fotg210_readl(fotg210, status_reg));
+
+                       /* restart schedule */
+                       fotg210->command |= CMD_RUN;
+                       fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
                }
 
                if (!(temp & (PORT_RESUME|PORT_RESET))) {
index 09a8ebd955888d6d375d7cee3d0fc53fd1cf0d9c..6968b9f2b76b5865bd70e7366b2701f6b2c50f6f 100644 (file)
@@ -159,7 +159,7 @@ out:
        return result;
 
 error_set_cluster_id:
-       wusb_cluster_id_put(wusbhc->cluster_id);
+       wusb_cluster_id_put(addr);
 error_cluster_id_get:
        goto out;
 
index b457fdaff29746a0e70794b06308289290b2baf9..1fe3deec35cf5495360f11bdc6a451f03abd650e 100644 (file)
@@ -419,8 +419,7 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
  * other cases where the next software may expect clean state from the
  * "firmware".  this is bus-neutral, unlike shutdown() methods.
  */
-static void
-ohci_shutdown (struct usb_hcd *hcd)
+static void _ohci_shutdown(struct usb_hcd *hcd)
 {
        struct ohci_hcd *ohci;
 
@@ -436,6 +435,16 @@ ohci_shutdown (struct usb_hcd *hcd)
        ohci->rh_state = OHCI_RH_HALTED;
 }
 
+static void ohci_shutdown(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ohci->lock, flags);
+       _ohci_shutdown(hcd);
+       spin_unlock_irqrestore(&ohci->lock, flags);
+}
+
 /*-------------------------------------------------------------------------*
  * HC functions
  *-------------------------------------------------------------------------*/
@@ -760,7 +769,7 @@ static void io_watchdog_func(struct timer_list *t)
  died:
                        usb_hc_died(ohci_to_hcd(ohci));
                        ohci_dump(ohci);
-                       ohci_shutdown(ohci_to_hcd(ohci));
+                       _ohci_shutdown(ohci_to_hcd(ohci));
                        goto done;
                } else {
                        /* No write back because the done queue was empty */
index a033f7d855e06eb6c38658ce0329b309f81abbf7..f4e13a3fddee11a4b62acf38265807493012d39d 100644 (file)
@@ -152,7 +152,7 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
 {
        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 
-       if (usb_amd_find_chipset_info())
+       if (usb_amd_quirk_pll_check())
                ohci->flags |= OHCI_QUIRK_AMD_PLL;
 
        /* SB800 needs pre-fetch fix */
index 3ce71cbfbb586abe275284d347b25447e375e2e6..f6d04491df608464b02894cb175acafbdcc0b423 100644 (file)
@@ -132,7 +132,7 @@ static struct amd_chipset_info {
        struct amd_chipset_type sb_type;
        int isoc_reqs;
        int probe_count;
-       int probe_result;
+       bool need_pll_quirk;
 } amd_chipset;
 
 static DEFINE_SPINLOCK(amd_lock);
@@ -201,11 +201,11 @@ void sb800_prefetch(struct device *dev, int on)
 }
 EXPORT_SYMBOL_GPL(sb800_prefetch);
 
-int usb_amd_find_chipset_info(void)
+static void usb_amd_find_chipset_info(void)
 {
        unsigned long flags;
        struct amd_chipset_info info;
-       int ret;
+       info.need_pll_quirk = 0;
 
        spin_lock_irqsave(&amd_lock, flags);
 
@@ -213,27 +213,34 @@ int usb_amd_find_chipset_info(void)
        if (amd_chipset.probe_count > 0) {
                amd_chipset.probe_count++;
                spin_unlock_irqrestore(&amd_lock, flags);
-               return amd_chipset.probe_result;
+               return;
        }
        memset(&info, 0, sizeof(info));
        spin_unlock_irqrestore(&amd_lock, flags);
 
        if (!amd_chipset_sb_type_init(&info)) {
-               ret = 0;
                goto commit;
        }
 
-       /* Below chipset generations needn't enable AMD PLL quirk */
-       if (info.sb_type.gen == AMD_CHIPSET_UNKNOWN ||
-                       info.sb_type.gen == AMD_CHIPSET_SB600 ||
-                       info.sb_type.gen == AMD_CHIPSET_YANGTZE ||
-                       (info.sb_type.gen == AMD_CHIPSET_SB700 &&
-                       info.sb_type.rev > 0x3b)) {
+       switch (info.sb_type.gen) {
+       case AMD_CHIPSET_SB700:
+               info.need_pll_quirk = info.sb_type.rev <= 0x3B;
+               break;
+       case AMD_CHIPSET_SB800:
+       case AMD_CHIPSET_HUDSON2:
+       case AMD_CHIPSET_BOLTON:
+               info.need_pll_quirk = 1;
+               break;
+       default:
+               info.need_pll_quirk = 0;
+               break;
+       }
+
+       if (!info.need_pll_quirk) {
                if (info.smbus_dev) {
                        pci_dev_put(info.smbus_dev);
                        info.smbus_dev = NULL;
                }
-               ret = 0;
                goto commit;
        }
 
@@ -252,7 +259,6 @@ int usb_amd_find_chipset_info(void)
                }
        }
 
-       ret = info.probe_result = 1;
        printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n");
 
 commit:
@@ -263,7 +269,6 @@ commit:
 
                /* Mark that we where here */
                amd_chipset.probe_count++;
-               ret = amd_chipset.probe_result;
 
                spin_unlock_irqrestore(&amd_lock, flags);
 
@@ -276,10 +281,7 @@ commit:
                amd_chipset = info;
                spin_unlock_irqrestore(&amd_lock, flags);
        }
-
-       return ret;
 }
-EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
 
 int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev)
 {
@@ -315,6 +317,13 @@ bool usb_amd_prefetch_quirk(void)
 }
 EXPORT_SYMBOL_GPL(usb_amd_prefetch_quirk);
 
+bool usb_amd_quirk_pll_check(void)
+{
+       usb_amd_find_chipset_info();
+       return amd_chipset.need_pll_quirk;
+}
+EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_check);
+
 /*
  * The hardware normally enables the A-link power management feature, which
  * lets the system lower the power consumption in idle states.
@@ -520,7 +529,7 @@ void usb_amd_dev_put(void)
        amd_chipset.nb_type = 0;
        memset(&amd_chipset.sb_type, 0, sizeof(amd_chipset.sb_type));
        amd_chipset.isoc_reqs = 0;
-       amd_chipset.probe_result = 0;
+       amd_chipset.need_pll_quirk = 0;
 
        spin_unlock_irqrestore(&amd_lock, flags);
 
index 63c633077d9ebcd930232effe2298722005c420f..e729de21fad7aacfcef9ce70bc94cf961f3ae46f 100644 (file)
@@ -5,11 +5,11 @@
 #ifdef CONFIG_USB_PCI
 void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
 int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
-int usb_amd_find_chipset_info(void);
 int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev);
 bool usb_amd_hang_symptom_quirk(void);
 bool usb_amd_prefetch_quirk(void);
 void usb_amd_dev_put(void);
+bool usb_amd_quirk_pll_check(void);
 void usb_amd_quirk_pll_disable(void);
 void usb_amd_quirk_pll_enable(void);
 void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
index c2fe218e051f04431b1413760626f4e012adc097..1e0236e906879edec2a72fa0c98d490bcc4faee7 100644 (file)
@@ -130,7 +130,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                xhci->quirks |= XHCI_AMD_0x96_HOST;
 
        /* AMD PLL quirk */
-       if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
+       if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_quirk_pll_check())
                xhci->quirks |= XHCI_AMD_PLL_FIX;
 
        if (pdev->vendor == PCI_VENDOR_ID_AMD &&
index 671bce18782c5a788ad1af896ab9066fd4078839..2b0ccd150209fe3a1f55bb73d29a965fe1cd6f26 100644 (file)
@@ -104,7 +104,7 @@ static int xhci_rcar_is_gen2(struct device *dev)
        return of_device_is_compatible(node, "renesas,xhci-r8a7790") ||
                of_device_is_compatible(node, "renesas,xhci-r8a7791") ||
                of_device_is_compatible(node, "renesas,xhci-r8a7793") ||
-               of_device_is_compatible(node, "renensas,rcar-gen2-xhci");
+               of_device_is_compatible(node, "renesas,rcar-gen2-xhci");
 }
 
 static int xhci_rcar_is_gen3(struct device *dev)
@@ -238,10 +238,15 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)
         * pointers. So, this driver clears the AC64 bit of xhci->hcc_params
         * to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in
         * xhci_gen_setup().
+        *
+        * And, since the firmware/internal CPU control the USBSTS.STS_HALT
+        * and the process speed is down when the roothub port enters U3,
+        * long delay for the handshake of STS_HALT is neeed in xhci_suspend().
         */
        if (xhci_rcar_is_gen2(hcd->self.controller) ||
-                       xhci_rcar_is_gen3(hcd->self.controller))
-               xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
+                       xhci_rcar_is_gen3(hcd->self.controller)) {
+               xhci->quirks |= XHCI_NO_64BIT_SUPPORT | XHCI_SLOW_SUSPEND;
+       }
 
        if (!xhci_rcar_wait_for_pll_active(hcd))
                return -ETIMEDOUT;
index dafc65911fc02625ae49be7197cc6e164fc874f3..2ff7c911fbd0d694f8c937f36418bf0949676fd3 100644 (file)
@@ -1194,6 +1194,16 @@ static int tegra_xusb_probe(struct platform_device *pdev)
 
        tegra_xusb_config(tegra, regs);
 
+       /*
+        * The XUSB Falcon microcontroller can only address 40 bits, so set
+        * the DMA mask accordingly.
+        */
+       err = dma_set_mask_and_coherent(tegra->dev, DMA_BIT_MASK(40));
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
+               goto put_rpm;
+       }
+
        err = tegra_xusb_load_firmware(tegra);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to load firmware: %d\n", err);
index 248cd7a8b163b60044ea390d75bfc2544c813aa0..03d1e552769bf9d1a7471e8c17d36765eb0225f6 100644 (file)
@@ -3089,8 +3089,18 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
                return;
        udev = (struct usb_device *) host_ep->hcpriv;
        vdev = xhci->devs[udev->slot_id];
+
+       /*
+        * vdev may be lost due to xHC restore error and re-initialization
+        * during S3/S4 resume. A new vdev will be allocated later by
+        * xhci_discover_or_reset_device()
+        */
+       if (!udev->slot_id || !vdev)
+               return;
        ep_index = xhci_get_endpoint_index(&host_ep->desc);
        ep = &vdev->eps[ep_index];
+       if (!ep)
+               return;
 
        /* Bail out if toggle is already being cleared by a endpoint reset */
        if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
index 7a264962a1a9c303a39f1802f499fb0aedbbebb3..f5c41448d067e2c72f1b6a0ea27e9d1568e1a713 100644 (file)
@@ -2175,7 +2175,8 @@ static inline bool xhci_urb_suitable_for_idt(struct urb *urb)
        if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) &&
            usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE &&
            urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE &&
-           !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+           !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) &&
+           !urb->num_sgs)
                return true;
 
        return false;
index ba05dd80a020fb553752ff2b80e04a20b862c26f..f5bed9f29e5621521b4ea754ed76a5442744492d 100644 (file)
@@ -866,19 +866,20 @@ static void iowarrior_disconnect(struct usb_interface *interface)
        dev = usb_get_intfdata(interface);
        mutex_lock(&iowarrior_open_disc_lock);
        usb_set_intfdata(interface, NULL);
+       /* prevent device read, write and ioctl */
+       dev->present = 0;
 
        minor = dev->minor;
+       mutex_unlock(&iowarrior_open_disc_lock);
+       /* give back our minor - this will call close() locks need to be dropped at this point*/
 
-       /* give back our minor */
        usb_deregister_dev(interface, &iowarrior_class);
 
        mutex_lock(&dev->mutex);
 
        /* prevent device read, write and ioctl */
-       dev->present = 0;
 
        mutex_unlock(&dev->mutex);
-       mutex_unlock(&iowarrior_open_disc_lock);
 
        if (dev->opened) {
                /* There is a process that holds a filedescriptor to the device ,
index 27e9c78a791e25fc444728da708b63ca421f9983..a32d61a79ab8af6170b00578e7cc066138f66c53 100644 (file)
@@ -51,6 +51,7 @@ struct rio_usb_data {
         char *obuf, *ibuf;              /* transfer buffers */
         char bulk_in_ep, bulk_out_ep;   /* Endpoint assignments */
         wait_queue_head_t wait_q;       /* for timeouts */
+       struct mutex lock;          /* general race avoidance */
 };
 
 static DEFINE_MUTEX(rio500_mutex);
@@ -62,8 +63,10 @@ static int open_rio(struct inode *inode, struct file *file)
 
        /* against disconnect() */
        mutex_lock(&rio500_mutex);
+       mutex_lock(&(rio->lock));
 
        if (rio->isopen || !rio->present) {
+               mutex_unlock(&(rio->lock));
                mutex_unlock(&rio500_mutex);
                return -EBUSY;
        }
@@ -71,6 +74,7 @@ static int open_rio(struct inode *inode, struct file *file)
 
        init_waitqueue_head(&rio->wait_q);
 
+       mutex_unlock(&(rio->lock));
 
        dev_info(&rio->rio_dev->dev, "Rio opened.\n");
        mutex_unlock(&rio500_mutex);
@@ -84,6 +88,7 @@ static int close_rio(struct inode *inode, struct file *file)
 
        /* against disconnect() */
        mutex_lock(&rio500_mutex);
+       mutex_lock(&(rio->lock));
 
        rio->isopen = 0;
        if (!rio->present) {
@@ -95,6 +100,7 @@ static int close_rio(struct inode *inode, struct file *file)
        } else {
                dev_info(&rio->rio_dev->dev, "Rio closed.\n");
        }
+       mutex_unlock(&(rio->lock));
        mutex_unlock(&rio500_mutex);
        return 0;
 }
@@ -109,7 +115,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
        int retries;
        int retval=0;
 
-       mutex_lock(&rio500_mutex);
+       mutex_lock(&(rio->lock));
         /* Sanity check to make sure rio is connected, powered, etc */
         if (rio->present == 0 || rio->rio_dev == NULL) {
                retval = -ENODEV;
@@ -253,7 +259,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
 
 
 err_out:
-       mutex_unlock(&rio500_mutex);
+       mutex_unlock(&(rio->lock));
        return retval;
 }
 
@@ -273,12 +279,12 @@ write_rio(struct file *file, const char __user *buffer,
        int errn = 0;
        int intr;
 
-       intr = mutex_lock_interruptible(&rio500_mutex);
+       intr = mutex_lock_interruptible(&(rio->lock));
        if (intr)
                return -EINTR;
         /* Sanity check to make sure rio is connected, powered, etc */
         if (rio->present == 0 || rio->rio_dev == NULL) {
-               mutex_unlock(&rio500_mutex);
+               mutex_unlock(&(rio->lock));
                return -ENODEV;
        }
 
@@ -301,7 +307,7 @@ write_rio(struct file *file, const char __user *buffer,
                                goto error;
                        }
                        if (signal_pending(current)) {
-                               mutex_unlock(&rio500_mutex);
+                               mutex_unlock(&(rio->lock));
                                return bytes_written ? bytes_written : -EINTR;
                        }
 
@@ -339,12 +345,12 @@ write_rio(struct file *file, const char __user *buffer,
                buffer += copy_size;
        } while (count > 0);
 
-       mutex_unlock(&rio500_mutex);
+       mutex_unlock(&(rio->lock));
 
        return bytes_written ? bytes_written : -EIO;
 
 error:
-       mutex_unlock(&rio500_mutex);
+       mutex_unlock(&(rio->lock));
        return errn;
 }
 
@@ -361,12 +367,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
        char *ibuf;
        int intr;
 
-       intr = mutex_lock_interruptible(&rio500_mutex);
+       intr = mutex_lock_interruptible(&(rio->lock));
        if (intr)
                return -EINTR;
        /* Sanity check to make sure rio is connected, powered, etc */
         if (rio->present == 0 || rio->rio_dev == NULL) {
-               mutex_unlock(&rio500_mutex);
+               mutex_unlock(&(rio->lock));
                return -ENODEV;
        }
 
@@ -377,11 +383,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
 
        while (count > 0) {
                if (signal_pending(current)) {
-                       mutex_unlock(&rio500_mutex);
+                       mutex_unlock(&(rio->lock));
                        return read_count ? read_count : -EINTR;
                }
                if (!rio->rio_dev) {
-                       mutex_unlock(&rio500_mutex);
+                       mutex_unlock(&(rio->lock));
                        return -ENODEV;
                }
                this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
@@ -399,7 +405,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
                        count = this_read = partial;
                } else if (result == -ETIMEDOUT || result == 15) {      /* FIXME: 15 ??? */
                        if (!maxretry--) {
-                               mutex_unlock(&rio500_mutex);
+                               mutex_unlock(&(rio->lock));
                                dev_err(&rio->rio_dev->dev,
                                        "read_rio: maxretry timeout\n");
                                return -ETIME;
@@ -409,19 +415,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
                        finish_wait(&rio->wait_q, &wait);
                        continue;
                } else if (result != -EREMOTEIO) {
-                       mutex_unlock(&rio500_mutex);
+                       mutex_unlock(&(rio->lock));
                        dev_err(&rio->rio_dev->dev,
                                "Read Whoops - result:%d partial:%u this_read:%u\n",
                                result, partial, this_read);
                        return -EIO;
                } else {
-                       mutex_unlock(&rio500_mutex);
+                       mutex_unlock(&(rio->lock));
                        return (0);
                }
 
                if (this_read) {
                        if (copy_to_user(buffer, ibuf, this_read)) {
-                               mutex_unlock(&rio500_mutex);
+                               mutex_unlock(&(rio->lock));
                                return -EFAULT;
                        }
                        count -= this_read;
@@ -429,7 +435,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
                        buffer += this_read;
                }
        }
-       mutex_unlock(&rio500_mutex);
+       mutex_unlock(&(rio->lock));
        return read_count;
 }
 
@@ -494,6 +500,8 @@ static int probe_rio(struct usb_interface *intf,
        }
        dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
 
+       mutex_init(&(rio->lock));
+
        usb_set_intfdata (intf, rio);
        rio->present = 1;
 bail_out:
@@ -511,10 +519,12 @@ static void disconnect_rio(struct usb_interface *intf)
        if (rio) {
                usb_deregister_dev(intf, &usb_rio_class);
 
+               mutex_lock(&(rio->lock));
                if (rio->isopen) {
                        rio->isopen = 0;
                        /* better let it finish - the release will do whats needed */
                        rio->rio_dev = NULL;
+                       mutex_unlock(&(rio->lock));
                        mutex_unlock(&rio500_mutex);
                        return;
                }
@@ -524,6 +534,7 @@ static void disconnect_rio(struct usb_interface *intf)
                dev_info(&intf->dev, "USB Rio disconnected.\n");
 
                rio->present = 0;
+               mutex_unlock(&(rio->lock));
        }
        mutex_unlock(&rio500_mutex);
 }
index 4d6ae3795a883845548dad31bb3e9d82f7436f48..6ca9111d150a34b5fe567cc77e07c2c95c2b470e 100644 (file)
@@ -375,7 +375,8 @@ out_err:
 
 #ifdef CONFIG_OF
 static void usb251xb_get_ports_field(struct usb251xb *hub,
-                                   const char *prop_name, u8 port_cnt, u8 *fld)
+                                   const char *prop_name, u8 port_cnt,
+                                   bool ds_only, u8 *fld)
 {
        struct device *dev = hub->dev;
        struct property *prop;
@@ -383,7 +384,7 @@ static void usb251xb_get_ports_field(struct usb251xb *hub,
        u32 port;
 
        of_property_for_each_u32(dev->of_node, prop_name, prop, p, port) {
-               if ((port >= 1) && (port <= port_cnt))
+               if ((port >= ds_only ? 1 : 0) && (port <= port_cnt))
                        *fld |= BIT(port);
                else
                        dev_warn(dev, "port %u doesn't exist\n", port);
@@ -501,15 +502,15 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
 
        hub->non_rem_dev = USB251XB_DEF_NON_REMOVABLE_DEVICES;
        usb251xb_get_ports_field(hub, "non-removable-ports", data->port_cnt,
-                                &hub->non_rem_dev);
+                                true, &hub->non_rem_dev);
 
        hub->port_disable_sp = USB251XB_DEF_PORT_DISABLE_SELF;
        usb251xb_get_ports_field(hub, "sp-disabled-ports", data->port_cnt,
-                                &hub->port_disable_sp);
+                                true, &hub->port_disable_sp);
 
        hub->port_disable_bp = USB251XB_DEF_PORT_DISABLE_BUS;
        usb251xb_get_ports_field(hub, "bp-disabled-ports", data->port_cnt,
-                                &hub->port_disable_bp);
+                                true, &hub->port_disable_bp);
 
        hub->max_power_sp = USB251XB_DEF_MAX_POWER_SELF;
        if (!of_property_read_u32(np, "sp-max-total-current-microamp",
@@ -573,9 +574,7 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
         */
        hub->port_swap = USB251XB_DEF_PORT_SWAP;
        usb251xb_get_ports_field(hub, "swap-dx-lanes", data->port_cnt,
-                                &hub->port_swap);
-       if (of_get_property(np, "swap-us-lanes", NULL))
-               hub->port_swap |= BIT(0);
+                                false, &hub->port_swap);
 
        /* The following parameters are currently not exposed to devicetree, but
         * may be as soon as needed.
index 7b306aa22d2589518d696111cb2750bdc3bed4c0..6715a128e6c8b29bd52cb6c132b5eb0ecd459209 100644 (file)
@@ -92,7 +92,6 @@ static void yurex_delete(struct kref *kref)
 
        dev_dbg(&dev->interface->dev, "%s\n", __func__);
 
-       usb_put_dev(dev->udev);
        if (dev->cntl_urb) {
                usb_kill_urb(dev->cntl_urb);
                kfree(dev->cntl_req);
@@ -108,6 +107,7 @@ static void yurex_delete(struct kref *kref)
                                dev->int_buffer, dev->urb->transfer_dma);
                usb_free_urb(dev->urb);
        }
+       usb_put_dev(dev->udev);
        kfree(dev);
 }
 
index c1582fbd1150326e070603fc537f2f283e59b365..38e920ac7f82092f996279c0918c88538f932175 100644 (file)
@@ -968,6 +968,11 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7B) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7C) },
 
+       /* Motorola devices */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x2a70, 0xff, 0xff, 0xff) },    /* mdm6600 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x2e0a, 0xff, 0xff, 0xff) },    /* mdm9600 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x4281, 0x0a, 0x00, 0xfc) },    /* mdm ram dl */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x900e, 0xff, 0xff, 0xff) },    /* mdm qc dl */
 
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
@@ -1549,6 +1554,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff),  /* Telewell TW-LTE 4G v2 */
          .driver_info = RSVD(2) },
        { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x1476, 0xff) },    /* GosunCn ZTE WeLink ME3630 (ECM/NCM mode) */
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0x00, 0x00) }, /* ZTE MF871A */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) },
@@ -1952,11 +1958,15 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(4) },
        { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff),                     /* D-Link DWM-222 */
          .driver_info = RSVD(4) },
+       { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e3d, 0xff),                     /* D-Link DWM-222 A2 */
+         .driver_info = RSVD(4) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) },    /* D-Link DWM-152/C1 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) },    /* D-Link DWM-156/C1 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) },    /* D-Link DWM-156/A3 */
        { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff),                     /* Olicard 600 */
          .driver_info = RSVD(4) },
+       { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2060, 0xff),                     /* BroadMobi BM818 */
+         .driver_info = RSVD(4) },
        { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) },                   /* OLICARD300 - MT6225 */
        { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
        { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
index cc794e25a0b6ed043149685eb1400492a977b2c3..1d9ce9cbc831d1035a6ad086b10f1f99e3188a63 100644 (file)
@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
 
 static int auto_delink_en = 1;
 module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
+MODULE_PARM_DESC(auto_delink_en, "auto delink mode (0=firmware, 1=software [default])");
 
 #ifdef CONFIG_REALTEK_AUTOPM
 static int ss_en = 1;
@@ -996,12 +996,15 @@ static int init_realtek_cr(struct us_data *us)
                        goto INIT_FAIL;
        }
 
-       if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
-           CHECK_FW_VER(chip, 0x5901))
-               SET_AUTO_DELINK(chip);
-       if (STATUS_LEN(chip) == 16) {
-               if (SUPPORT_AUTO_DELINK(chip))
+       if (CHECK_PID(chip, 0x0138) || CHECK_PID(chip, 0x0158) ||
+           CHECK_PID(chip, 0x0159)) {
+               if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
+                               CHECK_FW_VER(chip, 0x5901))
                        SET_AUTO_DELINK(chip);
+               if (STATUS_LEN(chip) == 16) {
+                       if (SUPPORT_AUTO_DELINK(chip))
+                               SET_AUTO_DELINK(chip);
+               }
        }
 #ifdef CONFIG_REALTEK_AUTOPM
        if (ss_en)
index 30790240aec6c097e6b557dff889622560f91432..05b80211290d3e2df528eee1ef5065b71f9e9e39 100644 (file)
@@ -28,6 +28,8 @@
  * status of a command.
  */
 
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 
@@ -99,6 +101,7 @@ static int slave_alloc (struct scsi_device *sdev)
 static int slave_configure(struct scsi_device *sdev)
 {
        struct us_data *us = host_to_us(sdev->host);
+       struct device *dev = us->pusb_dev->bus->sysdev;
 
        /*
         * Many devices have trouble transferring more than 32KB at a time,
@@ -128,6 +131,14 @@ static int slave_configure(struct scsi_device *sdev)
                blk_queue_max_hw_sectors(sdev->request_queue, 2048);
        }
 
+       /*
+        * The max_hw_sectors should be up to maximum size of a mapping for
+        * the device. Otherwise, a DMA API might fail on swiotlb environment.
+        */
+       blk_queue_max_hw_sectors(sdev->request_queue,
+               min_t(size_t, queue_max_hw_sectors(sdev->request_queue),
+                     dma_max_mapping_size(dev) >> SECTOR_SHIFT));
+
        /*
         * Some USB host controllers can't do DMA; they have to use PIO.
         * They indicate this by setting their dma_mask to NULL.  For
index ea0d27a94afe058b3671ad6c66989ecbbdb98568..1cd9b6305b06042fecf75942c4f79af41747feea 100644 (file)
@@ -2100,7 +2100,7 @@ UNUSUAL_DEV(  0x14cd, 0x6600, 0x0201, 0x0201,
                US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Michael Büsch <m@bues.ch> */
-UNUSUAL_DEV(  0x152d, 0x0567, 0x0114, 0x0116,
+UNUSUAL_DEV(  0x152d, 0x0567, 0x0114, 0x0117,
                "JMicron",
                "USB to ATA/ATAPI Bridge",
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
index fba32d84e5787f2f0b47a94d7c61e0b16747e190..bcfdb55fd1985e942eda1e5f8c95ae868104b208 100644 (file)
@@ -379,7 +379,8 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
                        return SNK_UNATTACHED;
                else if (port->try_role == TYPEC_SOURCE)
                        return SRC_UNATTACHED;
-               else if (port->tcpc->config->default_role == TYPEC_SINK)
+               else if (port->tcpc->config &&
+                        port->tcpc->config->default_role == TYPEC_SINK)
                        return SNK_UNATTACHED;
                /* Fall through to return SRC_UNATTACHED */
        } else if (port->port_type == TYPEC_PORT_SNK) {
@@ -586,7 +587,20 @@ static void tcpm_debugfs_init(struct tcpm_port *port)
 
 static void tcpm_debugfs_exit(struct tcpm_port *port)
 {
+       int i;
+
+       mutex_lock(&port->logbuffer_lock);
+       for (i = 0; i < LOG_BUFFER_ENTRIES; i++) {
+               kfree(port->logbuffer[i]);
+               port->logbuffer[i] = NULL;
+       }
+       mutex_unlock(&port->logbuffer_lock);
+
        debugfs_remove(port->dentry);
+       if (list_empty(&rootdir->d_subdirs)) {
+               debugfs_remove(rootdir);
+               rootdir = NULL;
+       }
 }
 
 #else
@@ -1095,7 +1109,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
                        break;
                case CMD_ATTENTION:
                        /* Attention command does not have response */
-                       typec_altmode_attention(adev, p[1]);
+                       if (adev)
+                               typec_altmode_attention(adev, p[1]);
                        return 0;
                default:
                        break;
@@ -1147,20 +1162,26 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
                        }
                        break;
                case CMD_ENTER_MODE:
-                       typec_altmode_update_active(pdev, true);
-
-                       if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
-                               response[0] = VDO(adev->svid, 1, CMD_EXIT_MODE);
-                               response[0] |= VDO_OPOS(adev->mode);
-                               return 1;
+                       if (adev && pdev) {
+                               typec_altmode_update_active(pdev, true);
+
+                               if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
+                                       response[0] = VDO(adev->svid, 1,
+                                                         CMD_EXIT_MODE);
+                                       response[0] |= VDO_OPOS(adev->mode);
+                                       return 1;
+                               }
                        }
                        return 0;
                case CMD_EXIT_MODE:
-                       typec_altmode_update_active(pdev, false);
+                       if (adev && pdev) {
+                               typec_altmode_update_active(pdev, false);
 
-                       /* Back to USB Operation */
-                       WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB,
-                                                    NULL));
+                               /* Back to USB Operation */
+                               WARN_ON(typec_altmode_notify(adev,
+                                                            TYPEC_STATE_USB,
+                                                            NULL));
+                       }
                        break;
                default:
                        break;
@@ -1170,8 +1191,10 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
                switch (cmd) {
                case CMD_ENTER_MODE:
                        /* Back to USB Operation */
-                       WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB,
-                                                    NULL));
+                       if (adev)
+                               WARN_ON(typec_altmode_notify(adev,
+                                                            TYPEC_STATE_USB,
+                                                            NULL));
                        break;
                default:
                        break;
@@ -1182,7 +1205,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
        }
 
        /* Informing the alternate mode drivers about everything */
-       typec_altmode_vdm(adev, p[0], &p[1], cnt);
+       if (adev)
+               typec_altmode_vdm(adev, p[0], &p[1], cnt);
 
        return rlen;
 }
@@ -1422,7 +1446,7 @@ static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo,
                                else if ((pdo_min_voltage(pdo[i]) ==
                                          pdo_min_voltage(pdo[i - 1])) &&
                                         (pdo_max_voltage(pdo[i]) ==
-                                         pdo_min_voltage(pdo[i - 1])))
+                                         pdo_max_voltage(pdo[i - 1])))
                                        return PDO_ERR_DUPE_PDO;
                                break;
                        /*
@@ -4114,7 +4138,7 @@ static int tcpm_try_role(const struct typec_capability *cap, int role)
        mutex_lock(&port->lock);
        if (tcpc->try_role)
                ret = tcpc->try_role(tcpc, role);
-       if (!ret && !tcpc->config->try_role_hw)
+       if (!ret && (!tcpc->config || !tcpc->config->try_role_hw))
                port->try_role = role;
        port->try_src_count = 0;
        port->try_snk_count = 0;
@@ -4701,7 +4725,7 @@ static int tcpm_copy_caps(struct tcpm_port *port,
        port->typec_caps.prefer_role = tcfg->default_role;
        port->typec_caps.type = tcfg->type;
        port->typec_caps.data = tcfg->data;
-       port->self_powered = port->tcpc->config->self_powered;
+       port->self_powered = tcfg->self_powered;
 
        return 0;
 }
index f7a79a23ebedc02898102d287114ffafbb4b8ccc..8e9f8fba55af999f1b1c3c73bfd68919518e42e5 100644 (file)
@@ -1018,7 +1018,7 @@ release_fw:
  ******************************************************************************/
 static int ccg_fw_update(struct ucsi_ccg *uc, enum enum_flash_mode flash_mode)
 {
-       int err;
+       int err = 0;
 
        while (flash_mode != FLASH_NOT_NEEDED) {
                err = do_flash(uc, flash_mode);
index 9e90e969af5550254a8d2b68e58b1fc6c3033427..7804869c6a31398ffbcc9cd1c5786b76f1f54274 100644 (file)
  * Using this limit prevents one virtqueue from starving others. */
 #define VHOST_TEST_WEIGHT 0x80000
 
+/* Max number of packets transferred before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others with
+ * pkts.
+ */
+#define VHOST_TEST_PKT_WEIGHT 256
+
 enum {
        VHOST_TEST_VQ = 0,
        VHOST_TEST_VQ_MAX = 1,
@@ -80,10 +86,8 @@ static void handle_vq(struct vhost_test *n)
                }
                vhost_add_used_and_signal(&n->dev, vq, head, 0);
                total_len += len;
-               if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
-                       vhost_poll_queue(&vq->poll);
+               if (unlikely(vhost_exceeds_weight(vq, 0, total_len)))
                        break;
-               }
        }
 
        mutex_unlock(&vq->mutex);
@@ -115,7 +119,8 @@ static int vhost_test_open(struct inode *inode, struct file *f)
        dev = &n->dev;
        vqs[VHOST_TEST_VQ] = &n->vqs[VHOST_TEST_VQ];
        n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
-       vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX);
+       vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX, UIO_MAXIOV,
+                      VHOST_TEST_PKT_WEIGHT, VHOST_TEST_WEIGHT);
 
        f->private_data = n;
 
index 0536f85263599722b45fd9eaeb05da88085ea9c1..36ca2cf419bfebf475021d995640f383b154ee5e 100644 (file)
@@ -203,7 +203,6 @@ EXPORT_SYMBOL_GPL(vhost_poll_init);
 int vhost_poll_start(struct vhost_poll *poll, struct file *file)
 {
        __poll_t mask;
-       int ret = 0;
 
        if (poll->wqh)
                return 0;
@@ -213,10 +212,10 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file)
                vhost_poll_wakeup(&poll->wait, 0, 0, poll_to_key(mask));
        if (mask & EPOLLERR) {
                vhost_poll_stop(poll);
-               ret = -EINVAL;
+               return -EINVAL;
        }
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(vhost_poll_start);
 
@@ -298,160 +297,6 @@ static void vhost_vq_meta_reset(struct vhost_dev *d)
                __vhost_vq_meta_reset(d->vqs[i]);
 }
 
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-static void vhost_map_unprefetch(struct vhost_map *map)
-{
-       kfree(map->pages);
-       map->pages = NULL;
-       map->npages = 0;
-       map->addr = NULL;
-}
-
-static void vhost_uninit_vq_maps(struct vhost_virtqueue *vq)
-{
-       struct vhost_map *map[VHOST_NUM_ADDRS];
-       int i;
-
-       spin_lock(&vq->mmu_lock);
-       for (i = 0; i < VHOST_NUM_ADDRS; i++) {
-               map[i] = rcu_dereference_protected(vq->maps[i],
-                                 lockdep_is_held(&vq->mmu_lock));
-               if (map[i])
-                       rcu_assign_pointer(vq->maps[i], NULL);
-       }
-       spin_unlock(&vq->mmu_lock);
-
-       synchronize_rcu();
-
-       for (i = 0; i < VHOST_NUM_ADDRS; i++)
-               if (map[i])
-                       vhost_map_unprefetch(map[i]);
-
-}
-
-static void vhost_reset_vq_maps(struct vhost_virtqueue *vq)
-{
-       int i;
-
-       vhost_uninit_vq_maps(vq);
-       for (i = 0; i < VHOST_NUM_ADDRS; i++)
-               vq->uaddrs[i].size = 0;
-}
-
-static bool vhost_map_range_overlap(struct vhost_uaddr *uaddr,
-                                    unsigned long start,
-                                    unsigned long end)
-{
-       if (unlikely(!uaddr->size))
-               return false;
-
-       return !(end < uaddr->uaddr || start > uaddr->uaddr - 1 + uaddr->size);
-}
-
-static void vhost_invalidate_vq_start(struct vhost_virtqueue *vq,
-                                     int index,
-                                     unsigned long start,
-                                     unsigned long end)
-{
-       struct vhost_uaddr *uaddr = &vq->uaddrs[index];
-       struct vhost_map *map;
-       int i;
-
-       if (!vhost_map_range_overlap(uaddr, start, end))
-               return;
-
-       spin_lock(&vq->mmu_lock);
-       ++vq->invalidate_count;
-
-       map = rcu_dereference_protected(vq->maps[index],
-                                       lockdep_is_held(&vq->mmu_lock));
-       if (map) {
-               if (uaddr->write) {
-                       for (i = 0; i < map->npages; i++)
-                               set_page_dirty(map->pages[i]);
-               }
-               rcu_assign_pointer(vq->maps[index], NULL);
-       }
-       spin_unlock(&vq->mmu_lock);
-
-       if (map) {
-               synchronize_rcu();
-               vhost_map_unprefetch(map);
-       }
-}
-
-static void vhost_invalidate_vq_end(struct vhost_virtqueue *vq,
-                                   int index,
-                                   unsigned long start,
-                                   unsigned long end)
-{
-       if (!vhost_map_range_overlap(&vq->uaddrs[index], start, end))
-               return;
-
-       spin_lock(&vq->mmu_lock);
-       --vq->invalidate_count;
-       spin_unlock(&vq->mmu_lock);
-}
-
-static int vhost_invalidate_range_start(struct mmu_notifier *mn,
-                                       const struct mmu_notifier_range *range)
-{
-       struct vhost_dev *dev = container_of(mn, struct vhost_dev,
-                                            mmu_notifier);
-       int i, j;
-
-       if (!mmu_notifier_range_blockable(range))
-               return -EAGAIN;
-
-       for (i = 0; i < dev->nvqs; i++) {
-               struct vhost_virtqueue *vq = dev->vqs[i];
-
-               for (j = 0; j < VHOST_NUM_ADDRS; j++)
-                       vhost_invalidate_vq_start(vq, j,
-                                                 range->start,
-                                                 range->end);
-       }
-
-       return 0;
-}
-
-static void vhost_invalidate_range_end(struct mmu_notifier *mn,
-                                      const struct mmu_notifier_range *range)
-{
-       struct vhost_dev *dev = container_of(mn, struct vhost_dev,
-                                            mmu_notifier);
-       int i, j;
-
-       for (i = 0; i < dev->nvqs; i++) {
-               struct vhost_virtqueue *vq = dev->vqs[i];
-
-               for (j = 0; j < VHOST_NUM_ADDRS; j++)
-                       vhost_invalidate_vq_end(vq, j,
-                                               range->start,
-                                               range->end);
-       }
-}
-
-static const struct mmu_notifier_ops vhost_mmu_notifier_ops = {
-       .invalidate_range_start = vhost_invalidate_range_start,
-       .invalidate_range_end = vhost_invalidate_range_end,
-};
-
-static void vhost_init_maps(struct vhost_dev *dev)
-{
-       struct vhost_virtqueue *vq;
-       int i, j;
-
-       dev->mmu_notifier.ops = &vhost_mmu_notifier_ops;
-
-       for (i = 0; i < dev->nvqs; ++i) {
-               vq = dev->vqs[i];
-               for (j = 0; j < VHOST_NUM_ADDRS; j++)
-                       RCU_INIT_POINTER(vq->maps[j], NULL);
-       }
-}
-#endif
-
 static void vhost_vq_reset(struct vhost_dev *dev,
                           struct vhost_virtqueue *vq)
 {
@@ -480,11 +325,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
        vq->busyloop_timeout = 0;
        vq->umem = NULL;
        vq->iotlb = NULL;
-       vq->invalidate_count = 0;
        __vhost_vq_meta_reset(vq);
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       vhost_reset_vq_maps(vq);
-#endif
 }
 
 static int vhost_worker(void *data)
@@ -634,9 +475,7 @@ void vhost_dev_init(struct vhost_dev *dev,
        INIT_LIST_HEAD(&dev->read_list);
        INIT_LIST_HEAD(&dev->pending_list);
        spin_lock_init(&dev->iotlb_lock);
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       vhost_init_maps(dev);
-#endif
+
 
        for (i = 0; i < dev->nvqs; ++i) {
                vq = dev->vqs[i];
@@ -645,7 +484,6 @@ void vhost_dev_init(struct vhost_dev *dev,
                vq->heads = NULL;
                vq->dev = dev;
                mutex_init(&vq->mutex);
-               spin_lock_init(&vq->mmu_lock);
                vhost_vq_reset(dev, vq);
                if (vq->handle_kick)
                        vhost_poll_init(&vq->poll, vq->handle_kick,
@@ -725,18 +563,7 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
        if (err)
                goto err_cgroup;
 
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       err = mmu_notifier_register(&dev->mmu_notifier, dev->mm);
-       if (err)
-               goto err_mmu_notifier;
-#endif
-
        return 0;
-
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-err_mmu_notifier:
-       vhost_dev_free_iovecs(dev);
-#endif
 err_cgroup:
        kthread_stop(worker);
        dev->worker = NULL;
@@ -827,107 +654,6 @@ static void vhost_clear_msg(struct vhost_dev *dev)
        spin_unlock(&dev->iotlb_lock);
 }
 
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-static void vhost_setup_uaddr(struct vhost_virtqueue *vq,
-                             int index, unsigned long uaddr,
-                             size_t size, bool write)
-{
-       struct vhost_uaddr *addr = &vq->uaddrs[index];
-
-       addr->uaddr = uaddr;
-       addr->size = size;
-       addr->write = write;
-}
-
-static void vhost_setup_vq_uaddr(struct vhost_virtqueue *vq)
-{
-       vhost_setup_uaddr(vq, VHOST_ADDR_DESC,
-                         (unsigned long)vq->desc,
-                         vhost_get_desc_size(vq, vq->num),
-                         false);
-       vhost_setup_uaddr(vq, VHOST_ADDR_AVAIL,
-                         (unsigned long)vq->avail,
-                         vhost_get_avail_size(vq, vq->num),
-                         false);
-       vhost_setup_uaddr(vq, VHOST_ADDR_USED,
-                         (unsigned long)vq->used,
-                         vhost_get_used_size(vq, vq->num),
-                         true);
-}
-
-static int vhost_map_prefetch(struct vhost_virtqueue *vq,
-                              int index)
-{
-       struct vhost_map *map;
-       struct vhost_uaddr *uaddr = &vq->uaddrs[index];
-       struct page **pages;
-       int npages = DIV_ROUND_UP(uaddr->size, PAGE_SIZE);
-       int npinned;
-       void *vaddr, *v;
-       int err;
-       int i;
-
-       spin_lock(&vq->mmu_lock);
-
-       err = -EFAULT;
-       if (vq->invalidate_count)
-               goto err;
-
-       err = -ENOMEM;
-       map = kmalloc(sizeof(*map), GFP_ATOMIC);
-       if (!map)
-               goto err;
-
-       pages = kmalloc_array(npages, sizeof(struct page *), GFP_ATOMIC);
-       if (!pages)
-               goto err_pages;
-
-       err = EFAULT;
-       npinned = __get_user_pages_fast(uaddr->uaddr, npages,
-                                       uaddr->write, pages);
-       if (npinned > 0)
-               release_pages(pages, npinned);
-       if (npinned != npages)
-               goto err_gup;
-
-       for (i = 0; i < npinned; i++)
-               if (PageHighMem(pages[i]))
-                       goto err_gup;
-
-       vaddr = v = page_address(pages[0]);
-
-       /* For simplicity, fallback to userspace address if VA is not
-        * contigious.
-        */
-       for (i = 1; i < npinned; i++) {
-               v += PAGE_SIZE;
-               if (v != page_address(pages[i]))
-                       goto err_gup;
-       }
-
-       map->addr = vaddr + (uaddr->uaddr & (PAGE_SIZE - 1));
-       map->npages = npages;
-       map->pages = pages;
-
-       rcu_assign_pointer(vq->maps[index], map);
-       /* No need for a synchronize_rcu(). This function should be
-        * called by dev->worker so we are serialized with all
-        * readers.
-        */
-       spin_unlock(&vq->mmu_lock);
-
-       return 0;
-
-err_gup:
-       kfree(pages);
-err_pages:
-       kfree(map);
-err:
-       spin_unlock(&vq->mmu_lock);
-       return err;
-}
-#endif
-
 void vhost_dev_cleanup(struct vhost_dev *dev)
 {
        int i;
@@ -957,16 +683,8 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
                kthread_stop(dev->worker);
                dev->worker = NULL;
        }
-       if (dev->mm) {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-               mmu_notifier_unregister(&dev->mmu_notifier, dev->mm);
-#endif
+       if (dev->mm)
                mmput(dev->mm);
-       }
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       for (i = 0; i < dev->nvqs; i++)
-               vhost_uninit_vq_maps(dev->vqs[i]);
-#endif
        dev->mm = NULL;
 }
 EXPORT_SYMBOL_GPL(vhost_dev_cleanup);
@@ -1195,26 +913,6 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,
 
 static inline int vhost_put_avail_event(struct vhost_virtqueue *vq)
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_used *used;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
-               if (likely(map)) {
-                       used = map->addr;
-                       *((__virtio16 *)&used->ring[vq->num]) =
-                               cpu_to_vhost16(vq, vq->avail_idx);
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx),
                              vhost_avail_event(vq));
 }
@@ -1223,27 +921,6 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq,
                                 struct vring_used_elem *head, int idx,
                                 int count)
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_used *used;
-       size_t size;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
-               if (likely(map)) {
-                       used = map->addr;
-                       size = count * sizeof(*head);
-                       memcpy(used->ring + idx, head, size);
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_copy_to_user(vq, vq->used->ring + idx, head,
                                  count * sizeof(*head));
 }
@@ -1251,25 +928,6 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq,
 static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)
 
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_used *used;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
-               if (likely(map)) {
-                       used = map->addr;
-                       used->flags = cpu_to_vhost16(vq, vq->used_flags);
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags),
                              &vq->used->flags);
 }
@@ -1277,25 +935,6 @@ static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)
 static inline int vhost_put_used_idx(struct vhost_virtqueue *vq)
 
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_used *used;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
-               if (likely(map)) {
-                       used = map->addr;
-                       used->idx = cpu_to_vhost16(vq, vq->last_used_idx);
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx),
                              &vq->used->idx);
 }
@@ -1341,50 +980,12 @@ static void vhost_dev_unlock_vqs(struct vhost_dev *d)
 static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq,
                                      __virtio16 *idx)
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_avail *avail;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
-               if (likely(map)) {
-                       avail = map->addr;
-                       *idx = avail->idx;
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_get_avail(vq, *idx, &vq->avail->idx);
 }
 
 static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,
                                       __virtio16 *head, int idx)
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_avail *avail;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
-               if (likely(map)) {
-                       avail = map->addr;
-                       *head = avail->ring[idx & (vq->num - 1)];
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_get_avail(vq, *head,
                               &vq->avail->ring[idx & (vq->num - 1)]);
 }
@@ -1392,98 +993,24 @@ static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,
 static inline int vhost_get_avail_flags(struct vhost_virtqueue *vq,
                                        __virtio16 *flags)
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_avail *avail;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
-               if (likely(map)) {
-                       avail = map->addr;
-                       *flags = avail->flags;
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_get_avail(vq, *flags, &vq->avail->flags);
 }
 
 static inline int vhost_get_used_event(struct vhost_virtqueue *vq,
                                       __virtio16 *event)
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_avail *avail;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-               map = rcu_dereference(vq->maps[VHOST_ADDR_AVAIL]);
-               if (likely(map)) {
-                       avail = map->addr;
-                       *event = (__virtio16)avail->ring[vq->num];
-                       rcu_read_unlock();
-                       return 0;
-               }
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_get_avail(vq, *event, vhost_used_event(vq));
 }
 
 static inline int vhost_get_used_idx(struct vhost_virtqueue *vq,
                                     __virtio16 *idx)
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_used *used;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_USED]);
-               if (likely(map)) {
-                       used = map->addr;
-                       *idx = used->idx;
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_get_used(vq, *idx, &vq->used->idx);
 }
 
 static inline int vhost_get_desc(struct vhost_virtqueue *vq,
                                 struct vring_desc *desc, int idx)
 {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       struct vhost_map *map;
-       struct vring_desc *d;
-
-       if (!vq->iotlb) {
-               rcu_read_lock();
-
-               map = rcu_dereference(vq->maps[VHOST_ADDR_DESC]);
-               if (likely(map)) {
-                       d = map->addr;
-                       *desc = *(d + idx);
-                       rcu_read_unlock();
-                       return 0;
-               }
-
-               rcu_read_unlock();
-       }
-#endif
-
        return vhost_copy_from_user(vq, desc, vq->desc + idx, sizeof(*desc));
 }
 
@@ -1824,32 +1351,12 @@ static bool iotlb_access_ok(struct vhost_virtqueue *vq,
        return true;
 }
 
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-static void vhost_vq_map_prefetch(struct vhost_virtqueue *vq)
-{
-       struct vhost_map __rcu *map;
-       int i;
-
-       for (i = 0; i < VHOST_NUM_ADDRS; i++) {
-               rcu_read_lock();
-               map = rcu_dereference(vq->maps[i]);
-               rcu_read_unlock();
-               if (unlikely(!map))
-                       vhost_map_prefetch(vq, i);
-       }
-}
-#endif
-
 int vq_meta_prefetch(struct vhost_virtqueue *vq)
 {
        unsigned int num = vq->num;
 
-       if (!vq->iotlb) {
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-               vhost_vq_map_prefetch(vq);
-#endif
+       if (!vq->iotlb)
                return 1;
-       }
 
        return iotlb_access_ok(vq, VHOST_ACCESS_RO, (u64)(uintptr_t)vq->desc,
                               vhost_get_desc_size(vq, num), VHOST_ADDR_DESC) &&
@@ -2060,16 +1567,6 @@ static long vhost_vring_set_num_addr(struct vhost_dev *d,
 
        mutex_lock(&vq->mutex);
 
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       /* Unregister MMU notifer to allow invalidation callback
-        * can access vq->uaddrs[] without holding a lock.
-        */
-       if (d->mm)
-               mmu_notifier_unregister(&d->mmu_notifier, d->mm);
-
-       vhost_uninit_vq_maps(vq);
-#endif
-
        switch (ioctl) {
        case VHOST_SET_VRING_NUM:
                r = vhost_vring_set_num(d, vq, argp);
@@ -2081,13 +1578,6 @@ static long vhost_vring_set_num_addr(struct vhost_dev *d,
                BUG();
        }
 
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       vhost_setup_vq_uaddr(vq);
-
-       if (d->mm)
-               mmu_notifier_register(&d->mmu_notifier, d->mm);
-#endif
-
        mutex_unlock(&vq->mutex);
 
        return r;
@@ -2688,7 +2178,7 @@ static int get_indirect(struct vhost_virtqueue *vq,
                /* If this is an input descriptor, increment that count. */
                if (access == VHOST_ACCESS_WO) {
                        *in_num += ret;
-                       if (unlikely(log)) {
+                       if (unlikely(log && ret)) {
                                log[*log_num].addr = vhost64_to_cpu(vq, desc.addr);
                                log[*log_num].len = vhost32_to_cpu(vq, desc.len);
                                ++*log_num;
@@ -2829,7 +2319,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
                        /* If this is an input descriptor,
                         * increment that count. */
                        *in_num += ret;
-                       if (unlikely(log)) {
+                       if (unlikely(log && ret)) {
                                log[*log_num].addr = vhost64_to_cpu(vq, desc.addr);
                                log[*log_num].len = vhost32_to_cpu(vq, desc.len);
                                ++*log_num;
index 8192963329138210cde91919aaa184e9ee217a31..e9ed2722b63333404b444f55dd4638a5358c59fa 100644 (file)
@@ -12,9 +12,6 @@
 #include <linux/virtio_config.h>
 #include <linux/virtio_ring.h>
 #include <linux/atomic.h>
-#include <linux/pagemap.h>
-#include <linux/mmu_notifier.h>
-#include <asm/cacheflush.h>
 
 struct vhost_work;
 typedef void (*vhost_work_fn_t)(struct vhost_work *work);
@@ -83,24 +80,6 @@ enum vhost_uaddr_type {
        VHOST_NUM_ADDRS = 3,
 };
 
-struct vhost_map {
-       int npages;
-       void *addr;
-       struct page **pages;
-};
-
-struct vhost_uaddr {
-       unsigned long uaddr;
-       size_t size;
-       bool write;
-};
-
-#if defined(CONFIG_MMU_NOTIFIER) && ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 0
-#define VHOST_ARCH_CAN_ACCEL_UACCESS 1
-#else
-#define VHOST_ARCH_CAN_ACCEL_UACCESS 0
-#endif
-
 /* The virtqueue structure describes a queue attached to a device. */
 struct vhost_virtqueue {
        struct vhost_dev *dev;
@@ -111,22 +90,7 @@ struct vhost_virtqueue {
        struct vring_desc __user *desc;
        struct vring_avail __user *avail;
        struct vring_used __user *used;
-
-#if VHOST_ARCH_CAN_ACCEL_UACCESS
-       /* Read by memory accessors, modified by meta data
-        * prefetching, MMU notifier and vring ioctl().
-        * Synchonrized through mmu_lock (writers) and RCU (writers
-        * and readers).
-        */
-       struct vhost_map __rcu *maps[VHOST_NUM_ADDRS];
-       /* Read by MMU notifier, modified by vring ioctl(),
-        * synchronized through MMU notifier
-        * registering/unregistering.
-        */
-       struct vhost_uaddr uaddrs[VHOST_NUM_ADDRS];
-#endif
        const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS];
-
        struct file *kick;
        struct eventfd_ctx *call_ctx;
        struct eventfd_ctx *error_ctx;
@@ -181,8 +145,6 @@ struct vhost_virtqueue {
        bool user_be;
 #endif
        u32 busyloop_timeout;
-       spinlock_t mmu_lock;
-       int invalidate_count;
 };
 
 struct vhost_msg_node {
@@ -196,9 +158,6 @@ struct vhost_msg_node {
 
 struct vhost_dev {
        struct mm_struct *mm;
-#ifdef CONFIG_MMU_NOTIFIER
-       struct mmu_notifier mmu_notifier;
-#endif
        struct mutex mutex;
        struct vhost_virtqueue **vqs;
        int nvqs;
index 92f23e3bc27a2400cfd14ed9b19017bc648457cf..7cacae5a8797d9faeaa1e8fa572af53ae2dd5f62 100644 (file)
@@ -858,6 +858,7 @@ static void acornfb_parse_dram(char *opt)
                case 'M':
                case 'm':
                        size *= 1024;
+                       /* Fall through */
                case 'K':
                case 'k':
                        size *= 1024;
index 90eca64e3144398a3c44472eb1a2c7e81d18d2b5..702cca59bda192a730f73648b5edd3b1b55ab533 100644 (file)
@@ -447,6 +447,7 @@ static int set_color_mode(struct omapfb_plane_struct *plane,
                return 0;
        case 12:
                var->bits_per_pixel = 16;
+               /* fall through */
        case 16:
                if (plane->fbdev->panel->bpp == 12)
                        plane->color_mode = OMAPFB_COLOR_RGB444;
@@ -1534,20 +1535,27 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
        case OMAPFB_ACTIVE:
                for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
                        unregister_framebuffer(fbdev->fb_info[i]);
+               /* fall through */
        case 7:
                omapfb_unregister_sysfs(fbdev);
+               /* fall through */
        case 6:
                if (fbdev->panel->disable)
                        fbdev->panel->disable(fbdev->panel);
+               /* fall through */
        case 5:
                omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
+               /* fall through */
        case 4:
                planes_cleanup(fbdev);
+               /* fall through */
        case 3:
                ctrl_cleanup(fbdev);
+               /* fall through */
        case 2:
                if (fbdev->panel->cleanup)
                        fbdev->panel->cleanup(fbdev->panel);
+               /* fall through */
        case 1:
                dev_set_drvdata(fbdev->dev, NULL);
                kfree(fbdev);
index c8be1c4f5b5566929d9dc1601bd8b05b6552402e..bdc08244a648dbf0ee58fe8b9dc4e5e36c15dcb8 100644 (file)
@@ -566,13 +566,17 @@ static inline int virtqueue_add_split(struct virtqueue *_vq,
 
 unmap_release:
        err_idx = i;
-       i = head;
+
+       if (indirect)
+               i = 0;
+       else
+               i = head;
 
        for (n = 0; n < total_sg; n++) {
                if (i == err_idx)
                        break;
                vring_unmap_one_split(vq, &desc[i]);
-               i = virtio16_to_cpu(_vq->vdev, vq->split.vring.desc[i].next);
+               i = virtio16_to_cpu(_vq->vdev, desc[i].next);
        }
 
        if (indirect)
index b9b2d06b387965eb206e1f08c6ffad7129b4f707..668a1c704f28063602b87a90713522d593be80d6 100644 (file)
@@ -235,6 +235,7 @@ static long ar7_wdt_ioctl(struct file *file,
                ar7_wdt_update_margin(new_margin);
                ar7_wdt_kick(1);
                spin_unlock(&wdt_lock);
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                if (put_user(margin, (int *)arg))
index 1b2cf5b95a89d301a14e8413bc1fcb2c47b17110..c3c93e00b32050947d6bd0a592915ba2a8fb4f03 100644 (file)
@@ -651,7 +651,7 @@ static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        return -EINVAL;
 
                pcwd_keepalive();
-               /* Fall */
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                return put_user(heartbeat, argp);
index 41a2a11535a6a8939cd48c0d7c3239b2ba889dc0..b35f7be20c00d08b12b7ef234d6c5f2214717aca 100644 (file)
@@ -134,7 +134,7 @@ static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        return -EINVAL;
                riowd_timeout = (new_margin + 59) / 60;
                riowd_writereg(p, riowd_timeout, WDTO_INDEX);
-               /* Fall */
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                return put_user(riowd_timeout * 60, (int __user *)argp);
index 5a6ced7a7e8f80a95ebc0ecba3e70c793caea701..202fc8d8ca5fa573385279ca14c6d7557784c71c 100644 (file)
@@ -202,6 +202,7 @@ static long sbwdog_ioctl(struct file *file, unsigned int cmd,
                timeout = time;
                sbwdog_set(user_dog, timeout);
                sbwdog_pet(user_dog);
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                /*
index efd7996694de6c994a282c2bc65a84a1db299e62..46268309ee9b86825eb5cc1a6155e4ca08430de1 100644 (file)
@@ -186,6 +186,7 @@ static long scx200_wdt_ioctl(struct file *file, unsigned int cmd,
                margin = new_margin;
                scx200_wdt_update_margin();
                scx200_wdt_ping();
+               /* Fall through */
        case WDIOC_GETTIMEOUT:
                if (put_user(margin, p))
                        return -EFAULT;
index 0650100fad001e1c337f7f9839e1dd82dc8945df..7d278b37e083d2bb4b8d5f0401593554e0e94a5b 100644 (file)
@@ -389,7 +389,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                if (wdt_set_heartbeat(new_heartbeat))
                        return -EINVAL;
                wdt_ping();
-               /* Fall */
+               /* Fall through */
        case WDIOC_GETTIMEOUT:
                return put_user(heartbeat, p);
        default:
index 4eacfb1ce1ac61b109292971194e57b7429bb644..eb729d704836b656ccb00972c878cd036f68b8d6 100644 (file)
@@ -168,7 +168,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
                soft_margin = new_margin;
                reload = soft_margin * (mem_fclk_21285 / 256);
                watchdog_ping();
-               /* Fall */
+               /* Fall through */
        case WDIOC_GETTIMEOUT:
                ret = put_user(soft_margin, int_arg);
                break;
index 567005d7598e244c70c3d923fb22e08ac61daff4..5c52c73e183993c6ce7713362bbcfd331e12d76a 100644 (file)
@@ -398,7 +398,7 @@ static long wdt977_ioctl(struct file *file, unsigned int cmd,
                        return -EINVAL;
 
                wdt977_keepalive();
-               /* Fall */
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                return put_user(timeout, uarg.i);
index 4c339c7e66e50d79312e00eee4c82492be5accab..a446a7221e13e9ac564ddf446e7fce84f8587420 100644 (file)
@@ -1143,7 +1143,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
                goto out_put_map;
 
        if (!use_ptemod) {
-               err = vm_map_pages(vma, map->pages, map->count);
+               err = vm_map_pages_zero(vma, map->pages, map->count);
                if (err)
                        goto out_put_map;
        } else {
index 2f5ce7230a43e88a1a6ffde1a528a370b8ea8595..c6070e70dd73d6229f522aa3cd890e830589a04d 100644 (file)
@@ -724,25 +724,6 @@ static long privcmd_ioctl_restrict(struct file *file, void __user *udata)
        return 0;
 }
 
-struct remap_pfn {
-       struct mm_struct *mm;
-       struct page **pages;
-       pgprot_t prot;
-       unsigned long i;
-};
-
-static int remap_pfn_fn(pte_t *ptep, unsigned long addr, void *data)
-{
-       struct remap_pfn *r = data;
-       struct page *page = r->pages[r->i];
-       pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), r->prot));
-
-       set_pte_at(r->mm, addr, ptep, pte);
-       r->i++;
-
-       return 0;
-}
-
 static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
 {
        struct privcmd_data *data = file->private_data;
@@ -774,7 +755,8 @@ static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
                goto out;
        }
 
-       if (xen_feature(XENFEAT_auto_translated_physmap)) {
+       if (IS_ENABLED(CONFIG_XEN_AUTO_XLATE) &&
+           xen_feature(XENFEAT_auto_translated_physmap)) {
                unsigned int nr = DIV_ROUND_UP(kdata.num, XEN_PFN_PER_PAGE);
                struct page **pages;
                unsigned int i;
@@ -808,16 +790,9 @@ static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata)
        if (rc)
                goto out;
 
-       if (xen_feature(XENFEAT_auto_translated_physmap)) {
-               struct remap_pfn r = {
-                       .mm = vma->vm_mm,
-                       .pages = vma->vm_private_data,
-                       .prot = vma->vm_page_prot,
-               };
-
-               rc = apply_to_page_range(r.mm, kdata.addr,
-                                        kdata.num << PAGE_SHIFT,
-                                        remap_pfn_fn, &r);
+       if (IS_ENABLED(CONFIG_XEN_AUTO_XLATE) &&
+           xen_feature(XENFEAT_auto_translated_physmap)) {
+               rc = xen_remap_vma_range(vma, kdata.addr, kdata.num << PAGE_SHIFT);
        } else {
                unsigned int domid =
                        (xdata.flags & XENMEM_rsrc_acq_caller_owned) ?
index cfbe46785a3b32ed76dca278fd3b2b93f1a41a3e..ae1df496bf384bdb3d8f9c37769326f4c95f01cb 100644 (file)
@@ -83,34 +83,18 @@ static inline dma_addr_t xen_virt_to_bus(void *address)
        return xen_phys_to_bus(virt_to_phys(address));
 }
 
-static int check_pages_physically_contiguous(unsigned long xen_pfn,
-                                            unsigned int offset,
-                                            size_t length)
+static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
 {
-       unsigned long next_bfn;
-       int i;
-       int nr_pages;
+       unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p);
+       unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size);
 
        next_bfn = pfn_to_bfn(xen_pfn);
-       nr_pages = (offset + length + XEN_PAGE_SIZE-1) >> XEN_PAGE_SHIFT;
 
-       for (i = 1; i < nr_pages; i++) {
+       for (i = 1; i < nr_pages; i++)
                if (pfn_to_bfn(++xen_pfn) != ++next_bfn)
-                       return 0;
-       }
-       return 1;
-}
+                       return 1;
 
-static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
-{
-       unsigned long xen_pfn = XEN_PFN_DOWN(p);
-       unsigned int offset = p & ~XEN_PAGE_MASK;
-
-       if (offset + size <= XEN_PAGE_SIZE)
-               return 0;
-       if (check_pages_physically_contiguous(xen_pfn, offset, size))
-               return 0;
-       return 1;
+       return 0;
 }
 
 static int is_xen_swiotlb_buffer(dma_addr_t dma_addr)
@@ -338,6 +322,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                        xen_free_coherent_pages(hwdev, size, ret, (dma_addr_t)phys, attrs);
                        return NULL;
                }
+               SetPageXenRemapped(virt_to_page(ret));
        }
        memset(ret, 0, size);
        return ret;
@@ -361,8 +346,9 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
        /* Convert the size to actually allocated. */
        size = 1UL << (order + XEN_PAGE_SHIFT);
 
-       if (((dev_addr + size - 1 <= dma_mask)) ||
-           range_straddles_page_boundary(phys, size))
+       if (!WARN_ON((dev_addr + size - 1 > dma_mask) ||
+                    range_straddles_page_boundary(phys, size)) &&
+           TestClearPageXenRemapped(virt_to_page(vaddr)))
                xen_destroy_contiguous_region(phys, order);
 
        xen_free_coherent_pages(hwdev, size, vaddr, (dma_addr_t)phys, attrs);
index 73427d8e01161ae55fa561599927bb68536bdbd0..e5694133ebe57f37950b134c26c3fbc2a231a221 100644 (file)
@@ -116,13 +116,12 @@ static int pm_ctrl_write(struct pci_dev *dev, int offset, u16 new_value,
 {
        int err;
        u16 old_value;
-       pci_power_t new_state, old_state;
+       pci_power_t new_state;
 
        err = pci_read_config_word(dev, offset, &old_value);
        if (err)
                goto out;
 
-       old_state = (pci_power_t)(old_value & PCI_PM_CTRL_STATE_MASK);
        new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK);
 
        new_value &= PM_OK_BITS;
index ba883a80b3c04db30fa08f8f21eba9f569c02598..7b1077f0abcb0839d89a299de2a9d9d60760943a 100644 (file)
@@ -262,3 +262,35 @@ int __init xen_xlate_map_ballooned_pages(xen_pfn_t **gfns, void **virt,
        return 0;
 }
 EXPORT_SYMBOL_GPL(xen_xlate_map_ballooned_pages);
+
+struct remap_pfn {
+       struct mm_struct *mm;
+       struct page **pages;
+       pgprot_t prot;
+       unsigned long i;
+};
+
+static int remap_pfn_fn(pte_t *ptep, unsigned long addr, void *data)
+{
+       struct remap_pfn *r = data;
+       struct page *page = r->pages[r->i];
+       pte_t pte = pte_mkspecial(pfn_pte(page_to_pfn(page), r->prot));
+
+       set_pte_at(r->mm, addr, ptep, pte);
+       r->i++;
+
+       return 0;
+}
+
+/* Used by the privcmd module, but has to be built-in on ARM */
+int xen_remap_vma_range(struct vm_area_struct *vma, unsigned long addr, unsigned long len)
+{
+       struct remap_pfn r = {
+               .mm = vma->vm_mm,
+               .pages = vma->vm_private_data,
+               .prot = vma->vm_page_prot,
+       };
+
+       return apply_to_page_range(vma->vm_mm, addr, len, remap_pfn_fn, &r);
+}
+EXPORT_SYMBOL_GPL(xen_remap_vma_range);
index a2a87117d2626220719cd10e71572c0e5f1b385d..fd5133e26a38b01af89ef488be709eed7987a7c5 100644 (file)
@@ -74,6 +74,7 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
                        cell = rcu_dereference_raw(net->ws_cell);
                        if (cell) {
                                afs_get_cell(cell);
+                               ret = 0;
                                break;
                        }
                        ret = -EDESTADDRREQ;
@@ -108,6 +109,9 @@ struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
 
        done_seqretry(&net->cells_lock, seq);
 
+       if (ret != 0 && cell)
+               afs_put_cell(net, cell);
+
        return ret == 0 ? cell : ERR_PTR(ret);
 }
 
index 4f1b6f466ff510d2899ae6f225ff5e0234875f15..b86195e4dc6cd657485eb01f62d103b4e06f7008 100644 (file)
@@ -505,18 +505,14 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
        struct afs_call *call = container_of(work, struct afs_call, work);
        struct afs_uuid *r = call->request;
 
-       struct {
-               __be32  match;
-       } reply;
-
        _enter("");
 
        if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0)
-               reply.match = htonl(0);
+               afs_send_empty_reply(call);
        else
-               reply.match = htonl(1);
+               rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
+                                       1, 1, "K-1");
 
-       afs_send_simple_reply(call, &reply, sizeof(reply));
        afs_put_call(call);
        _leave("");
 }
index e640d67274be2b06e64a83dd967670d72a1cbed4..139b4e3cc9464d81a72e980d5fc0077a5c8425c4 100644 (file)
@@ -440,7 +440,7 @@ static int afs_dir_iterate_block(struct afs_vnode *dvnode,
  * iterate through the data blob that lists the contents of an AFS directory
  */
 static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
-                          struct key *key)
+                          struct key *key, afs_dataversion_t *_dir_version)
 {
        struct afs_vnode *dvnode = AFS_FS_I(dir);
        struct afs_xdr_dir_page *dbuf;
@@ -460,6 +460,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
        req = afs_read_dir(dvnode, key);
        if (IS_ERR(req))
                return PTR_ERR(req);
+       *_dir_version = req->data_version;
 
        /* round the file position up to the next entry boundary */
        ctx->pos += sizeof(union afs_xdr_dirent) - 1;
@@ -514,7 +515,10 @@ out:
  */
 static int afs_readdir(struct file *file, struct dir_context *ctx)
 {
-       return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file));
+       afs_dataversion_t dir_version;
+
+       return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file),
+                              &dir_version);
 }
 
 /*
@@ -555,7 +559,8 @@ static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
  * - just returns the FID the dentry name maps to if found
  */
 static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
-                            struct afs_fid *fid, struct key *key)
+                            struct afs_fid *fid, struct key *key,
+                            afs_dataversion_t *_dir_version)
 {
        struct afs_super_info *as = dir->i_sb->s_fs_info;
        struct afs_lookup_one_cookie cookie = {
@@ -568,7 +573,7 @@ static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
        _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
 
        /* search the directory */
-       ret = afs_dir_iterate(dir, &cookie.ctx, key);
+       ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
        if (ret < 0) {
                _leave(" = %d [iter]", ret);
                return ret;
@@ -642,6 +647,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
        struct afs_server *server;
        struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
        struct inode *inode = NULL, *ti;
+       afs_dataversion_t data_version = READ_ONCE(dvnode->status.data_version);
        int ret, i;
 
        _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
@@ -669,12 +675,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
                cookie->fids[i].vid = as->volume->vid;
 
        /* search the directory */
-       ret = afs_dir_iterate(dir, &cookie->ctx, key);
+       ret = afs_dir_iterate(dir, &cookie->ctx, key, &data_version);
        if (ret < 0) {
                inode = ERR_PTR(ret);
                goto out;
        }
 
+       dentry->d_fsdata = (void *)(unsigned long)data_version;
+
        inode = ERR_PTR(-ENOENT);
        if (!cookie->found)
                goto out;
@@ -951,7 +959,8 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
                                 inode ? AFS_FS_I(inode) : NULL);
        } else {
                trace_afs_lookup(dvnode, &dentry->d_name,
-                                inode ? AFS_FS_I(inode) : NULL);
+                                IS_ERR_OR_NULL(inode) ? NULL
+                                : AFS_FS_I(inode));
        }
        return d;
 }
@@ -968,7 +977,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        struct dentry *parent;
        struct inode *inode;
        struct key *key;
-       long dir_version, de_version;
+       afs_dataversion_t dir_version;
+       long de_version;
        int ret;
 
        if (flags & LOOKUP_RCU)
@@ -1014,20 +1024,20 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
         * on a 32-bit system, we only have 32 bits in the dentry to store the
         * version.
         */
-       dir_version = (long)dir->status.data_version;
+       dir_version = dir->status.data_version;
        de_version = (long)dentry->d_fsdata;
-       if (de_version == dir_version)
-               goto out_valid;
+       if (de_version == (long)dir_version)
+               goto out_valid_noupdate;
 
-       dir_version = (long)dir->invalid_before;
-       if (de_version - dir_version >= 0)
+       dir_version = dir->invalid_before;
+       if (de_version - (long)dir_version >= 0)
                goto out_valid;
 
        _debug("dir modified");
        afs_stat_v(dir, n_reval);
 
        /* search the directory for this vnode */
-       ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key);
+       ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
        switch (ret) {
        case 0:
                /* the filename maps to something */
@@ -1080,7 +1090,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        }
 
 out_valid:
-       dentry->d_fsdata = (void *)dir_version;
+       dentry->d_fsdata = (void *)(unsigned long)dir_version;
+out_valid_noupdate:
        dput(parent);
        key_put(key);
        _leave(" = 1 [valid]");
@@ -1185,6 +1196,20 @@ static void afs_prep_for_new_inode(struct afs_fs_cursor *fc,
        iget_data->cb_s_break = fc->cbi->server->cb_s_break;
 }
 
+/*
+ * Note that a dentry got changed.  We need to set d_fsdata to the data version
+ * number derived from the result of the operation.  It doesn't matter if
+ * d_fsdata goes backwards as we'll just revalidate.
+ */
+static void afs_update_dentry_version(struct afs_fs_cursor *fc,
+                                     struct dentry *dentry,
+                                     struct afs_status_cb *scb)
+{
+       if (fc->ac.error == 0)
+               dentry->d_fsdata =
+                       (void *)(unsigned long)scb->status.data_version;
+}
+
 /*
  * create a directory on an AFS filesystem
  */
@@ -1227,6 +1252,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
                afs_check_for_remote_deletion(&fc, dvnode);
                afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
                                        &data_version, &scb[0]);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
@@ -1319,6 +1345,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 
                afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
                                        &data_version, scb);
+               afs_update_dentry_version(&fc, dentry, scb);
                ret = afs_end_vnode_operation(&fc);
                if (ret == 0) {
                        afs_dir_remove_subdir(dentry);
@@ -1458,6 +1485,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
                                        &data_version, &scb[0]);
                afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
                                        &data_version_2, &scb[1]);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                ret = afs_end_vnode_operation(&fc);
                if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
                        ret = afs_dir_remove_link(dvnode, dentry, key);
@@ -1526,6 +1554,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                afs_check_for_remote_deletion(&fc, dvnode);
                afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
                                        &data_version, &scb[0]);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
@@ -1607,6 +1636,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
                afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
                                        NULL, &scb[1]);
                ihold(&vnode->vfs_inode);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                d_instantiate(dentry, &vnode->vfs_inode);
 
                mutex_unlock(&vnode->io_lock);
@@ -1686,6 +1716,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
                afs_check_for_remote_deletion(&fc, dvnode);
                afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
                                        &data_version, &scb[0]);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
@@ -1791,6 +1822,17 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                }
        }
 
+       /* This bit is potentially nasty as there's a potential race with
+        * afs_d_revalidate{,_rcu}().  We have to change d_fsdata on the dentry
+        * to reflect it's new parent's new data_version after the op, but
+        * d_revalidate may see old_dentry between the op having taken place
+        * and the version being updated.
+        *
+        * So drop the old_dentry for now to make other threads go through
+        * lookup instead - which we hold a lock against.
+        */
+       d_drop(old_dentry);
+
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
                afs_dataversion_t orig_data_version;
@@ -1802,9 +1844,9 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                if (orig_dvnode != new_dvnode) {
                        if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
                                afs_end_vnode_operation(&fc);
-                               goto error_rehash;
+                               goto error_rehash_old;
                        }
-                       new_data_version = new_dvnode->status.data_version;
+                       new_data_version = new_dvnode->status.data_version + 1;
                } else {
                        new_data_version = orig_data_version;
                        new_scb = &scb[0];
@@ -1827,7 +1869,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                }
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
-                       goto error_rehash;
+                       goto error_rehash_old;
        }
 
        if (ret == 0) {
@@ -1853,10 +1895,26 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                drop_nlink(new_inode);
                        spin_unlock(&new_inode->i_lock);
                }
+
+               /* Now we can update d_fsdata on the dentries to reflect their
+                * new parent's data_version.
+                *
+                * Note that if we ever implement RENAME_EXCHANGE, we'll have
+                * to update both dentries with opposing dir versions.
+                */
+               if (new_dvnode != orig_dvnode) {
+                       afs_update_dentry_version(&fc, old_dentry, &scb[1]);
+                       afs_update_dentry_version(&fc, new_dentry, &scb[1]);
+               } else {
+                       afs_update_dentry_version(&fc, old_dentry, &scb[0]);
+                       afs_update_dentry_version(&fc, new_dentry, &scb[0]);
+               }
                d_move(old_dentry, new_dentry);
                goto error_tmp;
        }
 
+error_rehash_old:
+       d_rehash(new_dentry);
 error_rehash:
        if (rehash)
                d_rehash(rehash);
index 56b69576274d5b64cae3be2192f01838f201507d..dd3c55c9101c4e8475eca6a66e789a5f991d845d 100644 (file)
@@ -191,11 +191,13 @@ void afs_put_read(struct afs_read *req)
        int i;
 
        if (refcount_dec_and_test(&req->usage)) {
-               for (i = 0; i < req->nr_pages; i++)
-                       if (req->pages[i])
-                               put_page(req->pages[i]);
-               if (req->pages != req->array)
-                       kfree(req->pages);
+               if (req->pages) {
+                       for (i = 0; i < req->nr_pages; i++)
+                               if (req->pages[i])
+                                       put_page(req->pages[i]);
+                       if (req->pages != req->array)
+                               kfree(req->pages);
+               }
                kfree(req);
        }
 }
index 1ce73e014139be9240f19925e3333892c0be151f..114f281f3687880a9739a94d23228179f83b8bfa 100644 (file)
@@ -339,8 +339,9 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                        call->tmp_u = htonl(0);
                        afs_extract_to_tmp(call);
                }
+               /* Fall through */
 
-               /* Fall through - and extract the returned data length */
+               /* extract the returned data length */
        case 1:
                _debug("extract data length");
                ret = afs_extract_data(call, true);
@@ -366,8 +367,9 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                call->bvec[0].bv_page = req->pages[req->index];
                iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
                ASSERTCMP(size, <=, PAGE_SIZE);
+               /* Fall through */
 
-               /* Fall through - and extract the returned data */
+               /* extract the returned data */
        case 2:
                _debug("extract data %zu/%llu",
                       iov_iter_count(&call->iter), req->remain);
@@ -394,8 +396,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                /* Discard any excess data the server gave us */
                iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
                call->unmarshall = 3;
-
                /* Fall through */
+
        case 3:
                _debug("extract discard %zu/%llu",
                       iov_iter_count(&call->iter), req->actual_len - req->len);
@@ -407,8 +409,9 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
        no_more_data:
                call->unmarshall = 4;
                afs_extract_to_buf(call, (21 + 3 + 6) * 4);
+               /* Fall through */
 
-               /* Fall through - and extract the metadata */
+               /* extract the metadata */
        case 4:
                ret = afs_extract_data(call, false);
                if (ret < 0)
@@ -1471,8 +1474,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
        case 0:
                call->unmarshall++;
                afs_extract_to_buf(call, 12 * 4);
+               /* Fall through */
 
-               /* Fall through - and extract the returned status record */
+               /* extract the returned status record */
        case 1:
                _debug("extract status");
                ret = afs_extract_data(call, true);
@@ -1483,8 +1487,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus);
                call->unmarshall++;
                afs_extract_to_tmp(call);
+               /* Fall through */
 
-               /* Fall through - and extract the volume name length */
+               /* extract the volume name length */
        case 2:
                ret = afs_extract_data(call, true);
                if (ret < 0)
@@ -1498,8 +1503,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                size = (call->count + 3) & ~3; /* It's padded */
                afs_extract_to_buf(call, size);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the volume name */
+               /* extract the volume name */
        case 3:
                _debug("extract volname");
                ret = afs_extract_data(call, true);
@@ -1511,8 +1517,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                _debug("volname '%s'", p);
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the offline message length */
+               /* extract the offline message length */
        case 4:
                ret = afs_extract_data(call, true);
                if (ret < 0)
@@ -1526,8 +1533,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                size = (call->count + 3) & ~3; /* It's padded */
                afs_extract_to_buf(call, size);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the offline message */
+               /* extract the offline message */
        case 5:
                _debug("extract offline");
                ret = afs_extract_data(call, true);
@@ -1540,8 +1548,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
 
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the message of the day length */
+               /* extract the message of the day length */
        case 6:
                ret = afs_extract_data(call, true);
                if (ret < 0)
@@ -1555,8 +1564,9 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                size = (call->count + 3) & ~3; /* It's padded */
                afs_extract_to_buf(call, size);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the message of the day */
+               /* extract the message of the day */
        case 7:
                _debug("extract motd");
                ret = afs_extract_data(call, false);
@@ -1850,8 +1860,9 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call)
        case 0:
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the capabilities word count */
+               /* Extract the capabilities word count */
        case 1:
                ret = afs_extract_data(call, true);
                if (ret < 0)
@@ -1863,8 +1874,9 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call)
                call->count2 = count;
                iov_iter_discard(&call->iter, READ, count * sizeof(__be32));
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract capabilities words */
+               /* Extract capabilities words */
        case 2:
                ret = afs_extract_data(call, false);
                if (ret < 0)
@@ -2020,9 +2032,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
        case 0:
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
                /* Extract the file status count and array in two steps */
-               /* Fall through */
        case 1:
                _debug("extract status count");
                ret = afs_extract_data(call, true);
@@ -2039,8 +2051,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
                call->unmarshall++;
        more_counts:
                afs_extract_to_buf(call, 21 * sizeof(__be32));
-
                /* Fall through */
+
        case 2:
                _debug("extract status array %u", call->count);
                ret = afs_extract_data(call, true);
@@ -2060,9 +2072,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
                call->count = 0;
                call->unmarshall++;
                afs_extract_to_tmp(call);
+               /* Fall through */
 
                /* Extract the callback count and array in two steps */
-               /* Fall through */
        case 3:
                _debug("extract CB count");
                ret = afs_extract_data(call, true);
@@ -2078,8 +2090,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
                call->unmarshall++;
        more_cbs:
                afs_extract_to_buf(call, 3 * sizeof(__be32));
-
                /* Fall through */
+
        case 4:
                _debug("extract CB array");
                ret = afs_extract_data(call, true);
@@ -2096,8 +2108,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
 
                afs_extract_to_buf(call, 6 * sizeof(__be32));
                call->unmarshall++;
-
                /* Fall through */
+
        case 5:
                ret = afs_extract_data(call, false);
                if (ret < 0)
@@ -2193,6 +2205,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
        case 0:
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
                /* extract the returned data length */
        case 1:
@@ -2210,6 +2223,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
                acl->size = call->count2;
                afs_extract_begin(call, acl->data, size);
                call->unmarshall++;
+               /* Fall through */
 
                /* extract the returned data */
        case 2:
@@ -2219,6 +2233,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
 
                afs_extract_to_buf(call, (21 + 6) * 4);
                call->unmarshall++;
+               /* Fall through */
 
                /* extract the metadata */
        case 3:
index d7e0fd3c00df9e8ee52b97d272ffc6ae71effa8c..cfb0ac4bd039e672c14110ce8ad4eccb16706103 100644 (file)
@@ -56,23 +56,24 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
                struct afs_uuid__xdr *xdr;
                struct afs_uuid *uuid;
                int j;
+               int n = entry->nr_servers;
 
                tmp = ntohl(uvldb->serverFlags[i]);
                if (tmp & AFS_VLSF_DONTUSE ||
                    (new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
                        continue;
                if (tmp & AFS_VLSF_RWVOL) {
-                       entry->fs_mask[i] |= AFS_VOL_VTM_RW;
+                       entry->fs_mask[n] |= AFS_VOL_VTM_RW;
                        if (vlflags & AFS_VLF_BACKEXISTS)
-                               entry->fs_mask[i] |= AFS_VOL_VTM_BAK;
+                               entry->fs_mask[n] |= AFS_VOL_VTM_BAK;
                }
                if (tmp & AFS_VLSF_ROVOL)
-                       entry->fs_mask[i] |= AFS_VOL_VTM_RO;
-               if (!entry->fs_mask[i])
+                       entry->fs_mask[n] |= AFS_VOL_VTM_RO;
+               if (!entry->fs_mask[n])
                        continue;
 
                xdr = &uvldb->serverNumber[i];
-               uuid = (struct afs_uuid *)&entry->fs_server[i];
+               uuid = (struct afs_uuid *)&entry->fs_server[n];
                uuid->time_low                  = xdr->time_low;
                uuid->time_mid                  = htons(ntohl(xdr->time_mid));
                uuid->time_hi_and_version       = htons(ntohl(xdr->time_hi_and_version));
index 18722aaeda33a02ffb6a75c665f48ad3eb0fb88d..ca2452806ebf12ad0081c31ad0bd815cb9c01343 100644 (file)
@@ -450,8 +450,9 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                req->offset = req->pos & (PAGE_SIZE - 1);
                afs_extract_to_tmp64(call);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the returned data length */
+               /* extract the returned data length */
        case 1:
                _debug("extract data length");
                ret = afs_extract_data(call, true);
@@ -477,8 +478,9 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                call->bvec[0].bv_page = req->pages[req->index];
                iov_iter_bvec(&call->iter, READ, call->bvec, 1, size);
                ASSERTCMP(size, <=, PAGE_SIZE);
+               /* Fall through */
 
-               /* Fall through - and extract the returned data */
+               /* extract the returned data */
        case 2:
                _debug("extract data %zu/%llu",
                       iov_iter_count(&call->iter), req->remain);
@@ -505,8 +507,8 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                /* Discard any excess data the server gave us */
                iov_iter_discard(&call->iter, READ, req->actual_len - req->len);
                call->unmarshall = 3;
-
                /* Fall through */
+
        case 3:
                _debug("extract discard %zu/%llu",
                       iov_iter_count(&call->iter), req->actual_len - req->len);
@@ -521,8 +523,9 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                                   sizeof(struct yfs_xdr_YFSFetchStatus) +
                                   sizeof(struct yfs_xdr_YFSCallBack) +
                                   sizeof(struct yfs_xdr_YFSVolSync));
+               /* Fall through */
 
-               /* Fall through - and extract the metadata */
+               /* extract the metadata */
        case 4:
                ret = afs_extract_data(call, false);
                if (ret < 0)
@@ -539,8 +542,8 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                req->file_size = call->out_scb->status.size;
 
                call->unmarshall++;
-
                /* Fall through */
+
        case 5:
                break;
        }
@@ -1429,8 +1432,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
        case 0:
                call->unmarshall++;
                afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus));
+               /* Fall through */
 
-               /* Fall through - and extract the returned status record */
+               /* extract the returned status record */
        case 1:
                _debug("extract status");
                ret = afs_extract_data(call, true);
@@ -1441,8 +1445,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                xdr_decode_YFSFetchVolumeStatus(&bp, call->out_volstatus);
                call->unmarshall++;
                afs_extract_to_tmp(call);
+               /* Fall through */
 
-               /* Fall through - and extract the volume name length */
+               /* extract the volume name length */
        case 2:
                ret = afs_extract_data(call, true);
                if (ret < 0)
@@ -1456,8 +1461,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                size = (call->count + 3) & ~3; /* It's padded */
                afs_extract_to_buf(call, size);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the volume name */
+               /* extract the volume name */
        case 3:
                _debug("extract volname");
                ret = afs_extract_data(call, true);
@@ -1469,8 +1475,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                _debug("volname '%s'", p);
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the offline message length */
+               /* extract the offline message length */
        case 4:
                ret = afs_extract_data(call, true);
                if (ret < 0)
@@ -1484,8 +1491,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                size = (call->count + 3) & ~3; /* It's padded */
                afs_extract_to_buf(call, size);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the offline message */
+               /* extract the offline message */
        case 5:
                _debug("extract offline");
                ret = afs_extract_data(call, true);
@@ -1498,8 +1506,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
 
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the message of the day length */
+               /* extract the message of the day length */
        case 6:
                ret = afs_extract_data(call, true);
                if (ret < 0)
@@ -1513,8 +1522,9 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                size = (call->count + 3) & ~3; /* It's padded */
                afs_extract_to_buf(call, size);
                call->unmarshall++;
+               /* Fall through */
 
-               /* Fall through - and extract the message of the day */
+               /* extract the message of the day */
        case 7:
                _debug("extract motd");
                ret = afs_extract_data(call, false);
@@ -1526,8 +1536,8 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call)
                _debug("motd '%s'", p);
 
                call->unmarshall++;
-
                /* Fall through */
+
        case 8:
                break;
        }
@@ -1805,9 +1815,9 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
        case 0:
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
                /* Extract the file status count and array in two steps */
-               /* Fall through */
        case 1:
                _debug("extract status count");
                ret = afs_extract_data(call, true);
@@ -1824,8 +1834,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
                call->unmarshall++;
        more_counts:
                afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus));
-
                /* Fall through */
+
        case 2:
                _debug("extract status array %u", call->count);
                ret = afs_extract_data(call, true);
@@ -1845,9 +1855,9 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
                call->count = 0;
                call->unmarshall++;
                afs_extract_to_tmp(call);
+               /* Fall through */
 
                /* Extract the callback count and array in two steps */
-               /* Fall through */
        case 3:
                _debug("extract CB count");
                ret = afs_extract_data(call, true);
@@ -1863,8 +1873,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
                call->unmarshall++;
        more_cbs:
                afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack));
-
                /* Fall through */
+
        case 4:
                _debug("extract CB array");
                ret = afs_extract_data(call, true);
@@ -1881,8 +1891,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
 
                afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync));
                call->unmarshall++;
-
                /* Fall through */
+
        case 5:
                ret = afs_extract_data(call, false);
                if (ret < 0)
@@ -1892,8 +1902,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)
                xdr_decode_YFSVolSync(&bp, call->out_volsync);
 
                call->unmarshall++;
-
                /* Fall through */
+
        case 6:
                break;
        }
@@ -1978,6 +1988,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
        case 0:
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
                /* Extract the file ACL length */
        case 1:
@@ -1999,6 +2010,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
                        iov_iter_discard(&call->iter, READ, size);
                }
                call->unmarshall++;
+               /* Fall through */
 
                /* Extract the file ACL */
        case 2:
@@ -2008,6 +2020,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
 
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               /* Fall through */
 
                /* Extract the volume ACL length */
        case 3:
@@ -2029,6 +2042,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
                        iov_iter_discard(&call->iter, READ, size);
                }
                call->unmarshall++;
+               /* Fall through */
 
                /* Extract the volume ACL */
        case 4:
@@ -2041,6 +2055,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
                                   sizeof(struct yfs_xdr_YFSFetchStatus) +
                                   sizeof(struct yfs_xdr_YFSVolSync));
                call->unmarshall++;
+               /* Fall through */
 
                /* extract the metadata */
        case 5:
@@ -2057,6 +2072,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
                xdr_decode_YFSVolSync(&bp, call->out_volsync);
 
                call->unmarshall++;
+               /* Fall through */
 
        case 6:
                break;
@@ -2155,7 +2171,7 @@ int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl
               key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
 
        size = round_up(acl->size, 4);
-       call = afs_alloc_flat_call(net, &yfs_RXYFSStoreStatus,
+       call = afs_alloc_flat_call(net, &yfs_RXYFSStoreOpaqueACL2,
                                   sizeof(__be32) * 2 +
                                   sizeof(struct yfs_xdr_YFSFid) +
                                   sizeof(__be32) + size,
index 4707dfff991b55ddc9399e4f28797d81feae5e18..677cb364d33f0e43e65d25349fdcdce651a6ca5e 100644 (file)
@@ -1139,8 +1139,7 @@ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno)
  * Pointer to the block device containing @bdev on success, ERR_PTR()
  * value on failure.
  */
-static struct block_device *bd_start_claiming(struct block_device *bdev,
-                                             void *holder)
+struct block_device *bd_start_claiming(struct block_device *bdev, void *holder)
 {
        struct gendisk *disk;
        struct block_device *whole;
@@ -1187,6 +1186,62 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
                return ERR_PTR(err);
        }
 }
+EXPORT_SYMBOL(bd_start_claiming);
+
+static void bd_clear_claiming(struct block_device *whole, void *holder)
+{
+       lockdep_assert_held(&bdev_lock);
+       /* tell others that we're done */
+       BUG_ON(whole->bd_claiming != holder);
+       whole->bd_claiming = NULL;
+       wake_up_bit(&whole->bd_claiming, 0);
+}
+
+/**
+ * bd_finish_claiming - finish claiming of a block device
+ * @bdev: block device of interest
+ * @whole: whole block device (returned from bd_start_claiming())
+ * @holder: holder that has claimed @bdev
+ *
+ * Finish exclusive open of a block device. Mark the device as exlusively
+ * open by the holder and wake up all waiters for exclusive open to finish.
+ */
+void bd_finish_claiming(struct block_device *bdev, struct block_device *whole,
+                       void *holder)
+{
+       spin_lock(&bdev_lock);
+       BUG_ON(!bd_may_claim(bdev, whole, holder));
+       /*
+        * Note that for a whole device bd_holders will be incremented twice,
+        * and bd_holder will be set to bd_may_claim before being set to holder
+        */
+       whole->bd_holders++;
+       whole->bd_holder = bd_may_claim;
+       bdev->bd_holders++;
+       bdev->bd_holder = holder;
+       bd_clear_claiming(whole, holder);
+       spin_unlock(&bdev_lock);
+}
+EXPORT_SYMBOL(bd_finish_claiming);
+
+/**
+ * bd_abort_claiming - abort claiming of a block device
+ * @bdev: block device of interest
+ * @whole: whole block device (returned from bd_start_claiming())
+ * @holder: holder that has claimed @bdev
+ *
+ * Abort claiming of a block device when the exclusive open failed. This can be
+ * also used when exclusive open is not actually desired and we just needed
+ * to block other exclusive openers for a while.
+ */
+void bd_abort_claiming(struct block_device *bdev, struct block_device *whole,
+                      void *holder)
+{
+       spin_lock(&bdev_lock);
+       bd_clear_claiming(whole, holder);
+       spin_unlock(&bdev_lock);
+}
+EXPORT_SYMBOL(bd_abort_claiming);
 
 #ifdef CONFIG_SYSFS
 struct bd_holder_disk {
@@ -1656,29 +1711,10 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
 
                /* finish claiming */
                mutex_lock(&bdev->bd_mutex);
-               spin_lock(&bdev_lock);
-
-               if (!res) {
-                       BUG_ON(!bd_may_claim(bdev, whole, holder));
-                       /*
-                        * Note that for a whole device bd_holders
-                        * will be incremented twice, and bd_holder
-                        * will be set to bd_may_claim before being
-                        * set to holder
-                        */
-                       whole->bd_holders++;
-                       whole->bd_holder = bd_may_claim;
-                       bdev->bd_holders++;
-                       bdev->bd_holder = holder;
-               }
-
-               /* tell others that we're done */
-               BUG_ON(whole->bd_claiming != holder);
-               whole->bd_claiming = NULL;
-               wake_up_bit(&whole->bd_claiming, 0);
-
-               spin_unlock(&bdev_lock);
-
+               if (!res)
+                       bd_finish_claiming(bdev, whole, holder);
+               else
+                       bd_abort_claiming(bdev, whole, holder);
                /*
                 * Block event polling for write claims if requested.  Any
                 * write holder makes the write_holder state stick until
index 212b4a854f2c624359b7eeca9b1ae71e71324d1f..38651fae7f21aef15fd40f187d915144c9d3f952 100644 (file)
@@ -4,6 +4,7 @@ config BTRFS_FS
        tristate "Btrfs filesystem support"
        select CRYPTO
        select CRYPTO_CRC32C
+       select LIBCRC32C
        select ZLIB_INFLATE
        select ZLIB_DEFLATE
        select LZO_COMPRESS
index 89116afda7a20ff48f41e95a5f6e0ba8ff3da8d6..e5d85311d5d5d4eadd857fda99a99bd881074b38 100644 (file)
@@ -1483,7 +1483,7 @@ int btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr,
        ulist_init(roots);
        ulist_init(tmp);
 
-       trans = btrfs_attach_transaction(root);
+       trans = btrfs_join_transaction_nostart(root);
        if (IS_ERR(trans)) {
                if (PTR_ERR(trans) != -ENOENT && PTR_ERR(trans) != -EROFS) {
                        ret = PTR_ERR(trans);
index 299e11e6c554c00034df2e3941543434f00d911b..94660063a1628989108b5e15c5b1682e616b2dd3 100644 (file)
@@ -401,7 +401,6 @@ struct btrfs_dev_replace {
 struct raid_kobject {
        u64 flags;
        struct kobject kobj;
-       struct list_head list;
 };
 
 /*
@@ -915,8 +914,6 @@ struct btrfs_fs_info {
        u32 thread_pool_size;
 
        struct kobject *space_info_kobj;
-       struct list_head pending_raid_kobjs;
-       spinlock_t pending_raid_kobjs_lock; /* uncontended */
 
        u64 total_pinned;
 
@@ -2698,7 +2695,6 @@ int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr);
 int btrfs_make_block_group(struct btrfs_trans_handle *trans,
                           u64 bytes_used, u64 type, u64 chunk_offset,
                           u64 size);
-void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info);
 struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
                                struct btrfs_fs_info *fs_info,
                                const u64 chunk_offset);
index 41a2bd2e0c56d333bcc5f2792b9ca6cb277a184f..97beb351a10cdc0117bc41b5dade4d01eb916093 100644 (file)
@@ -2683,8 +2683,6 @@ int open_ctree(struct super_block *sb,
        INIT_LIST_HEAD(&fs_info->delayed_iputs);
        INIT_LIST_HEAD(&fs_info->delalloc_roots);
        INIT_LIST_HEAD(&fs_info->caching_block_groups);
-       INIT_LIST_HEAD(&fs_info->pending_raid_kobjs);
-       spin_lock_init(&fs_info->pending_raid_kobjs_lock);
        spin_lock_init(&fs_info->delalloc_root_lock);
        spin_lock_init(&fs_info->trans_lock);
        spin_lock_init(&fs_info->fs_roots_radix_lock);
@@ -4106,6 +4104,7 @@ void close_ctree(struct btrfs_fs_info *fs_info)
        percpu_counter_destroy(&fs_info->dev_replace.bio_counter);
        cleanup_srcu_struct(&fs_info->subvol_srcu);
 
+       btrfs_free_csum_hash(fs_info);
        btrfs_free_stripe_hash_table(fs_info);
        btrfs_free_ref_cache(fs_info);
 }
index d3b58e388535e704d7f0c4c961c2f068f19d1856..8b7eb22d508a597b3bcc97f018c096f6d251e715 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 #include <linux/sched/signal.h>
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
@@ -7888,33 +7889,6 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
        return 0;
 }
 
-/* link_block_group will queue up kobjects to add when we're reclaim-safe */
-void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info)
-{
-       struct btrfs_space_info *space_info;
-       struct raid_kobject *rkobj;
-       LIST_HEAD(list);
-       int ret = 0;
-
-       spin_lock(&fs_info->pending_raid_kobjs_lock);
-       list_splice_init(&fs_info->pending_raid_kobjs, &list);
-       spin_unlock(&fs_info->pending_raid_kobjs_lock);
-
-       list_for_each_entry(rkobj, &list, list) {
-               space_info = btrfs_find_space_info(fs_info, rkobj->flags);
-
-               ret = kobject_add(&rkobj->kobj, &space_info->kobj,
-                               "%s", btrfs_bg_type_to_raid_name(rkobj->flags));
-               if (ret) {
-                       kobject_put(&rkobj->kobj);
-                       break;
-               }
-       }
-       if (ret)
-               btrfs_warn(fs_info,
-                          "failed to add kobject for block cache, ignoring");
-}
-
 static void link_block_group(struct btrfs_block_group_cache *cache)
 {
        struct btrfs_space_info *space_info = cache->space_info;
@@ -7929,18 +7903,36 @@ static void link_block_group(struct btrfs_block_group_cache *cache)
        up_write(&space_info->groups_sem);
 
        if (first) {
-               struct raid_kobject *rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS);
+               struct raid_kobject *rkobj;
+               unsigned int nofs_flag;
+               int ret;
+
+               /*
+                * Setup a NOFS context because kobject_add(), deep in its call
+                * chain, does GFP_KERNEL allocations, and we are often called
+                * in a context where if reclaim is triggered we can deadlock
+                * (we are either holding a transaction handle or some lock
+                * required for a transaction commit).
+                */
+               nofs_flag = memalloc_nofs_save();
+               rkobj = kzalloc(sizeof(*rkobj), GFP_KERNEL);
                if (!rkobj) {
+                       memalloc_nofs_restore(nofs_flag);
                        btrfs_warn(cache->fs_info,
                                "couldn't alloc memory for raid level kobject");
                        return;
                }
                rkobj->flags = cache->flags;
                kobject_init(&rkobj->kobj, &btrfs_raid_ktype);
-
-               spin_lock(&fs_info->pending_raid_kobjs_lock);
-               list_add_tail(&rkobj->list, &fs_info->pending_raid_kobjs);
-               spin_unlock(&fs_info->pending_raid_kobjs_lock);
+               ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s",
+                                 btrfs_bg_type_to_raid_name(rkobj->flags));
+               memalloc_nofs_restore(nofs_flag);
+               if (ret) {
+                       kobject_put(&rkobj->kobj);
+                       btrfs_warn(fs_info,
+                          "failed to add kobject for block cache, ignoring");
+                       return;
+               }
                space_info->block_group_kobjs[index] = &rkobj->kobj;
        }
 }
@@ -8206,7 +8198,6 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                        inc_block_group_ro(cache, 1);
        }
 
-       btrfs_add_raid_kobjects(info);
        btrfs_init_global_block_rsv(info);
        ret = check_chunk_block_group_mappings(info);
 error:
@@ -8975,6 +8966,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
        struct btrfs_device *device;
        struct list_head *devices;
        u64 group_trimmed;
+       u64 range_end = U64_MAX;
        u64 start;
        u64 end;
        u64 trimmed = 0;
@@ -8984,16 +8976,23 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
        int dev_ret = 0;
        int ret = 0;
 
+       /*
+        * Check range overflow if range->len is set.
+        * The default range->len is U64_MAX.
+        */
+       if (range->len != U64_MAX &&
+           check_add_overflow(range->start, range->len, &range_end))
+               return -EINVAL;
+
        cache = btrfs_lookup_first_block_group(fs_info, range->start);
        for (; cache; cache = next_block_group(cache)) {
-               if (cache->key.objectid >= (range->start + range->len)) {
+               if (cache->key.objectid >= range_end) {
                        btrfs_put_block_group(cache);
                        break;
                }
 
                start = max(range->start, cache->key.objectid);
-               end = min(range->start + range->len,
-                               cache->key.objectid + cache->key.offset);
+               end = min(range_end, cache->key.objectid + cache->key.offset);
 
                if (end - start >= range->minlen) {
                        if (!block_group_cache_done(cache)) {
index 1ff438fd5bc2906499a0eb075e8c38740e64be7b..eeb75281894ed6a3ad41dfe53d9f1fa7df2d84dc 100644 (file)
@@ -3628,6 +3628,13 @@ void wait_on_extent_buffer_writeback(struct extent_buffer *eb)
                       TASK_UNINTERRUPTIBLE);
 }
 
+static void end_extent_buffer_writeback(struct extent_buffer *eb)
+{
+       clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
+       smp_mb__after_atomic();
+       wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
+}
+
 /*
  * Lock eb pages and flush the bio if we can't the locks
  *
@@ -3699,8 +3706,11 @@ static noinline_for_stack int lock_extent_buffer_for_io(struct extent_buffer *eb
 
                if (!trylock_page(p)) {
                        if (!flush) {
-                               ret = flush_write_bio(epd);
-                               if (ret < 0) {
+                               int err;
+
+                               err = flush_write_bio(epd);
+                               if (err < 0) {
+                                       ret = err;
                                        failed_page_nr = i;
                                        goto err_unlock;
                                }
@@ -3715,16 +3725,23 @@ err_unlock:
        /* Unlock already locked pages */
        for (i = 0; i < failed_page_nr; i++)
                unlock_page(eb->pages[i]);
+       /*
+        * Clear EXTENT_BUFFER_WRITEBACK and wake up anyone waiting on it.
+        * Also set back EXTENT_BUFFER_DIRTY so future attempts to this eb can
+        * be made and undo everything done before.
+        */
+       btrfs_tree_lock(eb);
+       spin_lock(&eb->refs_lock);
+       set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
+       end_extent_buffer_writeback(eb);
+       spin_unlock(&eb->refs_lock);
+       percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, eb->len,
+                                fs_info->dirty_metadata_batch);
+       btrfs_clear_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
+       btrfs_tree_unlock(eb);
        return ret;
 }
 
-static void end_extent_buffer_writeback(struct extent_buffer *eb)
-{
-       clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
-       smp_mb__after_atomic();
-       wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
-}
-
 static void set_btree_ioerr(struct page *page)
 {
        struct extent_buffer *eb = (struct extent_buffer *)page->private;
index 1af069a9a0c7205b4ba7649463dcba5288f9c36f..ee582a36653d30ee1f833153f9bc00225f7978ae 100644 (file)
@@ -395,10 +395,31 @@ static noinline int add_async_extent(struct async_chunk *cow,
        return 0;
 }
 
+/*
+ * Check if the inode has flags compatible with compression
+ */
+static inline bool inode_can_compress(struct inode *inode)
+{
+       if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW ||
+           BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)
+               return false;
+       return true;
+}
+
+/*
+ * Check if the inode needs to be submitted to compression, based on mount
+ * options, defragmentation, properties or heuristics.
+ */
 static inline int inode_need_compress(struct inode *inode, u64 start, u64 end)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
 
+       if (!inode_can_compress(inode)) {
+               WARN(IS_ENABLED(CONFIG_BTRFS_DEBUG),
+                       KERN_ERR "BTRFS: unexpected compression for ino %llu\n",
+                       btrfs_ino(BTRFS_I(inode)));
+               return 0;
+       }
        /* force compress */
        if (btrfs_test_opt(fs_info, FORCE_COMPRESS))
                return 1;
@@ -1631,7 +1652,8 @@ int btrfs_run_delalloc_range(struct inode *inode, struct page *locked_page,
        } else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC && !force_cow) {
                ret = run_delalloc_nocow(inode, locked_page, start, end,
                                         page_started, 0, nr_written);
-       } else if (!inode_need_compress(inode, start, end)) {
+       } else if (!inode_can_compress(inode) ||
+                  !inode_need_compress(inode, start, end)) {
                ret = cow_file_range(inode, locked_page, start, end, end,
                                      page_started, nr_written, 1, NULL);
        } else {
index 98fccce4208ca2d22e823253298d605f4545c337..393eceda57c8a2d8d31eb3e4b5e45db3fe697c32 100644 (file)
@@ -346,9 +346,12 @@ void btrfs_tree_unlock(struct extent_buffer *eb)
        if (blockers) {
                btrfs_assert_no_spinning_writers(eb);
                eb->blocking_writers--;
-               /* Use the lighter barrier after atomic */
-               smp_mb__after_atomic();
-               cond_wake_up_nomb(&eb->write_lock_wq);
+               /*
+                * We need to order modifying blocking_writers above with
+                * actually waking up the sleepers to ensure they see the
+                * updated value of blocking_writers
+                */
+               cond_wake_up(&eb->write_lock_wq);
        } else {
                btrfs_assert_spinning_writers_put(eb);
                write_unlock(&eb->lock);
index 1744ba8b275497b5a6cb5d65432ee4b4e645564d..ae7f64a8facb8758822f5cbd05f0bd0094de361a 100644 (file)
@@ -985,13 +985,14 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
                                        struct extent_state **cached_state)
 {
        struct btrfs_ordered_extent *ordered;
-       struct extent_state *cachedp = NULL;
+       struct extent_state *cache = NULL;
+       struct extent_state **cachedp = &cache;
 
        if (cached_state)
-               cachedp = *cached_state;
+               cachedp = cached_state;
 
        while (1) {
-               lock_extent_bits(tree, start, end, &cachedp);
+               lock_extent_bits(tree, start, end, cachedp);
                ordered = btrfs_lookup_ordered_range(inode, start,
                                                     end - start + 1);
                if (!ordered) {
@@ -1001,10 +1002,10 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
                         * aren't exposing it outside of this function
                         */
                        if (!cached_state)
-                               refcount_dec(&cachedp->refs);
+                               refcount_dec(&cache->refs);
                        break;
                }
-               unlock_extent_cached(tree, start, end, &cachedp);
+               unlock_extent_cached(tree, start, end, cachedp);
                btrfs_start_ordered_extent(&inode->vfs_inode, ordered, 1);
                btrfs_put_ordered_extent(ordered);
        }
index 69b59bf75882eff54415e03ef08943db946ef087..c3c0c064c25dadd317841e1d2761e2629b6ec9f3 100644 (file)
@@ -6322,68 +6322,21 @@ static int changed_extent(struct send_ctx *sctx,
 {
        int ret = 0;
 
-       if (sctx->cur_ino != sctx->cmp_key->objectid) {
-
-               if (result == BTRFS_COMPARE_TREE_CHANGED) {
-                       struct extent_buffer *leaf_l;
-                       struct extent_buffer *leaf_r;
-                       struct btrfs_file_extent_item *ei_l;
-                       struct btrfs_file_extent_item *ei_r;
-
-                       leaf_l = sctx->left_path->nodes[0];
-                       leaf_r = sctx->right_path->nodes[0];
-                       ei_l = btrfs_item_ptr(leaf_l,
-                                             sctx->left_path->slots[0],
-                                             struct btrfs_file_extent_item);
-                       ei_r = btrfs_item_ptr(leaf_r,
-                                             sctx->right_path->slots[0],
-                                             struct btrfs_file_extent_item);
-
-                       /*
-                        * We may have found an extent item that has changed
-                        * only its disk_bytenr field and the corresponding
-                        * inode item was not updated. This case happens due to
-                        * very specific timings during relocation when a leaf
-                        * that contains file extent items is COWed while
-                        * relocation is ongoing and its in the stage where it
-                        * updates data pointers. So when this happens we can
-                        * safely ignore it since we know it's the same extent,
-                        * but just at different logical and physical locations
-                        * (when an extent is fully replaced with a new one, we
-                        * know the generation number must have changed too,
-                        * since snapshot creation implies committing the current
-                        * transaction, and the inode item must have been updated
-                        * as well).
-                        * This replacement of the disk_bytenr happens at
-                        * relocation.c:replace_file_extents() through
-                        * relocation.c:btrfs_reloc_cow_block().
-                        */
-                       if (btrfs_file_extent_generation(leaf_l, ei_l) ==
-                           btrfs_file_extent_generation(leaf_r, ei_r) &&
-                           btrfs_file_extent_ram_bytes(leaf_l, ei_l) ==
-                           btrfs_file_extent_ram_bytes(leaf_r, ei_r) &&
-                           btrfs_file_extent_compression(leaf_l, ei_l) ==
-                           btrfs_file_extent_compression(leaf_r, ei_r) &&
-                           btrfs_file_extent_encryption(leaf_l, ei_l) ==
-                           btrfs_file_extent_encryption(leaf_r, ei_r) &&
-                           btrfs_file_extent_other_encoding(leaf_l, ei_l) ==
-                           btrfs_file_extent_other_encoding(leaf_r, ei_r) &&
-                           btrfs_file_extent_type(leaf_l, ei_l) ==
-                           btrfs_file_extent_type(leaf_r, ei_r) &&
-                           btrfs_file_extent_disk_bytenr(leaf_l, ei_l) !=
-                           btrfs_file_extent_disk_bytenr(leaf_r, ei_r) &&
-                           btrfs_file_extent_disk_num_bytes(leaf_l, ei_l) ==
-                           btrfs_file_extent_disk_num_bytes(leaf_r, ei_r) &&
-                           btrfs_file_extent_offset(leaf_l, ei_l) ==
-                           btrfs_file_extent_offset(leaf_r, ei_r) &&
-                           btrfs_file_extent_num_bytes(leaf_l, ei_l) ==
-                           btrfs_file_extent_num_bytes(leaf_r, ei_r))
-                               return 0;
-               }
-
-               inconsistent_snapshot_error(sctx, result, "extent");
-               return -EIO;
-       }
+       /*
+        * We have found an extent item that changed without the inode item
+        * having changed. This can happen either after relocation (where the
+        * disk_bytenr of an extent item is replaced at
+        * relocation.c:replace_file_extents()) or after deduplication into a
+        * file in both the parent and send snapshots (where an extent item can
+        * get modified or replaced with a new one). Note that deduplication
+        * updates the inode item, but it only changes the iversion (sequence
+        * field in the inode item) of the inode, so if a file is deduplicated
+        * the same amount of times in both the parent and send snapshots, its
+        * iversion becames the same in both snapshots, whence the inode item is
+        * the same on both snapshots.
+        */
+       if (sctx->cur_ino != sctx->cmp_key->objectid)
+               return 0;
 
        if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) {
                if (result != BTRFS_COMPARE_TREE_DELETED)
index 3b8ae1a8f02df77769542a3c0a0782f452c8c791..e3adb714c04b364869e9da5c36e2f9fa0157b7fb 100644 (file)
@@ -28,15 +28,18 @@ static const unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = {
        [TRANS_STATE_COMMIT_START]      = (__TRANS_START | __TRANS_ATTACH),
        [TRANS_STATE_COMMIT_DOING]      = (__TRANS_START |
                                           __TRANS_ATTACH |
-                                          __TRANS_JOIN),
+                                          __TRANS_JOIN |
+                                          __TRANS_JOIN_NOSTART),
        [TRANS_STATE_UNBLOCKED]         = (__TRANS_START |
                                           __TRANS_ATTACH |
                                           __TRANS_JOIN |
-                                          __TRANS_JOIN_NOLOCK),
+                                          __TRANS_JOIN_NOLOCK |
+                                          __TRANS_JOIN_NOSTART),
        [TRANS_STATE_COMPLETED]         = (__TRANS_START |
                                           __TRANS_ATTACH |
                                           __TRANS_JOIN |
-                                          __TRANS_JOIN_NOLOCK),
+                                          __TRANS_JOIN_NOLOCK |
+                                          __TRANS_JOIN_NOSTART),
 };
 
 void btrfs_put_transaction(struct btrfs_transaction *transaction)
@@ -543,7 +546,8 @@ again:
                ret = join_transaction(fs_info, type);
                if (ret == -EBUSY) {
                        wait_current_trans(fs_info);
-                       if (unlikely(type == TRANS_ATTACH))
+                       if (unlikely(type == TRANS_ATTACH ||
+                                    type == TRANS_JOIN_NOSTART))
                                ret = -ENOENT;
                }
        } while (ret == -EBUSY);
@@ -659,6 +663,16 @@ struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root
                                 BTRFS_RESERVE_NO_FLUSH, true);
 }
 
+/*
+ * Similar to regular join but it never starts a transaction when none is
+ * running or after waiting for the current one to finish.
+ */
+struct btrfs_trans_handle *btrfs_join_transaction_nostart(struct btrfs_root *root)
+{
+       return start_transaction(root, 0, TRANS_JOIN_NOSTART,
+                                BTRFS_RESERVE_NO_FLUSH, true);
+}
+
 /*
  * btrfs_attach_transaction() - catch the running transaction
  *
@@ -2037,6 +2051,16 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
                }
        } else {
                spin_unlock(&fs_info->trans_lock);
+               /*
+                * The previous transaction was aborted and was already removed
+                * from the list of transactions at fs_info->trans_list. So we
+                * abort to prevent writing a new superblock that reflects a
+                * corrupt state (pointing to trees with unwritten nodes/leafs).
+                */
+               if (test_bit(BTRFS_FS_STATE_TRANS_ABORTED, &fs_info->fs_state)) {
+                       ret = -EROFS;
+                       goto cleanup_transaction;
+               }
        }
 
        extwriter_counter_dec(cur_trans, trans->type);
index 527ea94b57d91a6c289cb4b4b67f6a07ecb85934..2c5a6f6e5bb0904eecef07941f9ad76f3ba2f036 100644 (file)
@@ -94,11 +94,13 @@ struct btrfs_transaction {
 #define __TRANS_JOIN           (1U << 11)
 #define __TRANS_JOIN_NOLOCK    (1U << 12)
 #define __TRANS_DUMMY          (1U << 13)
+#define __TRANS_JOIN_NOSTART   (1U << 14)
 
 #define TRANS_START            (__TRANS_START | __TRANS_FREEZABLE)
 #define TRANS_ATTACH           (__TRANS_ATTACH)
 #define TRANS_JOIN             (__TRANS_JOIN | __TRANS_FREEZABLE)
 #define TRANS_JOIN_NOLOCK      (__TRANS_JOIN_NOLOCK)
+#define TRANS_JOIN_NOSTART     (__TRANS_JOIN_NOSTART)
 
 #define TRANS_EXTWRITERS       (__TRANS_START | __TRANS_ATTACH)
 
@@ -183,6 +185,7 @@ struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
                                        int min_factor);
 struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root);
 struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root);
+struct btrfs_trans_handle *btrfs_join_transaction_nostart(struct btrfs_root *root);
 struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root);
 struct btrfs_trans_handle *btrfs_attach_transaction_barrier(
                                        struct btrfs_root *root);
index 6c8297bcfeb7caa63bc2b39bdd06b5a1f7708489..1bfd7e34f31e33709f0e937f83c6d978d74564c6 100644 (file)
@@ -4985,7 +4985,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
                                                      BTRFS_I(inode),
                                                      LOG_OTHER_INODE_ALL,
                                                      0, LLONG_MAX, ctx);
-                                       iput(inode);
+                                       btrfs_add_delayed_iput(inode);
                                }
                        }
                        continue;
@@ -5000,7 +5000,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
                ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
                                      LOG_OTHER_INODE, 0, LLONG_MAX, ctx);
                if (ret) {
-                       iput(inode);
+                       btrfs_add_delayed_iput(inode);
                        continue;
                }
 
@@ -5009,7 +5009,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
                key.offset = 0;
                ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
                if (ret < 0) {
-                       iput(inode);
+                       btrfs_add_delayed_iput(inode);
                        continue;
                }
 
@@ -5056,7 +5056,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
                        }
                        path->slots[0]++;
                }
-               iput(inode);
+               btrfs_add_delayed_iput(inode);
        }
 
        return ret;
@@ -5689,7 +5689,7 @@ process_leaf:
                        }
 
                        if (btrfs_inode_in_log(BTRFS_I(di_inode), trans->transid)) {
-                               iput(di_inode);
+                               btrfs_add_delayed_iput(di_inode);
                                break;
                        }
 
@@ -5701,7 +5701,7 @@ process_leaf:
                        if (!ret &&
                            btrfs_must_commit_transaction(trans, BTRFS_I(di_inode)))
                                ret = 1;
-                       iput(di_inode);
+                       btrfs_add_delayed_iput(di_inode);
                        if (ret)
                                goto next_dir_inode;
                        if (ctx->log_new_dentries) {
@@ -5848,7 +5848,7 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,
                        if (!ret && ctx && ctx->log_new_dentries)
                                ret = log_new_dir_dentries(trans, root,
                                                   BTRFS_I(dir_inode), ctx);
-                       iput(dir_inode);
+                       btrfs_add_delayed_iput(dir_inode);
                        if (ret)
                                goto out;
                }
@@ -5891,7 +5891,7 @@ static int log_new_ancestors(struct btrfs_trans_handle *trans,
                        ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
                                              LOG_INODE_EXISTS,
                                              0, LLONG_MAX, ctx);
-               iput(inode);
+               btrfs_add_delayed_iput(inode);
                if (ret)
                        return ret;
 
index a13ddba1ebc3b75f9fc0f301036d0d7979a74c1d..a447d3ec48d506b848e1ab228fc0ce55fb0f87c7 100644 (file)
@@ -3087,16 +3087,6 @@ static int btrfs_relocate_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset)
        if (ret)
                return ret;
 
-       /*
-        * We add the kobjects here (and after forcing data chunk creation)
-        * since relocation is the only place we'll create chunks of a new
-        * type at runtime.  The only place where we'll remove the last
-        * chunk of a type is the call immediately below this one.  Even
-        * so, we're protected against races with the cleaner thread since
-        * we're covered by the delete_unused_bgs_mutex.
-        */
-       btrfs_add_raid_kobjects(fs_info);
-
        trans = btrfs_start_trans_remove_block_group(root->fs_info,
                                                     chunk_offset);
        if (IS_ERR(trans)) {
@@ -3223,9 +3213,6 @@ static int btrfs_may_alloc_data_chunk(struct btrfs_fs_info *fs_info,
                        btrfs_end_transaction(trans);
                        if (ret < 0)
                                return ret;
-
-                       btrfs_add_raid_kobjects(fs_info);
-
                        return 1;
                }
        }
@@ -5941,6 +5928,7 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        u64 stripe_len;
        u64 raid56_full_stripe_start = (u64)-1;
        int data_stripes;
+       int ret = 0;
 
        ASSERT(op != BTRFS_MAP_DISCARD);
 
@@ -5961,8 +5949,8 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                btrfs_crit(fs_info,
 "stripe math has gone wrong, stripe_offset=%llu offset=%llu start=%llu logical=%llu stripe_len=%llu",
                        stripe_offset, offset, em->start, logical, stripe_len);
-               free_extent_map(em);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        /* stripe_offset is the offset of this block in its stripe */
@@ -6009,7 +5997,10 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        io_geom->stripe_offset = stripe_offset;
        io_geom->raid56_stripe_offset = raid56_full_stripe_start;
 
-       return 0;
+out:
+       /* once for us */
+       free_extent_map(em);
+       return ret;
 }
 
 static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
index e078cc55b989e287e8d3891f8294778b995598f5..b3c8b886bf647d71c7d93af58f89d619aa81cd35 100644 (file)
@@ -913,8 +913,9 @@ get_more_pages:
                        if (page_offset(page) >= ceph_wbc.i_size) {
                                dout("%p page eof %llu\n",
                                     page, ceph_wbc.i_size);
-                               if (ceph_wbc.size_stable ||
-                                   page_offset(page) >= i_size_read(inode))
+                               if ((ceph_wbc.size_stable ||
+                                   page_offset(page) >= i_size_read(inode)) &&
+                                   clear_page_dirty_for_io(page))
                                        mapping->a_ops->invalidatepage(page,
                                                                0, PAGE_SIZE);
                                unlock_page(page);
index d98dcd976c8004249c72419b671a6089b350f5f2..ce0f5658720ab9d06764c1f63dbe3d267ffb336f 100644 (file)
@@ -1301,6 +1301,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
 {
        struct ceph_inode_info *ci = cap->ci;
        struct inode *inode = &ci->vfs_inode;
+       struct ceph_buffer *old_blob = NULL;
        struct cap_msg_args arg;
        int held, revoking;
        int wake = 0;
@@ -1365,7 +1366,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
        ci->i_requested_max_size = arg.max_size;
 
        if (flushing & CEPH_CAP_XATTR_EXCL) {
-               __ceph_build_xattrs_blob(ci);
+               old_blob = __ceph_build_xattrs_blob(ci);
                arg.xattr_version = ci->i_xattrs.version;
                arg.xattr_buf = ci->i_xattrs.blob;
        } else {
@@ -1409,6 +1410,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
 
        spin_unlock(&ci->i_ceph_lock);
 
+       ceph_buffer_put(old_blob);
+
        ret = send_cap_msg(&arg);
        if (ret < 0) {
                dout("error sending cap msg, must requeue %p\n", inode);
index 791f84a13bb8e16daad628d07e0e8573024c4a3f..18500edefc56f8f53fd70984116e477cd437b77f 100644 (file)
@@ -736,6 +736,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
        int issued, new_issued, info_caps;
        struct timespec64 mtime, atime, ctime;
        struct ceph_buffer *xattr_blob = NULL;
+       struct ceph_buffer *old_blob = NULL;
        struct ceph_string *pool_ns = NULL;
        struct ceph_cap *new_cap = NULL;
        int err = 0;
@@ -881,7 +882,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
        if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL))  &&
            le64_to_cpu(info->xattr_version) > ci->i_xattrs.version) {
                if (ci->i_xattrs.blob)
-                       ceph_buffer_put(ci->i_xattrs.blob);
+                       old_blob = ci->i_xattrs.blob;
                ci->i_xattrs.blob = xattr_blob;
                if (xattr_blob)
                        memcpy(ci->i_xattrs.blob->vec.iov_base,
@@ -1022,8 +1023,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
 out:
        if (new_cap)
                ceph_put_cap(mdsc, new_cap);
-       if (xattr_blob)
-               ceph_buffer_put(xattr_blob);
+       ceph_buffer_put(old_blob);
+       ceph_buffer_put(xattr_blob);
        ceph_put_string(pool_ns);
        return err;
 }
index ac9b53b893650270b80ccf5a69a954e55346922f..5083e238ad15fdd62ee7c92e5228f67ea69eb493 100644 (file)
@@ -111,8 +111,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode,
                req->r_wait_for_completion = ceph_lock_wait_for_completion;
 
        err = ceph_mdsc_do_request(mdsc, inode, req);
-
-       if (operation == CEPH_MDS_OP_GETFILELOCK) {
+       if (!err && operation == CEPH_MDS_OP_GETFILELOCK) {
                fl->fl_pid = -le64_to_cpu(req->r_reply_info.filelock_reply->pid);
                if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
                        fl->fl_type = F_RDLCK;
index 4c6494eb02b535df4c8f0f46d88ea1a8696304a5..ccfcc66aaf442030bd552dfbf8bb4e052fc3c9ee 100644 (file)
@@ -465,6 +465,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
        struct inode *inode = &ci->vfs_inode;
        struct ceph_cap_snap *capsnap;
        struct ceph_snap_context *old_snapc, *new_snapc;
+       struct ceph_buffer *old_blob = NULL;
        int used, dirty;
 
        capsnap = kzalloc(sizeof(*capsnap), GFP_NOFS);
@@ -541,7 +542,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
        capsnap->gid = inode->i_gid;
 
        if (dirty & CEPH_CAP_XATTR_EXCL) {
-               __ceph_build_xattrs_blob(ci);
+               old_blob = __ceph_build_xattrs_blob(ci);
                capsnap->xattr_blob =
                        ceph_buffer_get(ci->i_xattrs.blob);
                capsnap->xattr_version = ci->i_xattrs.version;
@@ -584,6 +585,7 @@ update_snapc:
        }
        spin_unlock(&ci->i_ceph_lock);
 
+       ceph_buffer_put(old_blob);
        kfree(capsnap);
        ceph_put_snap_context(old_snapc);
 }
index d2352fd95dbc73c4b8ce4f03e586f8a6ba8abda3..6b9f1ee7de8575a7db70fcf49fc16769df01fa3e 100644 (file)
@@ -926,7 +926,7 @@ extern int ceph_getattr(const struct path *path, struct kstat *stat,
 int __ceph_setxattr(struct inode *, const char *, const void *, size_t, int);
 ssize_t __ceph_getxattr(struct inode *, const char *, void *, size_t);
 extern ssize_t ceph_listxattr(struct dentry *, char *, size_t);
-extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci);
+extern struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci);
 extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci);
 extern const struct xattr_handler *ceph_xattr_handlers[];
 
index 37b458a9af3adafafa1b9fc310762762b3ff0841..939eab7aa219d74c652263d4c85c249b7b94898f 100644 (file)
@@ -754,12 +754,15 @@ static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
 
 /*
  * If there are dirty xattrs, reencode xattrs into the prealloc_blob
- * and swap into place.
+ * and swap into place.  It returns the old i_xattrs.blob (or NULL) so
+ * that it can be freed by the caller as the i_ceph_lock is likely to be
+ * held.
  */
-void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
+struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci)
 {
        struct rb_node *p;
        struct ceph_inode_xattr *xattr = NULL;
+       struct ceph_buffer *old_blob = NULL;
        void *dest;
 
        dout("__build_xattrs_blob %p\n", &ci->vfs_inode);
@@ -790,12 +793,14 @@ void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
                        dest - ci->i_xattrs.prealloc_blob->vec.iov_base;
 
                if (ci->i_xattrs.blob)
-                       ceph_buffer_put(ci->i_xattrs.blob);
+                       old_blob = ci->i_xattrs.blob;
                ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob;
                ci->i_xattrs.prealloc_blob = NULL;
                ci->i_xattrs.dirty = false;
                ci->i_xattrs.version++;
        }
+
+       return old_blob;
 }
 
 static inline int __get_request_mask(struct inode *in) {
@@ -1036,6 +1041,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_cap_flush *prealloc_cf = NULL;
+       struct ceph_buffer *old_blob = NULL;
        int issued;
        int err;
        int dirty = 0;
@@ -1109,13 +1115,15 @@ retry:
                struct ceph_buffer *blob;
 
                spin_unlock(&ci->i_ceph_lock);
-               dout(" preaallocating new blob size=%d\n", required_blob_size);
+               ceph_buffer_put(old_blob); /* Shouldn't be required */
+               dout(" pre-allocating new blob size=%d\n", required_blob_size);
                blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
                if (!blob)
                        goto do_sync_unlocked;
                spin_lock(&ci->i_ceph_lock);
+               /* prealloc_blob can't be released while holding i_ceph_lock */
                if (ci->i_xattrs.prealloc_blob)
-                       ceph_buffer_put(ci->i_xattrs.prealloc_blob);
+                       old_blob = ci->i_xattrs.prealloc_blob;
                ci->i_xattrs.prealloc_blob = blob;
                goto retry;
        }
@@ -1131,6 +1139,7 @@ retry:
        }
 
        spin_unlock(&ci->i_ceph_lock);
+       ceph_buffer_put(old_blob);
        if (lock_snap_rwsem)
                up_read(&mdsc->snap_rwsem);
        if (dirty)
index 4b21a90015a96e647de60b99dc20cd1f7ccce5a7..99caf77df4a23edd9291e0f9336ca4a0d6df323e 100644 (file)
@@ -152,5 +152,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.21"
+#define CIFS_VERSION   "2.22"
 #endif                         /* _CIFSFS_H */
index e23234207fc2cfbedaa7460eda6fabf0cd8e8210..592a6cea2b79f52df986bd9df7c1dcced837ccdd 100644 (file)
@@ -579,6 +579,7 @@ extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
                                unsigned int *len, unsigned int *offset);
 
 void extract_unc_hostname(const char *unc, const char **h, size_t *len);
+int copy_path_name(char *dst, const char *src);
 
 #ifdef CONFIG_CIFS_DFS_UPCALL
 static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
index e2f95965065d1d7fd42c8116d0d57cecb097bd6c..3907653e63c7784e8f70fb1f48da7bd3dcf68b73 100644 (file)
@@ -942,10 +942,8 @@ PsxDelete:
                                       PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else { /* BB add path length overrun check */
-               name_len = strnlen(fileName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, fileName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, fileName);
        }
 
        params = 6 + name_len;
@@ -1015,10 +1013,8 @@ DelFileRetry:
                                              remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {                /* BB improve check for buffer overruns BB */
-               name_len = strnlen(name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->fileName, name, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->fileName, name);
        }
        pSMB->SearchAttributes =
            cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
@@ -1062,10 +1058,8 @@ RmDirRetry:
                                              remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {                /* BB improve check for buffer overruns BB */
-               name_len = strnlen(name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->DirName, name, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->DirName, name);
        }
 
        pSMB->BufferFormat = 0x04;
@@ -1107,10 +1101,8 @@ MkDirRetry:
                                              remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {                /* BB improve check for buffer overruns BB */
-               name_len = strnlen(name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->DirName, name, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->DirName, name);
        }
 
        pSMB->BufferFormat = 0x04;
@@ -1157,10 +1149,8 @@ PsxCreat:
                                       PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, name, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, name);
        }
 
        params = 6 + name_len;
@@ -1324,11 +1314,9 @@ OldOpenRetry:
                                      fileName, PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {                /* BB improve check for buffer overruns BB */
+       } else {
                count = 0;      /* no pad */
-               name_len = strnlen(fileName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->fileName, fileName, name_len);
+               name_len = copy_path_name(pSMB->fileName, fileName);
        }
        if (*pOplock & REQ_OPLOCK)
                pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
@@ -1442,11 +1430,8 @@ openRetry:
                /* BB improve check for buffer overruns BB */
                /* no pad */
                count = 0;
-               name_len = strnlen(path, PATH_MAX);
-               /* trailing null */
-               name_len++;
+               name_len = copy_path_name(req->fileName, path);
                req->NameLength = cpu_to_le16(name_len);
-               strncpy(req->fileName, path, name_len);
        }
 
        if (*oplock & REQ_OPLOCK)
@@ -2812,15 +2797,10 @@ renameRetry:
                                       remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(from_name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->OldFileName, from_name, name_len);
-               name_len2 = strnlen(to_name, PATH_MAX);
-               name_len2++;    /* trailing null */
+       } else {
+               name_len = copy_path_name(pSMB->OldFileName, from_name);
+               name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
-               strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
-               name_len2++;    /* trailing null */
                name_len2++;    /* signature byte */
        }
 
@@ -2962,15 +2942,10 @@ copyRetry:
                                       toName, PATH_MAX, nls_codepage, remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fromName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->OldFileName, fromName, name_len);
-               name_len2 = strnlen(toName, PATH_MAX);
-               name_len2++;    /* trailing null */
+       } else {
+               name_len = copy_path_name(pSMB->OldFileName, fromName);
                pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
-               strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
-               name_len2++;    /* trailing null */
+               name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
                name_len2++;    /* signature byte */
        }
 
@@ -3021,10 +2996,8 @@ createSymLinkRetry:
                name_len++;     /* trailing null */
                name_len *= 2;
 
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fromName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, fromName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, fromName);
        }
        params = 6 + name_len;
        pSMB->MaxSetupCount = 0;
@@ -3044,10 +3017,8 @@ createSymLinkRetry:
                                        PATH_MAX, nls_codepage, remap);
                name_len_target++;      /* trailing null */
                name_len_target *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len_target = strnlen(toName, PATH_MAX);
-               name_len_target++;      /* trailing null */
-               strncpy(data_offset, toName, name_len_target);
+       } else {
+               name_len_target = copy_path_name(data_offset, toName);
        }
 
        pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -3109,10 +3080,8 @@ createHardLinkRetry:
                name_len++;     /* trailing null */
                name_len *= 2;
 
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(toName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, toName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, toName);
        }
        params = 6 + name_len;
        pSMB->MaxSetupCount = 0;
@@ -3131,10 +3100,8 @@ createHardLinkRetry:
                                       PATH_MAX, nls_codepage, remap);
                name_len_target++;      /* trailing null */
                name_len_target *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len_target = strnlen(fromName, PATH_MAX);
-               name_len_target++;      /* trailing null */
-               strncpy(data_offset, fromName, name_len_target);
+       } else {
+               name_len_target = copy_path_name(data_offset, fromName);
        }
 
        pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -3213,15 +3180,10 @@ winCreateHardLinkRetry:
                                       remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(from_name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->OldFileName, from_name, name_len);
-               name_len2 = strnlen(to_name, PATH_MAX);
-               name_len2++;    /* trailing null */
+       } else {
+               name_len = copy_path_name(pSMB->OldFileName, from_name);
                pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
-               strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
-               name_len2++;    /* trailing null */
+               name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
                name_len2++;    /* signature byte */
        }
 
@@ -3271,10 +3233,8 @@ querySymLinkRetry:
                                           remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, searchName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, searchName);
        }
 
        params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
@@ -3691,10 +3651,8 @@ queryAclRetry:
                name_len *= 2;
                pSMB->FileName[name_len] = 0;
                pSMB->FileName[name_len+1] = 0;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, searchName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, searchName);
        }
 
        params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
@@ -3776,10 +3734,8 @@ setAclRetry:
                                           PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, fileName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, fileName);
        }
        params = 6 + name_len;
        pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -4184,9 +4140,7 @@ QInfRetry:
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {
-               name_len = strnlen(search_name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, search_name, name_len);
+               name_len = copy_path_name(pSMB->FileName, search_name);
        }
        pSMB->BufferFormat = 0x04;
        name_len++; /* account for buffer type byte */
@@ -4321,10 +4275,8 @@ QPathInfoRetry:
                                       PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(search_name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, search_name, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, search_name);
        }
 
        params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
@@ -4490,10 +4442,8 @@ UnixQPathInfoRetry:
                                       PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, searchName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, searchName);
        }
 
        params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
@@ -4593,17 +4543,16 @@ findFirstRetry:
                        pSMB->FileName[name_len+1] = 0;
                        name_len += 2;
                }
-       } else {        /* BB add check for overrun of SMB buf BB */
-               name_len = strnlen(searchName, PATH_MAX);
-/* BB fix here and in unicode clause above ie
-               if (name_len > buffersize-header)
-                       free buffer exit; BB */
-               strncpy(pSMB->FileName, searchName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, searchName);
                if (msearch) {
-                       pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
-                       pSMB->FileName[name_len+1] = '*';
-                       pSMB->FileName[name_len+2] = 0;
-                       name_len += 3;
+                       if (WARN_ON_ONCE(name_len > PATH_MAX-2))
+                               name_len = PATH_MAX-2;
+                       /* overwrite nul byte */
+                       pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
+                       pSMB->FileName[name_len] = '*';
+                       pSMB->FileName[name_len+1] = 0;
+                       name_len += 2;
                }
        }
 
@@ -4898,10 +4847,8 @@ GetInodeNumberRetry:
                                           remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(search_name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, search_name, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, search_name);
        }
 
        params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
@@ -5008,9 +4955,7 @@ getDFSRetry:
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(search_name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->RequestFileName, search_name, name_len);
+               name_len = copy_path_name(pSMB->RequestFileName, search_name);
        }
 
        if (ses->server->sign)
@@ -5663,10 +5608,8 @@ SetEOFRetry:
                                       PATH_MAX, cifs_sb->local_nls, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(file_name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, file_name, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, file_name);
        }
        params = 6 + name_len;
        data_count = sizeof(struct file_end_of_file_info);
@@ -5959,10 +5902,8 @@ SetTimesRetry:
                                       PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, fileName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, fileName);
        }
 
        params = 6 + name_len;
@@ -6040,10 +5981,8 @@ SetAttrLgcyRetry:
                                       PATH_MAX, nls_codepage);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->fileName, fileName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->fileName, fileName);
        }
        pSMB->attr = cpu_to_le16(dos_attrs);
        pSMB->BufferFormat = 0x04;
@@ -6203,10 +6142,8 @@ setPermsRetry:
                                       PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(file_name, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, file_name, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, file_name);
        }
 
        params = 6 + name_len;
@@ -6298,10 +6235,8 @@ QAllEAsRetry:
                                       PATH_MAX, nls_codepage, remap);
                list_len++;     /* trailing null */
                list_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               list_len = strnlen(searchName, PATH_MAX);
-               list_len++;     /* trailing null */
-               strncpy(pSMB->FileName, searchName, list_len);
+       } else {
+               list_len = copy_path_name(pSMB->FileName, searchName);
        }
 
        params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
@@ -6480,10 +6415,8 @@ SetEARetry:
                                       PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {        /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, fileName, name_len);
+       } else {
+               name_len = copy_path_name(pSMB->FileName, fileName);
        }
 
        params = 6 + name_len;
index a4830ced0f9899c35c89609b2ea25330a06693bd..5299effa6f7d42d940a76057395fb7d9bd6ce99f 100644 (file)
@@ -1113,6 +1113,7 @@ cifs_demultiplex_thread(void *p)
                mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
 
        set_freezable();
+       allow_kernel_signal(SIGKILL);
        while (server->tcpStatus != CifsExiting) {
                if (try_to_freeze())
                        continue;
@@ -2980,6 +2981,7 @@ static int
 cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
 {
        int rc = 0;
+       int is_domain = 0;
        const char *delim, *payload;
        char *desc;
        ssize_t len;
@@ -3027,6 +3029,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
                        rc = PTR_ERR(key);
                        goto out_err;
                }
+               is_domain = 1;
        }
 
        down_read(&key->sem);
@@ -3084,6 +3087,26 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
                goto out_key_put;
        }
 
+       /*
+        * If we have a domain key then we must set the domainName in the
+        * for the request.
+        */
+       if (is_domain && ses->domainName) {
+               vol->domainname = kstrndup(ses->domainName,
+                                          strlen(ses->domainName),
+                                          GFP_KERNEL);
+               if (!vol->domainname) {
+                       cifs_dbg(FYI, "Unable to allocate %zd bytes for "
+                                "domain\n", len);
+                       rc = -ENOMEM;
+                       kfree(vol->username);
+                       vol->username = NULL;
+                       kzfree(vol->password);
+                       vol->password = NULL;
+                       goto out_key_put;
+               }
+       }
+
 out_key_put:
        up_read(&key->sem);
        key_put(key);
@@ -4208,16 +4231,19 @@ build_unc_path_to_root(const struct smb_vol *vol,
                strlen(vol->prepath) + 1 : 0;
        unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
 
+       if (unc_len > MAX_TREE_SIZE)
+               return ERR_PTR(-EINVAL);
+
        full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
        if (full_path == NULL)
                return ERR_PTR(-ENOMEM);
 
-       strncpy(full_path, vol->UNC, unc_len);
+       memcpy(full_path, vol->UNC, unc_len);
        pos = full_path + unc_len;
 
        if (pplen) {
                *pos = CIFS_DIR_SEP(cifs_sb);
-               strncpy(pos + 1, vol->prepath, pplen);
+               memcpy(pos + 1, vol->prepath, pplen);
                pos += pplen;
        }
 
index f26a48dd2e39508ab01c11c91d85fbb471beb16c..be424e81e3ad98e20f65de41572d87a569a28c7b 100644 (file)
@@ -69,11 +69,10 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
                return full_path;
 
        if (dfsplen)
-               strncpy(full_path, tcon->treeName, dfsplen);
+               memcpy(full_path, tcon->treeName, dfsplen);
        full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb);
-       strncpy(full_path + dfsplen + 1, vol->prepath, pplen);
+       memcpy(full_path + dfsplen + 1, vol->prepath, pplen);
        convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
-       full_path[dfsplen + pplen] = 0; /* add trailing null */
        return full_path;
 }
 
index f383877a65117d5d42f40e99eae9c8127dcf8747..5ad83bdb9bea3ce3597238e862cd447ca878b40a 100644 (file)
@@ -1011,3 +1011,25 @@ void extract_unc_hostname(const char *unc, const char **h, size_t *len)
        *h = unc;
        *len = end - unc;
 }
+
+/**
+ * copy_path_name - copy src path to dst, possibly truncating
+ *
+ * returns number of bytes written (including trailing nul)
+ */
+int copy_path_name(char *dst, const char *src)
+{
+       int name_len;
+
+       /*
+        * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it
+        * will truncate and strlen(dst) will be PATH_MAX-1
+        */
+       name_len = strscpy(dst, src, PATH_MAX);
+       if (WARN_ON_ONCE(name_len < 0))
+               name_len = PATH_MAX-1;
+
+       /* we count the trailing nul */
+       name_len++;
+       return name_len;
+}
index dcd49ad60c83d4b668f0d748ed8601147da74b63..4c764ff7edd217b73c35853db0c12543013a5cbe 100644 (file)
@@ -159,13 +159,16 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
                                 const struct nls_table *nls_cp)
 {
        char *bcc_ptr = *pbcc_area;
+       int len;
 
        /* copy user */
        /* BB what about null user mounts - check that we do this BB */
        /* copy user */
        if (ses->user_name != NULL) {
-               strncpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
-               bcc_ptr += strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
+               len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
+               if (WARN_ON_ONCE(len < 0))
+                       len = CIFS_MAX_USERNAME_LEN - 1;
+               bcc_ptr += len;
        }
        /* else null user mount */
        *bcc_ptr = 0;
@@ -173,8 +176,10 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
 
        /* copy domain */
        if (ses->domainName != NULL) {
-               strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
-               bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+               len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+               if (WARN_ON_ONCE(len < 0))
+                       len = CIFS_MAX_DOMAINNAME_LEN - 1;
+               bcc_ptr += len;
        } /* else we will send a null domain name
             so the server will default to its own domain */
        *bcc_ptr = 0;
@@ -242,9 +247,10 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
 
        kfree(ses->serverOS);
 
-       ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
+       ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
        if (ses->serverOS) {
-               strncpy(ses->serverOS, bcc_ptr, len);
+               memcpy(ses->serverOS, bcc_ptr, len);
+               ses->serverOS[len] = 0;
                if (strncmp(ses->serverOS, "OS/2", 4) == 0)
                        cifs_dbg(FYI, "OS/2 server\n");
        }
@@ -258,9 +264,11 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
 
        kfree(ses->serverNOS);
 
-       ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
-       if (ses->serverNOS)
-               strncpy(ses->serverNOS, bcc_ptr, len);
+       ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
+       if (ses->serverNOS) {
+               memcpy(ses->serverNOS, bcc_ptr, len);
+               ses->serverNOS[len] = 0;
+       }
 
        bcc_ptr += len + 1;
        bleft -= len + 1;
index a5bc1b671c126579a7161853ad0ef352e01f8c39..64a5864127be9154fead53d4188a15d3f7ddaf17 100644 (file)
@@ -3489,7 +3489,15 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
 static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
                                   unsigned int buflen)
 {
-       sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
+       void *addr;
+       /*
+        * VMAP_STACK (at least) puts stack into the vmalloc address space
+        */
+       if (is_vmalloc_addr(buf))
+               addr = vmalloc_to_page(buf);
+       else
+               addr = virt_to_page(buf);
+       sg_set_page(sg, addr, buflen, offset_in_page(buf));
 }
 
 /* Assumes the first rqst has a transform header as the first iov.
@@ -4070,7 +4078,6 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
 {
        int ret, length;
        char *buf = server->smallbuf;
-       char *tmpbuf;
        struct smb2_sync_hdr *shdr;
        unsigned int pdu_length = server->pdu_size;
        unsigned int buf_size;
@@ -4100,18 +4107,15 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
                return length;
 
        next_is_large = server->large_buf;
- one_more:
+one_more:
        shdr = (struct smb2_sync_hdr *)buf;
        if (shdr->NextCommand) {
-               if (next_is_large) {
-                       tmpbuf = server->bigbuf;
+               if (next_is_large)
                        next_buffer = (char *)cifs_buf_get();
-               } else {
-                       tmpbuf = server->smallbuf;
+               else
                        next_buffer = (char *)cifs_small_buf_get();
-               }
                memcpy(next_buffer,
-                      tmpbuf + le32_to_cpu(shdr->NextCommand),
+                      buf + le32_to_cpu(shdr->NextCommand),
                       pdu_length - le32_to_cpu(shdr->NextCommand));
        }
 
@@ -4140,12 +4144,21 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
                pdu_length -= le32_to_cpu(shdr->NextCommand);
                server->large_buf = next_is_large;
                if (next_is_large)
-                       server->bigbuf = next_buffer;
+                       server->bigbuf = buf = next_buffer;
                else
-                       server->smallbuf = next_buffer;
-
-               buf += le32_to_cpu(shdr->NextCommand);
+                       server->smallbuf = buf = next_buffer;
                goto one_more;
+       } else if (ret != 0) {
+               /*
+                * ret != 0 here means that we didn't get to handle_mid() thus
+                * server->smallbuf and server->bigbuf are still valid. We need
+                * to free next_buffer because it is not going to be used
+                * anywhere.
+                */
+               if (next_is_large)
+                       free_rsp_buf(CIFS_LARGE_BUFFER, next_buffer);
+               else
+                       free_rsp_buf(CIFS_SMALL_BUFFER, next_buffer);
        }
 
        return ret;
index c8cd7b6cdda2a5c93b0c6a5cf374d6b29291726e..31e4a1b0b1704b90e9ed8f0cdb123477933fb369 100644 (file)
@@ -252,7 +252,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
        if (tcon == NULL)
                return 0;
 
-       if (smb2_command == SMB2_TREE_CONNECT)
+       if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL)
                return 0;
 
        if (tcon->tidStatus == CifsExiting) {
@@ -1196,7 +1196,12 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
        else
                req->SecurityMode = 0;
 
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
+#else
        req->Capabilities = 0;
+#endif /* DFS_UPCALL */
+
        req->Channel = 0; /* MBZ */
 
        sess_data->iov[0].iov_base = (char *)req;
index 6e30949d9f7794a584c1503fe8dbf7a51d0e83b7..a7ec2d3dff9282bf6e8fbc2c29e2f8e0301efb39 100644 (file)
@@ -638,9 +638,6 @@ COMPATIBLE_IOCTL(PPPIOCDISCONN)
 COMPATIBLE_IOCTL(PPPIOCATTCHAN)
 COMPATIBLE_IOCTL(PPPIOCGCHAN)
 COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
-/* PPPOX */
-COMPATIBLE_IOCTL(PPPOEIOCSFWD)
-COMPATIBLE_IOCTL(PPPOEIOCDFWD)
 /* Big A */
 /* sparc only */
 /* Big Q for sound/OSS */
index f752d83a9c44807818d12ad7f010cdaf43b83c8d..520f1813e789c0553e84edc6f7e2255fde174bf1 100644 (file)
 #include <linux/list.h>
 #include <linux/spinlock.h>
 
+struct configfs_fragment {
+       atomic_t frag_count;
+       struct rw_semaphore frag_sem;
+       bool frag_dead;
+};
+
+void put_fragment(struct configfs_fragment *);
+struct configfs_fragment *get_fragment(struct configfs_fragment *);
+
 struct configfs_dirent {
        atomic_t                s_count;
        int                     s_dependent_count;
@@ -34,6 +43,7 @@ struct configfs_dirent {
 #ifdef CONFIG_LOCKDEP
        int                     s_depth;
 #endif
+       struct configfs_fragment *s_frag;
 };
 
 #define CONFIGFS_ROOT          0x0001
@@ -61,8 +71,8 @@ extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct in
 extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
 extern int configfs_create_bin_file(struct config_item *,
                                    const struct configfs_bin_attribute *);
-extern int configfs_make_dirent(struct configfs_dirent *,
-                               struct dentry *, void *, umode_t, int);
+extern int configfs_make_dirent(struct configfs_dirent *, struct dentry *,
+                               void *, umode_t, int, struct configfs_fragment *);
 extern int configfs_dirent_is_ready(struct configfs_dirent *);
 
 extern void configfs_hash_and_remove(struct dentry * dir, const char * name);
@@ -137,6 +147,7 @@ static inline void release_configfs_dirent(struct configfs_dirent * sd)
 {
        if (!(sd->s_type & CONFIGFS_ROOT)) {
                kfree(sd->s_iattr);
+               put_fragment(sd->s_frag);
                kmem_cache_free(configfs_dir_cachep, sd);
        }
 }
index 92112915de8e752a1a9ae1b548513e41c7d0f7e4..79fc25aaa8cd5e8168d32a7ada8bb0ec40af4c1d 100644 (file)
@@ -151,11 +151,38 @@ configfs_adjust_dir_dirent_depth_after_populate(struct configfs_dirent *sd)
 
 #endif /* CONFIG_LOCKDEP */
 
+static struct configfs_fragment *new_fragment(void)
+{
+       struct configfs_fragment *p;
+
+       p = kmalloc(sizeof(struct configfs_fragment), GFP_KERNEL);
+       if (p) {
+               atomic_set(&p->frag_count, 1);
+               init_rwsem(&p->frag_sem);
+               p->frag_dead = false;
+       }
+       return p;
+}
+
+void put_fragment(struct configfs_fragment *frag)
+{
+       if (frag && atomic_dec_and_test(&frag->frag_count))
+               kfree(frag);
+}
+
+struct configfs_fragment *get_fragment(struct configfs_fragment *frag)
+{
+       if (likely(frag))
+               atomic_inc(&frag->frag_count);
+       return frag;
+}
+
 /*
  * Allocates a new configfs_dirent and links it to the parent configfs_dirent
  */
 static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent *parent_sd,
-                                                  void *element, int type)
+                                                  void *element, int type,
+                                                  struct configfs_fragment *frag)
 {
        struct configfs_dirent * sd;
 
@@ -175,6 +202,7 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent *paren
                kmem_cache_free(configfs_dir_cachep, sd);
                return ERR_PTR(-ENOENT);
        }
+       sd->s_frag = get_fragment(frag);
        list_add(&sd->s_sibling, &parent_sd->s_children);
        spin_unlock(&configfs_dirent_lock);
 
@@ -209,11 +237,11 @@ static int configfs_dirent_exists(struct configfs_dirent *parent_sd,
 
 int configfs_make_dirent(struct configfs_dirent * parent_sd,
                         struct dentry * dentry, void * element,
-                        umode_t mode, int type)
+                        umode_t mode, int type, struct configfs_fragment *frag)
 {
        struct configfs_dirent * sd;
 
-       sd = configfs_new_dirent(parent_sd, element, type);
+       sd = configfs_new_dirent(parent_sd, element, type, frag);
        if (IS_ERR(sd))
                return PTR_ERR(sd);
 
@@ -260,7 +288,8 @@ static void init_symlink(struct inode * inode)
  *     until it is validated by configfs_dir_set_ready()
  */
 
-static int configfs_create_dir(struct config_item *item, struct dentry *dentry)
+static int configfs_create_dir(struct config_item *item, struct dentry *dentry,
+                               struct configfs_fragment *frag)
 {
        int error;
        umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
@@ -273,7 +302,8 @@ static int configfs_create_dir(struct config_item *item, struct dentry *dentry)
                return error;
 
        error = configfs_make_dirent(p->d_fsdata, dentry, item, mode,
-                                    CONFIGFS_DIR | CONFIGFS_USET_CREATING);
+                                    CONFIGFS_DIR | CONFIGFS_USET_CREATING,
+                                    frag);
        if (unlikely(error))
                return error;
 
@@ -338,9 +368,10 @@ int configfs_create_link(struct configfs_symlink *sl,
 {
        int err = 0;
        umode_t mode = S_IFLNK | S_IRWXUGO;
+       struct configfs_dirent *p = parent->d_fsdata;
 
-       err = configfs_make_dirent(parent->d_fsdata, dentry, sl, mode,
-                                  CONFIGFS_ITEM_LINK);
+       err = configfs_make_dirent(p, dentry, sl, mode,
+                                  CONFIGFS_ITEM_LINK, p->s_frag);
        if (!err) {
                err = configfs_create(dentry, mode, init_symlink);
                if (err) {
@@ -599,7 +630,8 @@ static int populate_attrs(struct config_item *item)
 
 static int configfs_attach_group(struct config_item *parent_item,
                                 struct config_item *item,
-                                struct dentry *dentry);
+                                struct dentry *dentry,
+                                struct configfs_fragment *frag);
 static void configfs_detach_group(struct config_item *item);
 
 static void detach_groups(struct config_group *group)
@@ -647,7 +679,8 @@ static void detach_groups(struct config_group *group)
  * try using vfs_mkdir.  Just a thought.
  */
 static int create_default_group(struct config_group *parent_group,
-                               struct config_group *group)
+                               struct config_group *group,
+                               struct configfs_fragment *frag)
 {
        int ret;
        struct configfs_dirent *sd;
@@ -663,7 +696,7 @@ static int create_default_group(struct config_group *parent_group,
                d_add(child, NULL);
 
                ret = configfs_attach_group(&parent_group->cg_item,
-                                           &group->cg_item, child);
+                                           &group->cg_item, child, frag);
                if (!ret) {
                        sd = child->d_fsdata;
                        sd->s_type |= CONFIGFS_USET_DEFAULT;
@@ -677,13 +710,14 @@ static int create_default_group(struct config_group *parent_group,
        return ret;
 }
 
-static int populate_groups(struct config_group *group)
+static int populate_groups(struct config_group *group,
+                          struct configfs_fragment *frag)
 {
        struct config_group *new_group;
        int ret = 0;
 
        list_for_each_entry(new_group, &group->default_groups, group_entry) {
-               ret = create_default_group(group, new_group);
+               ret = create_default_group(group, new_group, frag);
                if (ret) {
                        detach_groups(group);
                        break;
@@ -797,11 +831,12 @@ static void link_group(struct config_group *parent_group, struct config_group *g
  */
 static int configfs_attach_item(struct config_item *parent_item,
                                struct config_item *item,
-                               struct dentry *dentry)
+                               struct dentry *dentry,
+                               struct configfs_fragment *frag)
 {
        int ret;
 
-       ret = configfs_create_dir(item, dentry);
+       ret = configfs_create_dir(item, dentry, frag);
        if (!ret) {
                ret = populate_attrs(item);
                if (ret) {
@@ -831,12 +866,13 @@ static void configfs_detach_item(struct config_item *item)
 
 static int configfs_attach_group(struct config_item *parent_item,
                                 struct config_item *item,
-                                struct dentry *dentry)
+                                struct dentry *dentry,
+                                struct configfs_fragment *frag)
 {
        int ret;
        struct configfs_dirent *sd;
 
-       ret = configfs_attach_item(parent_item, item, dentry);
+       ret = configfs_attach_item(parent_item, item, dentry, frag);
        if (!ret) {
                sd = dentry->d_fsdata;
                sd->s_type |= CONFIGFS_USET_DIR;
@@ -852,7 +888,7 @@ static int configfs_attach_group(struct config_item *parent_item,
                 */
                inode_lock_nested(d_inode(dentry), I_MUTEX_CHILD);
                configfs_adjust_dir_dirent_depth_before_populate(sd);
-               ret = populate_groups(to_config_group(item));
+               ret = populate_groups(to_config_group(item), frag);
                if (ret) {
                        configfs_detach_item(item);
                        d_inode(dentry)->i_flags |= S_DEAD;
@@ -1247,6 +1283,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
        struct configfs_dirent *sd;
        const struct config_item_type *type;
        struct module *subsys_owner = NULL, *new_item_owner = NULL;
+       struct configfs_fragment *frag;
        char *name;
 
        sd = dentry->d_parent->d_fsdata;
@@ -1265,6 +1302,12 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
                goto out;
        }
 
+       frag = new_fragment();
+       if (!frag) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
        /* Get a working ref for the duration of this function */
        parent_item = configfs_get_config_item(dentry->d_parent);
        type = parent_item->ci_type;
@@ -1367,9 +1410,9 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
        spin_unlock(&configfs_dirent_lock);
 
        if (group)
-               ret = configfs_attach_group(parent_item, item, dentry);
+               ret = configfs_attach_group(parent_item, item, dentry, frag);
        else
-               ret = configfs_attach_item(parent_item, item, dentry);
+               ret = configfs_attach_item(parent_item, item, dentry, frag);
 
        spin_lock(&configfs_dirent_lock);
        sd->s_type &= ~CONFIGFS_USET_IN_MKDIR;
@@ -1406,6 +1449,7 @@ out_put:
         * reference.
         */
        config_item_put(parent_item);
+       put_fragment(frag);
 
 out:
        return ret;
@@ -1417,6 +1461,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
        struct config_item *item;
        struct configfs_subsystem *subsys;
        struct configfs_dirent *sd;
+       struct configfs_fragment *frag;
        struct module *subsys_owner = NULL, *dead_item_owner = NULL;
        int ret;
 
@@ -1474,6 +1519,16 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
                }
        } while (ret == -EAGAIN);
 
+       frag = sd->s_frag;
+       if (down_write_killable(&frag->frag_sem)) {
+               spin_lock(&configfs_dirent_lock);
+               configfs_detach_rollback(dentry);
+               spin_unlock(&configfs_dirent_lock);
+               return -EINTR;
+       }
+       frag->frag_dead = true;
+       up_write(&frag->frag_sem);
+
        /* Get a working ref for the duration of this function */
        item = configfs_get_config_item(dentry);
 
@@ -1574,7 +1629,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file)
         */
        err = -ENOENT;
        if (configfs_dirent_is_ready(parent_sd)) {
-               file->private_data = configfs_new_dirent(parent_sd, NULL, 0);
+               file->private_data = configfs_new_dirent(parent_sd, NULL, 0, NULL);
                if (IS_ERR(file->private_data))
                        err = PTR_ERR(file->private_data);
                else
@@ -1732,8 +1787,13 @@ int configfs_register_group(struct config_group *parent_group,
 {
        struct configfs_subsystem *subsys = parent_group->cg_subsys;
        struct dentry *parent;
+       struct configfs_fragment *frag;
        int ret;
 
+       frag = new_fragment();
+       if (!frag)
+               return -ENOMEM;
+
        mutex_lock(&subsys->su_mutex);
        link_group(parent_group, group);
        mutex_unlock(&subsys->su_mutex);
@@ -1741,7 +1801,7 @@ int configfs_register_group(struct config_group *parent_group,
        parent = parent_group->cg_item.ci_dentry;
 
        inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
-       ret = create_default_group(parent_group, group);
+       ret = create_default_group(parent_group, group, frag);
        if (ret)
                goto err_out;
 
@@ -1749,12 +1809,14 @@ int configfs_register_group(struct config_group *parent_group,
        configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata);
        spin_unlock(&configfs_dirent_lock);
        inode_unlock(d_inode(parent));
+       put_fragment(frag);
        return 0;
 err_out:
        inode_unlock(d_inode(parent));
        mutex_lock(&subsys->su_mutex);
        unlink_group(group);
        mutex_unlock(&subsys->su_mutex);
+       put_fragment(frag);
        return ret;
 }
 EXPORT_SYMBOL(configfs_register_group);
@@ -1770,16 +1832,12 @@ void configfs_unregister_group(struct config_group *group)
        struct configfs_subsystem *subsys = group->cg_subsys;
        struct dentry *dentry = group->cg_item.ci_dentry;
        struct dentry *parent = group->cg_item.ci_parent->ci_dentry;
+       struct configfs_dirent *sd = dentry->d_fsdata;
+       struct configfs_fragment *frag = sd->s_frag;
 
-       mutex_lock(&subsys->su_mutex);
-       if (!group->cg_item.ci_parent->ci_group) {
-               /*
-                * The parent has already been unlinked and detached
-                * due to a rmdir.
-                */
-               goto unlink_group;
-       }
-       mutex_unlock(&subsys->su_mutex);
+       down_write(&frag->frag_sem);
+       frag->frag_dead = true;
+       up_write(&frag->frag_sem);
 
        inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
        spin_lock(&configfs_dirent_lock);
@@ -1796,7 +1854,6 @@ void configfs_unregister_group(struct config_group *group)
        dput(dentry);
 
        mutex_lock(&subsys->su_mutex);
-unlink_group:
        unlink_group(group);
        mutex_unlock(&subsys->su_mutex);
 }
@@ -1853,10 +1910,17 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
        struct dentry *dentry;
        struct dentry *root;
        struct configfs_dirent *sd;
+       struct configfs_fragment *frag;
+
+       frag = new_fragment();
+       if (!frag)
+               return -ENOMEM;
 
        root = configfs_pin_fs();
-       if (IS_ERR(root))
+       if (IS_ERR(root)) {
+               put_fragment(frag);
                return PTR_ERR(root);
+       }
 
        if (!group->cg_item.ci_name)
                group->cg_item.ci_name = group->cg_item.ci_namebuf;
@@ -1872,7 +1936,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
                d_add(dentry, NULL);
 
                err = configfs_attach_group(sd->s_element, &group->cg_item,
-                                           dentry);
+                                           dentry, frag);
                if (err) {
                        BUG_ON(d_inode(dentry));
                        d_drop(dentry);
@@ -1890,6 +1954,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
                unlink_group(group);
                configfs_release_fs();
        }
+       put_fragment(frag);
 
        return err;
 }
@@ -1899,12 +1964,18 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
        struct config_group *group = &subsys->su_group;
        struct dentry *dentry = group->cg_item.ci_dentry;
        struct dentry *root = dentry->d_sb->s_root;
+       struct configfs_dirent *sd = dentry->d_fsdata;
+       struct configfs_fragment *frag = sd->s_frag;
 
        if (dentry->d_parent != root) {
                pr_err("Tried to unregister non-subsystem!\n");
                return;
        }
 
+       down_write(&frag->frag_sem);
+       frag->frag_dead = true;
+       up_write(&frag->frag_sem);
+
        inode_lock_nested(d_inode(root),
                          I_MUTEX_PARENT);
        inode_lock_nested(d_inode(dentry), I_MUTEX_CHILD);
index 61e4db4390a1f2878a4a3bcb9c7fabcd129309dd..fb65b706cc0db9976b552c884a8ae056f27f3a68 100644 (file)
@@ -39,40 +39,44 @@ struct configfs_buffer {
        bool                    write_in_progress;
        char                    *bin_buffer;
        int                     bin_buffer_size;
+       int                     cb_max_size;
+       struct config_item      *item;
+       struct module           *owner;
+       union {
+               struct configfs_attribute       *attr;
+               struct configfs_bin_attribute   *bin_attr;
+       };
 };
 
+static inline struct configfs_fragment *to_frag(struct file *file)
+{
+       struct configfs_dirent *sd = file->f_path.dentry->d_fsdata;
 
-/**
- *     fill_read_buffer - allocate and fill buffer from item.
- *     @dentry:        dentry pointer.
- *     @buffer:        data buffer for file.
- *
- *     Allocate @buffer->page, if it hasn't been already, then call the
- *     config_item's show() method to fill the buffer with this attribute's
- *     data.
- *     This is called only once, on the file's first read.
- */
-static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buffer)
+       return sd->s_frag;
+}
+
+static int fill_read_buffer(struct file *file, struct configfs_buffer *buffer)
 {
-       struct configfs_attribute * attr = to_attr(dentry);
-       struct config_item * item = to_item(dentry->d_parent);
-       int ret = 0;
-       ssize_t count;
+       struct configfs_fragment *frag = to_frag(file);
+       ssize_t count = -ENOENT;
 
        if (!buffer->page)
                buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
        if (!buffer->page)
                return -ENOMEM;
 
-       count = attr->show(item, buffer->page);
-
-       BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
-       if (count >= 0) {
-               buffer->needs_read_fill = 0;
-               buffer->count = count;
-       } else
-               ret = count;
-       return ret;
+       down_read(&frag->frag_sem);
+       if (!frag->frag_dead)
+               count = buffer->attr->show(buffer->item, buffer->page);
+       up_read(&frag->frag_sem);
+
+       if (count < 0)
+               return count;
+       if (WARN_ON_ONCE(count > (ssize_t)SIMPLE_ATTR_SIZE))
+               return -EIO;
+       buffer->needs_read_fill = 0;
+       buffer->count = count;
+       return 0;
 }
 
 /**
@@ -97,12 +101,13 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf
 static ssize_t
 configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-       struct configfs_buffer * buffer = file->private_data;
+       struct configfs_buffer *buffer = file->private_data;
        ssize_t retval = 0;
 
        mutex_lock(&buffer->mutex);
        if (buffer->needs_read_fill) {
-               if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
+               retval = fill_read_buffer(file, buffer);
+               if (retval)
                        goto out;
        }
        pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -138,10 +143,8 @@ static ssize_t
 configfs_read_bin_file(struct file *file, char __user *buf,
                       size_t count, loff_t *ppos)
 {
+       struct configfs_fragment *frag = to_frag(file);
        struct configfs_buffer *buffer = file->private_data;
-       struct dentry *dentry = file->f_path.dentry;
-       struct config_item *item = to_item(dentry->d_parent);
-       struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
        ssize_t retval = 0;
        ssize_t len = min_t(size_t, count, PAGE_SIZE);
 
@@ -156,14 +159,19 @@ configfs_read_bin_file(struct file *file, char __user *buf,
 
        if (buffer->needs_read_fill) {
                /* perform first read with buf == NULL to get extent */
-               len = bin_attr->read(item, NULL, 0);
+               down_read(&frag->frag_sem);
+               if (!frag->frag_dead)
+                       len = buffer->bin_attr->read(buffer->item, NULL, 0);
+               else
+                       len = -ENOENT;
+               up_read(&frag->frag_sem);
                if (len <= 0) {
                        retval = len;
                        goto out;
                }
 
                /* do not exceed the maximum value */
-               if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) {
+               if (buffer->cb_max_size && len > buffer->cb_max_size) {
                        retval = -EFBIG;
                        goto out;
                }
@@ -176,7 +184,13 @@ configfs_read_bin_file(struct file *file, char __user *buf,
                buffer->bin_buffer_size = len;
 
                /* perform second read to fill buffer */
-               len = bin_attr->read(item, buffer->bin_buffer, len);
+               down_read(&frag->frag_sem);
+               if (!frag->frag_dead)
+                       len = buffer->bin_attr->read(buffer->item,
+                                                    buffer->bin_buffer, len);
+               else
+                       len = -ENOENT;
+               up_read(&frag->frag_sem);
                if (len < 0) {
                        retval = len;
                        vfree(buffer->bin_buffer);
@@ -226,25 +240,17 @@ fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size
        return error ? -EFAULT : count;
 }
 
-
-/**
- *     flush_write_buffer - push buffer to config_item.
- *     @dentry:        dentry to the attribute
- *     @buffer:        data buffer for file.
- *     @count:         number of bytes
- *
- *     Get the correct pointers for the config_item and the attribute we're
- *     dealing with, then call the store() method for the attribute,
- *     passing the buffer that we acquired in fill_write_buffer().
- */
-
 static int
-flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count)
+flush_write_buffer(struct file *file, struct configfs_buffer *buffer, size_t count)
 {
-       struct configfs_attribute * attr = to_attr(dentry);
-       struct config_item * item = to_item(dentry->d_parent);
-
-       return attr->store(item, buffer->page, count);
+       struct configfs_fragment *frag = to_frag(file);
+       int res = -ENOENT;
+
+       down_read(&frag->frag_sem);
+       if (!frag->frag_dead)
+               res = buffer->attr->store(buffer->item, buffer->page, count);
+       up_read(&frag->frag_sem);
+       return res;
 }
 
 
@@ -268,13 +274,13 @@ flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size
 static ssize_t
 configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
-       struct configfs_buffer * buffer = file->private_data;
+       struct configfs_buffer *buffer = file->private_data;
        ssize_t len;
 
        mutex_lock(&buffer->mutex);
        len = fill_write_buffer(buffer, buf, count);
        if (len > 0)
-               len = flush_write_buffer(file->f_path.dentry, buffer, len);
+               len = flush_write_buffer(file, buffer, len);
        if (len > 0)
                *ppos += len;
        mutex_unlock(&buffer->mutex);
@@ -299,8 +305,6 @@ configfs_write_bin_file(struct file *file, const char __user *buf,
                        size_t count, loff_t *ppos)
 {
        struct configfs_buffer *buffer = file->private_data;
-       struct dentry *dentry = file->f_path.dentry;
-       struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
        void *tbuf = NULL;
        ssize_t len;
 
@@ -316,8 +320,8 @@ configfs_write_bin_file(struct file *file, const char __user *buf,
        /* buffer grows? */
        if (*ppos + count > buffer->bin_buffer_size) {
 
-               if (bin_attr->cb_max_size &&
-                       *ppos + count > bin_attr->cb_max_size) {
+               if (buffer->cb_max_size &&
+                       *ppos + count > buffer->cb_max_size) {
                        len = -EFBIG;
                        goto out;
                }
@@ -349,31 +353,51 @@ out:
        return len;
 }
 
-static int check_perm(struct inode * inode, struct file * file, int type)
+static int __configfs_open_file(struct inode *inode, struct file *file, int type)
 {
-       struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent);
-       struct configfs_attribute * attr = to_attr(file->f_path.dentry);
-       struct configfs_bin_attribute *bin_attr = NULL;
-       struct configfs_buffer * buffer;
-       struct configfs_item_operations * ops = NULL;
-       int error = 0;
+       struct dentry *dentry = file->f_path.dentry;
+       struct configfs_fragment *frag = to_frag(file);
+       struct configfs_attribute *attr;
+       struct configfs_buffer *buffer;
+       int error;
 
-       if (!item || !attr)
-               goto Einval;
+       error = -ENOMEM;
+       buffer = kzalloc(sizeof(struct configfs_buffer), GFP_KERNEL);
+       if (!buffer)
+               goto out;
 
-       if (type & CONFIGFS_ITEM_BIN_ATTR)
-               bin_attr = to_bin_attr(file->f_path.dentry);
+       error = -ENOENT;
+       down_read(&frag->frag_sem);
+       if (unlikely(frag->frag_dead))
+               goto out_free_buffer;
 
-       /* Grab the module reference for this attribute if we have one */
-       if (!try_module_get(attr->ca_owner)) {
-               error = -ENODEV;
-               goto Done;
+       error = -EINVAL;
+       buffer->item = to_item(dentry->d_parent);
+       if (!buffer->item)
+               goto out_free_buffer;
+
+       attr = to_attr(dentry);
+       if (!attr)
+               goto out_put_item;
+
+       if (type & CONFIGFS_ITEM_BIN_ATTR) {
+               buffer->bin_attr = to_bin_attr(dentry);
+               buffer->cb_max_size = buffer->bin_attr->cb_max_size;
+       } else {
+               buffer->attr = attr;
        }
 
-       if (item->ci_type)
-               ops = item->ci_type->ct_item_ops;
-       else
-               goto Eaccess;
+       buffer->owner = attr->ca_owner;
+       /* Grab the module reference for this attribute if we have one */
+       error = -ENODEV;
+       if (!try_module_get(buffer->owner))
+               goto out_put_item;
+
+       error = -EACCES;
+       if (!buffer->item->ci_type)
+               goto out_put_module;
+
+       buffer->ops = buffer->item->ci_type->ct_item_ops;
 
        /* File needs write support.
         * The inode's perms must say it's ok,
@@ -381,13 +405,11 @@ static int check_perm(struct inode * inode, struct file * file, int type)
         */
        if (file->f_mode & FMODE_WRITE) {
                if (!(inode->i_mode & S_IWUGO))
-                       goto Eaccess;
-
+                       goto out_put_module;
                if ((type & CONFIGFS_ITEM_ATTR) && !attr->store)
-                       goto Eaccess;
-
-               if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->write)
-                       goto Eaccess;
+                       goto out_put_module;
+               if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->write)
+                       goto out_put_module;
        }
 
        /* File needs read support.
@@ -396,92 +418,72 @@ static int check_perm(struct inode * inode, struct file * file, int type)
         */
        if (file->f_mode & FMODE_READ) {
                if (!(inode->i_mode & S_IRUGO))
-                       goto Eaccess;
-
+                       goto out_put_module;
                if ((type & CONFIGFS_ITEM_ATTR) && !attr->show)
-                       goto Eaccess;
-
-               if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->read)
-                       goto Eaccess;
+                       goto out_put_module;
+               if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->read)
+                       goto out_put_module;
        }
 
-       /* No error? Great, allocate a buffer for the file, and store it
-        * it in file->private_data for easy access.
-        */
-       buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
-       if (!buffer) {
-               error = -ENOMEM;
-               goto Enomem;
-       }
        mutex_init(&buffer->mutex);
        buffer->needs_read_fill = 1;
        buffer->read_in_progress = false;
        buffer->write_in_progress = false;
-       buffer->ops = ops;
        file->private_data = buffer;
-       goto Done;
+       up_read(&frag->frag_sem);
+       return 0;
 
- Einval:
-       error = -EINVAL;
-       goto Done;
- Eaccess:
-       error = -EACCES;
- Enomem:
-       module_put(attr->ca_owner);
- Done:
-       if (error && item)
-               config_item_put(item);
+out_put_module:
+       module_put(buffer->owner);
+out_put_item:
+       config_item_put(buffer->item);
+out_free_buffer:
+       up_read(&frag->frag_sem);
+       kfree(buffer);
+out:
        return error;
 }
 
 static int configfs_release(struct inode *inode, struct file *filp)
 {
-       struct config_item * item = to_item(filp->f_path.dentry->d_parent);
-       struct configfs_attribute * attr = to_attr(filp->f_path.dentry);
-       struct module * owner = attr->ca_owner;
-       struct configfs_buffer * buffer = filp->private_data;
-
-       if (item)
-               config_item_put(item);
-       /* After this point, attr should not be accessed. */
-       module_put(owner);
-
-       if (buffer) {
-               if (buffer->page)
-                       free_page((unsigned long)buffer->page);
-               mutex_destroy(&buffer->mutex);
-               kfree(buffer);
-       }
+       struct configfs_buffer *buffer = filp->private_data;
+
+       module_put(buffer->owner);
+       if (buffer->page)
+               free_page((unsigned long)buffer->page);
+       mutex_destroy(&buffer->mutex);
+       kfree(buffer);
        return 0;
 }
 
 static int configfs_open_file(struct inode *inode, struct file *filp)
 {
-       return check_perm(inode, filp, CONFIGFS_ITEM_ATTR);
+       return __configfs_open_file(inode, filp, CONFIGFS_ITEM_ATTR);
 }
 
 static int configfs_open_bin_file(struct inode *inode, struct file *filp)
 {
-       return check_perm(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
+       return __configfs_open_file(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
 }
 
-static int configfs_release_bin_file(struct inode *inode, struct file *filp)
+static int configfs_release_bin_file(struct inode *inode, struct file *file)
 {
-       struct configfs_buffer *buffer = filp->private_data;
-       struct dentry *dentry = filp->f_path.dentry;
-       struct config_item *item = to_item(dentry->d_parent);
-       struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry);
-       ssize_t len = 0;
-       int ret;
+       struct configfs_buffer *buffer = file->private_data;
 
        buffer->read_in_progress = false;
 
        if (buffer->write_in_progress) {
+               struct configfs_fragment *frag = to_frag(file);
                buffer->write_in_progress = false;
 
-               len = bin_attr->write(item, buffer->bin_buffer,
-                               buffer->bin_buffer_size);
-
+               down_read(&frag->frag_sem);
+               if (!frag->frag_dead) {
+                       /* result of ->release() is ignored */
+                       buffer->bin_attr->write(buffer->item,
+                                       buffer->bin_buffer,
+                                       buffer->bin_buffer_size);
+               }
+               up_read(&frag->frag_sem);
                /* vfree on NULL is safe */
                vfree(buffer->bin_buffer);
                buffer->bin_buffer = NULL;
@@ -489,10 +491,8 @@ static int configfs_release_bin_file(struct inode *inode, struct file *filp)
                buffer->needs_read_fill = 1;
        }
 
-       ret = configfs_release(inode, filp);
-       if (len < 0)
-               return len;
-       return ret;
+       configfs_release(inode, file);
+       return 0;
 }
 
 
@@ -527,7 +527,7 @@ int configfs_create_file(struct config_item * item, const struct configfs_attrib
 
        inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL);
        error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode,
-                                    CONFIGFS_ITEM_ATTR);
+                                    CONFIGFS_ITEM_ATTR, parent_sd->s_frag);
        inode_unlock(d_inode(dir));
 
        return error;
@@ -549,7 +549,7 @@ int configfs_create_bin_file(struct config_item *item,
 
        inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL);
        error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode,
-                                    CONFIGFS_ITEM_BIN_ATTR);
+                                    CONFIGFS_ITEM_BIN_ATTR, parent_sd->s_frag);
        inode_unlock(dir->d_inode);
 
        return error;
index e42e17e55bfd5512bee600f6bd435e66e3f90147..b1ea7dfbd1494bd8d990ae03ee1bc21277dbd636 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/swap.h>
+#include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
@@ -187,11 +188,13 @@ put_exe_file:
  * name into corename, which must have space for at least
  * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
  */
-static int format_corename(struct core_name *cn, struct coredump_params *cprm)
+static int format_corename(struct core_name *cn, struct coredump_params *cprm,
+                          size_t **argv, int *argc)
 {
        const struct cred *cred = current_cred();
        const char *pat_ptr = core_pattern;
        int ispipe = (*pat_ptr == '|');
+       bool was_space = false;
        int pid_in_pattern = 0;
        int err = 0;
 
@@ -201,12 +204,35 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
                return -ENOMEM;
        cn->corename[0] = '\0';
 
-       if (ispipe)
+       if (ispipe) {
+               int argvs = sizeof(core_pattern) / 2;
+               (*argv) = kmalloc_array(argvs, sizeof(**argv), GFP_KERNEL);
+               if (!(*argv))
+                       return -ENOMEM;
+               (*argv)[(*argc)++] = 0;
                ++pat_ptr;
+       }
 
        /* Repeat as long as we have more pattern to process and more output
           space */
        while (*pat_ptr) {
+               /*
+                * Split on spaces before doing template expansion so that
+                * %e and %E don't get split if they have spaces in them
+                */
+               if (ispipe) {
+                       if (isspace(*pat_ptr)) {
+                               was_space = true;
+                               pat_ptr++;
+                               continue;
+                       } else if (was_space) {
+                               was_space = false;
+                               err = cn_printf(cn, "%c", '\0');
+                               if (err)
+                                       return err;
+                               (*argv)[(*argc)++] = cn->used;
+                       }
+               }
                if (*pat_ptr != '%') {
                        err = cn_printf(cn, "%c", *pat_ptr++);
                } else {
@@ -546,6 +572,8 @@ void do_coredump(const kernel_siginfo_t *siginfo)
        struct cred *cred;
        int retval = 0;
        int ispipe;
+       size_t *argv = NULL;
+       int argc = 0;
        struct files_struct *displaced;
        /* require nonrelative corefile path and be extra careful */
        bool need_suid_safe = false;
@@ -592,9 +620,10 @@ void do_coredump(const kernel_siginfo_t *siginfo)
 
        old_cred = override_creds(cred);
 
-       ispipe = format_corename(&cn, &cprm);
+       ispipe = format_corename(&cn, &cprm, &argv, &argc);
 
        if (ispipe) {
+               int argi;
                int dump_count;
                char **helper_argv;
                struct subprocess_info *sub_info;
@@ -637,12 +666,16 @@ void do_coredump(const kernel_siginfo_t *siginfo)
                        goto fail_dropcount;
                }
 
-               helper_argv = argv_split(GFP_KERNEL, cn.corename, NULL);
+               helper_argv = kmalloc_array(argc + 1, sizeof(*helper_argv),
+                                           GFP_KERNEL);
                if (!helper_argv) {
                        printk(KERN_WARNING "%s failed to allocate memory\n",
                               __func__);
                        goto fail_dropcount;
                }
+               for (argi = 0; argi < argc; argi++)
+                       helper_argv[argi] = cn.corename + argv[argi];
+               helper_argv[argi] = NULL;
 
                retval = -ENOMEM;
                sub_info = call_usermodehelper_setup(helper_argv[0],
@@ -652,7 +685,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
                        retval = call_usermodehelper_exec(sub_info,
                                                          UMH_WAIT_EXEC);
 
-               argv_free(helper_argv);
+               kfree(helper_argv);
                if (retval) {
                        printk(KERN_INFO "Core dump to |%s pipe failed\n",
                               cn.corename);
@@ -766,6 +799,7 @@ fail_dropcount:
        if (ispipe)
                atomic_dec(&core_dump_count);
 fail_unlock:
+       kfree(argv);
        kfree(cn.corename);
        coredump_finish(mm, core_dumped);
        revert_creds(old_cred);
index a237141d8787166eddf9701210ed811ffb77138e..6bf81f931de39e48bc2983a1c901b1a6643443f8 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -266,7 +266,7 @@ static void wait_entry_unlocked(struct xa_state *xas, void *entry)
 static void put_unlocked_entry(struct xa_state *xas, void *entry)
 {
        /* If we were the only waiter woken, wake the next one */
-       if (entry && dax_is_conflict(entry))
+       if (entry && !dax_is_conflict(entry))
                dax_wake_entry(xas, entry, false);
 }
 
@@ -600,7 +600,7 @@ struct page *dax_layout_busy_page(struct address_space *mapping)
         * guaranteed to either see new references or prevent new
         * references from being established.
         */
-       unmap_mapping_range(mapping, 0, 0, 1);
+       unmap_mapping_range(mapping, 0, 0, 0);
 
        xas_lock_irq(&xas);
        xas_for_each(&xas, entry, ULONG_MAX) {
index c71cbfe6826a5165577057000393be299613df5b..f7f6a140856a8315c9403eeaac0c2376071e95ec 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1828,7 +1828,7 @@ static int __do_execve_file(int fd, struct filename *filename,
        membarrier_execve(current);
        rseq_execve(current);
        acct_update_integrals(current);
-       task_numa_free(current);
+       task_numa_free(current, false);
        free_bprm(bprm);
        kfree(pathbuf);
        if (filename)
index 420fe3deed39702b93a5567dbebe77a8e4b6b992..006b7a2070bf6869d2f7c42500eea135919def74 100644 (file)
@@ -4586,7 +4586,6 @@ static int __ext4_get_inode_loc(struct inode *inode,
        struct buffer_head      *bh;
        struct super_block      *sb = inode->i_sb;
        ext4_fsblk_t            block;
-       struct blk_plug         plug;
        int                     inodes_per_block, inode_offset;
 
        iloc->bh = NULL;
@@ -4675,7 +4674,6 @@ make_io:
                 * If we need to do any I/O, try to pre-readahead extra
                 * blocks from the inode table.
                 */
-               blk_start_plug(&plug);
                if (EXT4_SB(sb)->s_inode_readahead_blks) {
                        ext4_fsblk_t b, end, table;
                        unsigned num;
@@ -4706,7 +4704,6 @@ make_io:
                get_bh(bh);
                bh->b_end_io = end_buffer_read_sync;
                submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh);
-               blk_finish_plug(&plug);
                wait_on_buffer(bh);
                if (!buffer_uptodate(bh)) {
                        EXT4_ERROR_INODE_BLOCK(inode, block,
index f8d46df8fa9ee5cd91813b2de5e735e39a2ad4c5..3e58a6f697dd8ca73218c36304083e332d5e4c80 100644 (file)
@@ -1653,19 +1653,12 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id)
 static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)
 {
        struct f2fs_inode_info *fi = F2FS_I(inode);
-       u32 oldflags;
 
        /* Is it quota file? Do not allow user to mess with it */
        if (IS_NOQUOTA(inode))
                return -EPERM;
 
-       oldflags = fi->i_flags;
-
-       if ((iflags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
-               if (!capable(CAP_LINUX_IMMUTABLE))
-                       return -EPERM;
-
-       fi->i_flags = iflags | (oldflags & ~mask);
+       fi->i_flags = iflags | (fi->i_flags & ~mask);
 
        if (fi->i_flags & F2FS_PROJINHERIT_FL)
                set_inode_flag(inode, FI_PROJ_INHERIT);
@@ -1770,7 +1763,8 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
 static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
-       u32 fsflags;
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       u32 fsflags, old_fsflags;
        u32 iflags;
        int ret;
 
@@ -1794,8 +1788,14 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
 
        inode_lock(inode);
 
+       old_fsflags = f2fs_iflags_to_fsflags(fi->i_flags);
+       ret = vfs_ioc_setflags_prepare(inode, old_fsflags, fsflags);
+       if (ret)
+               goto out;
+
        ret = f2fs_setflags_common(inode, iflags,
                        f2fs_fsflags_to_iflags(F2FS_SETTABLE_FS_FL));
+out:
        inode_unlock(inode);
        mnt_drop_write_file(filp);
        return ret;
@@ -2855,52 +2855,32 @@ static inline u32 f2fs_xflags_to_iflags(u32 xflags)
        return iflags;
 }
 
-static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg)
+static void f2fs_fill_fsxattr(struct inode *inode, struct fsxattr *fa)
 {
-       struct inode *inode = file_inode(filp);
        struct f2fs_inode_info *fi = F2FS_I(inode);
-       struct fsxattr fa;
 
-       memset(&fa, 0, sizeof(struct fsxattr));
-       fa.fsx_xflags = f2fs_iflags_to_xflags(fi->i_flags);
+       simple_fill_fsxattr(fa, f2fs_iflags_to_xflags(fi->i_flags));
 
        if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)))
-               fa.fsx_projid = (__u32)from_kprojid(&init_user_ns,
-                                                       fi->i_projid);
-
-       if (copy_to_user((struct fsxattr __user *)arg, &fa, sizeof(fa)))
-               return -EFAULT;
-       return 0;
+               fa->fsx_projid = from_kprojid(&init_user_ns, fi->i_projid);
 }
 
-static int f2fs_ioctl_check_project(struct inode *inode, struct fsxattr *fa)
+static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg)
 {
-       /*
-        * Project Quota ID state is only allowed to change from within the init
-        * namespace. Enforce that restriction only if we are trying to change
-        * the quota ID state. Everything else is allowed in user namespaces.
-        */
-       if (current_user_ns() == &init_user_ns)
-               return 0;
+       struct inode *inode = file_inode(filp);
+       struct fsxattr fa;
 
-       if (__kprojid_val(F2FS_I(inode)->i_projid) != fa->fsx_projid)
-               return -EINVAL;
-
-       if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL) {
-               if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT))
-                       return -EINVAL;
-       } else {
-               if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT)
-                       return -EINVAL;
-       }
+       f2fs_fill_fsxattr(inode, &fa);
 
+       if (copy_to_user((struct fsxattr __user *)arg, &fa, sizeof(fa)))
+               return -EFAULT;
        return 0;
 }
 
 static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
-       struct fsxattr fa;
+       struct fsxattr fa, old_fa;
        u32 iflags;
        int err;
 
@@ -2923,9 +2903,12 @@ static int f2fs_ioc_fssetxattr(struct file *filp, unsigned long arg)
                return err;
 
        inode_lock(inode);
-       err = f2fs_ioctl_check_project(inode, &fa);
+
+       f2fs_fill_fsxattr(inode, &old_fa);
+       err = vfs_ioc_fssetxattr_check(inode, &old_fa, &fa);
        if (err)
                goto out;
+
        err = f2fs_setflags_common(inode, iflags,
                        f2fs_xflags_to_iflags(F2FS_SUPPORTED_XFLAGS));
        if (err)
index 6691f526fa400b18aed0f632c6bee9106f10ce15..8974672db78f39ef929f2bb61230054ae38471e4 100644 (file)
@@ -796,6 +796,29 @@ static int move_data_block(struct inode *inode, block_t bidx,
        if (lfs_mode)
                down_write(&fio.sbi->io_order_lock);
 
+       mpage = f2fs_grab_cache_page(META_MAPPING(fio.sbi),
+                                       fio.old_blkaddr, false);
+       if (!mpage)
+               goto up_out;
+
+       fio.encrypted_page = mpage;
+
+       /* read source block in mpage */
+       if (!PageUptodate(mpage)) {
+               err = f2fs_submit_page_bio(&fio);
+               if (err) {
+                       f2fs_put_page(mpage, 1);
+                       goto up_out;
+               }
+               lock_page(mpage);
+               if (unlikely(mpage->mapping != META_MAPPING(fio.sbi) ||
+                                               !PageUptodate(mpage))) {
+                       err = -EIO;
+                       f2fs_put_page(mpage, 1);
+                       goto up_out;
+               }
+       }
+
        f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
                                        &sum, CURSEG_COLD_DATA, NULL, false);
 
@@ -803,44 +826,18 @@ static int move_data_block(struct inode *inode, block_t bidx,
                                newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS);
        if (!fio.encrypted_page) {
                err = -ENOMEM;
-               goto recover_block;
-       }
-
-       mpage = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
-                                       fio.old_blkaddr, FGP_LOCK, GFP_NOFS);
-       if (mpage) {
-               bool updated = false;
-
-               if (PageUptodate(mpage)) {
-                       memcpy(page_address(fio.encrypted_page),
-                                       page_address(mpage), PAGE_SIZE);
-                       updated = true;
-               }
                f2fs_put_page(mpage, 1);
-               invalidate_mapping_pages(META_MAPPING(fio.sbi),
-                                       fio.old_blkaddr, fio.old_blkaddr);
-               if (updated)
-                       goto write_page;
-       }
-
-       err = f2fs_submit_page_bio(&fio);
-       if (err)
-               goto put_page_out;
-
-       /* write page */
-       lock_page(fio.encrypted_page);
-
-       if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi))) {
-               err = -EIO;
-               goto put_page_out;
-       }
-       if (unlikely(!PageUptodate(fio.encrypted_page))) {
-               err = -EIO;
-               goto put_page_out;
+               goto recover_block;
        }
 
-write_page:
+       /* write target block */
        f2fs_wait_on_page_writeback(fio.encrypted_page, DATA, true, true);
+       memcpy(page_address(fio.encrypted_page),
+                               page_address(mpage), PAGE_SIZE);
+       f2fs_put_page(mpage, 1);
+       invalidate_mapping_pages(META_MAPPING(fio.sbi),
+                               fio.old_blkaddr, fio.old_blkaddr);
+
        set_page_dirty(fio.encrypted_page);
        if (clear_page_dirty_for_io(fio.encrypted_page))
                dec_page_count(fio.sbi, F2FS_DIRTY_META);
@@ -871,11 +868,12 @@ write_page:
 put_page_out:
        f2fs_put_page(fio.encrypted_page, 1);
 recover_block:
-       if (lfs_mode)
-               up_write(&fio.sbi->io_order_lock);
        if (err)
                f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr,
                                                                true, true);
+up_out:
+       if (lfs_mode)
+               up_write(&fio.sbi->io_order_lock);
 put_out:
        f2fs_put_dnode(&dn);
 out:
index 6de6cda440315d68b4055f0c428a6ed302624b30..78a1b873e48ade9259c2592bd263fb86f22fdf16 100644 (file)
@@ -2422,6 +2422,12 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
        size_t crc_offset = 0;
        __u32 crc = 0;
 
+       if (le32_to_cpu(raw_super->magic) != F2FS_SUPER_MAGIC) {
+               f2fs_info(sbi, "Magic Mismatch, valid(0x%x) - read(0x%x)",
+                         F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic));
+               return -EINVAL;
+       }
+
        /* Check checksum_offset and crc in superblock */
        if (__F2FS_HAS_FEATURE(raw_super, F2FS_FEATURE_SB_CHKSUM)) {
                crc_offset = le32_to_cpu(raw_super->checksum_offset);
@@ -2429,26 +2435,20 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                        offsetof(struct f2fs_super_block, crc)) {
                        f2fs_info(sbi, "Invalid SB checksum offset: %zu",
                                  crc_offset);
-                       return 1;
+                       return -EFSCORRUPTED;
                }
                crc = le32_to_cpu(raw_super->crc);
                if (!f2fs_crc_valid(sbi, crc, raw_super, crc_offset)) {
                        f2fs_info(sbi, "Invalid SB checksum value: %u", crc);
-                       return 1;
+                       return -EFSCORRUPTED;
                }
        }
 
-       if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) {
-               f2fs_info(sbi, "Magic Mismatch, valid(0x%x) - read(0x%x)",
-                         F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic));
-               return 1;
-       }
-
        /* Currently, support only 4KB page cache size */
        if (F2FS_BLKSIZE != PAGE_SIZE) {
                f2fs_info(sbi, "Invalid page_cache_size (%lu), supports only 4KB",
                          PAGE_SIZE);
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        /* Currently, support only 4KB block size */
@@ -2456,14 +2456,14 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
        if (blocksize != F2FS_BLKSIZE) {
                f2fs_info(sbi, "Invalid blocksize (%u), supports only 4KB",
                          blocksize);
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        /* check log blocks per segment */
        if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) {
                f2fs_info(sbi, "Invalid log blocks per segment (%u)",
                          le32_to_cpu(raw_super->log_blocks_per_seg));
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        /* Currently, support 512/1024/2048/4096 bytes sector size */
@@ -2473,7 +2473,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                                F2FS_MIN_LOG_SECTOR_SIZE) {
                f2fs_info(sbi, "Invalid log sectorsize (%u)",
                          le32_to_cpu(raw_super->log_sectorsize));
-               return 1;
+               return -EFSCORRUPTED;
        }
        if (le32_to_cpu(raw_super->log_sectors_per_block) +
                le32_to_cpu(raw_super->log_sectorsize) !=
@@ -2481,7 +2481,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                f2fs_info(sbi, "Invalid log sectors per block(%u) log sectorsize(%u)",
                          le32_to_cpu(raw_super->log_sectors_per_block),
                          le32_to_cpu(raw_super->log_sectorsize));
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        segment_count = le32_to_cpu(raw_super->segment_count);
@@ -2495,7 +2495,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
        if (segment_count > F2FS_MAX_SEGMENT ||
                                segment_count < F2FS_MIN_SEGMENTS) {
                f2fs_info(sbi, "Invalid segment count (%u)", segment_count);
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        if (total_sections > segment_count ||
@@ -2503,25 +2503,25 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                        segs_per_sec > segment_count || !segs_per_sec) {
                f2fs_info(sbi, "Invalid segment/section count (%u, %u x %u)",
                          segment_count, total_sections, segs_per_sec);
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        if ((segment_count / segs_per_sec) < total_sections) {
                f2fs_info(sbi, "Small segment_count (%u < %u * %u)",
                          segment_count, segs_per_sec, total_sections);
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        if (segment_count > (le64_to_cpu(raw_super->block_count) >> 9)) {
                f2fs_info(sbi, "Wrong segment_count / block_count (%u > %llu)",
                          segment_count, le64_to_cpu(raw_super->block_count));
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        if (secs_per_zone > total_sections || !secs_per_zone) {
                f2fs_info(sbi, "Wrong secs_per_zone / total_sections (%u, %u)",
                          secs_per_zone, total_sections);
-               return 1;
+               return -EFSCORRUPTED;
        }
        if (le32_to_cpu(raw_super->extension_count) > F2FS_MAX_EXTENSION ||
                        raw_super->hot_ext_count > F2FS_MAX_EXTENSION ||
@@ -2531,7 +2531,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                          le32_to_cpu(raw_super->extension_count),
                          raw_super->hot_ext_count,
                          F2FS_MAX_EXTENSION);
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        if (le32_to_cpu(raw_super->cp_payload) >
@@ -2539,7 +2539,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                f2fs_info(sbi, "Insane cp_payload (%u > %u)",
                          le32_to_cpu(raw_super->cp_payload),
                          blocks_per_seg - F2FS_CP_PACKS);
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        /* check reserved ino info */
@@ -2550,12 +2550,12 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                          le32_to_cpu(raw_super->node_ino),
                          le32_to_cpu(raw_super->meta_ino),
                          le32_to_cpu(raw_super->root_ino));
-               return 1;
+               return -EFSCORRUPTED;
        }
 
        /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */
        if (sanity_check_area_boundary(sbi, bh))
-               return 1;
+               return -EFSCORRUPTED;
 
        return 0;
 }
@@ -2870,10 +2870,10 @@ static int read_raw_super_block(struct f2fs_sb_info *sbi,
                }
 
                /* sanity checking of raw super */
-               if (sanity_check_raw_super(sbi, bh)) {
+               err = sanity_check_raw_super(sbi, bh);
+               if (err) {
                        f2fs_err(sbi, "Can't find valid F2FS filesystem in %dth superblock",
                                 block + 1);
-                       err = -EFSCORRUPTED;
                        brelse(bh);
                        continue;
                }
index 79581b9bdebb357a62cfd0d821b4de0d74349b03..4f8b5fd6c81fdeafccff2ffbf4409ada329b7d00 100644 (file)
@@ -390,6 +390,19 @@ static int fillup_metapath(struct gfs2_inode *ip, struct metapath *mp, int h)
        return mp->mp_aheight - x - 1;
 }
 
+static sector_t metapath_to_block(struct gfs2_sbd *sdp, struct metapath *mp)
+{
+       sector_t factor = 1, block = 0;
+       int hgt;
+
+       for (hgt = mp->mp_fheight - 1; hgt >= 0; hgt--) {
+               if (hgt < mp->mp_aheight)
+                       block += mp->mp_list[hgt] * factor;
+               factor *= sdp->sd_inptrs;
+       }
+       return block;
+}
+
 static void release_metapath(struct metapath *mp)
 {
        int i;
@@ -430,60 +443,84 @@ static inline unsigned int gfs2_extent_length(struct buffer_head *bh, __be64 *pt
        return ptr - first;
 }
 
-typedef const __be64 *(*gfs2_metadata_walker)(
-               struct metapath *mp,
-               const __be64 *start, const __be64 *end,
-               u64 factor, void *data);
+enum walker_status { WALK_STOP, WALK_FOLLOW, WALK_CONTINUE };
+
+/*
+ * gfs2_metadata_walker - walk an indirect block
+ * @mp: Metapath to indirect block
+ * @ptrs: Number of pointers to look at
+ *
+ * When returning WALK_FOLLOW, the walker must update @mp to point at the right
+ * indirect block to follow.
+ */
+typedef enum walker_status (*gfs2_metadata_walker)(struct metapath *mp,
+                                                  unsigned int ptrs);
 
-#define WALK_STOP ((__be64 *)0)
-#define WALK_NEXT ((__be64 *)1)
+/*
+ * gfs2_walk_metadata - walk a tree of indirect blocks
+ * @inode: The inode
+ * @mp: Starting point of walk
+ * @max_len: Maximum number of blocks to walk
+ * @walker: Called during the walk
+ *
+ * Returns 1 if the walk was stopped by @walker, 0 if we went past @max_len or
+ * past the end of metadata, and a negative error code otherwise.
+ */
 
-static int gfs2_walk_metadata(struct inode *inode, sector_t lblock,
-               u64 len, struct metapath *mp, gfs2_metadata_walker walker,
-               void *data)
+static int gfs2_walk_metadata(struct inode *inode, struct metapath *mp,
+               u64 max_len, gfs2_metadata_walker walker)
 {
-       struct metapath clone;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
-       const __be64 *start, *end, *ptr;
        u64 factor = 1;
        unsigned int hgt;
-       int ret = 0;
+       int ret;
 
-       for (hgt = ip->i_height - 1; hgt >= mp->mp_aheight; hgt--)
+       /*
+        * The walk starts in the lowest allocated indirect block, which may be
+        * before the position indicated by @mp.  Adjust @max_len accordingly
+        * to avoid a short walk.
+        */
+       for (hgt = mp->mp_fheight - 1; hgt >= mp->mp_aheight; hgt--) {
+               max_len += mp->mp_list[hgt] * factor;
+               mp->mp_list[hgt] = 0;
                factor *= sdp->sd_inptrs;
+       }
 
        for (;;) {
-               u64 step;
+               u16 start = mp->mp_list[hgt];
+               enum walker_status status;
+               unsigned int ptrs;
+               u64 len;
 
                /* Walk indirect block. */
-               start = metapointer(hgt, mp);
-               end = metaend(hgt, mp);
-
-               step = (end - start) * factor;
-               if (step > len)
-                       end = start + DIV_ROUND_UP_ULL(len, factor);
-
-               ptr = walker(mp, start, end, factor, data);
-               if (ptr == WALK_STOP)
+               ptrs = (hgt >= 1 ? sdp->sd_inptrs : sdp->sd_diptrs) - start;
+               len = ptrs * factor;
+               if (len > max_len)
+                       ptrs = DIV_ROUND_UP_ULL(max_len, factor);
+               status = walker(mp, ptrs);
+               switch (status) {
+               case WALK_STOP:
+                       return 1;
+               case WALK_FOLLOW:
+                       BUG_ON(mp->mp_aheight == mp->mp_fheight);
+                       ptrs = mp->mp_list[hgt] - start;
+                       len = ptrs * factor;
                        break;
-               if (step >= len)
+               case WALK_CONTINUE:
                        break;
-               len -= step;
-               if (ptr != WALK_NEXT) {
-                       BUG_ON(!*ptr);
-                       mp->mp_list[hgt] += ptr - start;
-                       goto fill_up_metapath;
                }
+               if (len >= max_len)
+                       break;
+               max_len -= len;
+               if (status == WALK_FOLLOW)
+                       goto fill_up_metapath;
 
 lower_metapath:
                /* Decrease height of metapath. */
-               if (mp != &clone) {
-                       clone_metapath(&clone, mp);
-                       mp = &clone;
-               }
                brelse(mp->mp_bh[hgt]);
                mp->mp_bh[hgt] = NULL;
+               mp->mp_list[hgt] = 0;
                if (!hgt)
                        break;
                hgt--;
@@ -491,10 +528,7 @@ lower_metapath:
 
                /* Advance in metadata tree. */
                (mp->mp_list[hgt])++;
-               start = metapointer(hgt, mp);
-               end = metaend(hgt, mp);
-               if (start >= end) {
-                       mp->mp_list[hgt] = 0;
+               if (mp->mp_list[hgt] >= sdp->sd_inptrs) {
                        if (!hgt)
                                break;
                        goto lower_metapath;
@@ -502,44 +536,36 @@ lower_metapath:
 
 fill_up_metapath:
                /* Increase height of metapath. */
-               if (mp != &clone) {
-                       clone_metapath(&clone, mp);
-                       mp = &clone;
-               }
                ret = fillup_metapath(ip, mp, ip->i_height - 1);
                if (ret < 0)
-                       break;
+                       return ret;
                hgt += ret;
                for (; ret; ret--)
                        do_div(factor, sdp->sd_inptrs);
                mp->mp_aheight = hgt + 1;
        }
-       if (mp == &clone)
-               release_metapath(mp);
-       return ret;
+       return 0;
 }
 
-struct gfs2_hole_walker_args {
-       u64 blocks;
-};
-
-static const __be64 *gfs2_hole_walker(struct metapath *mp,
-               const __be64 *start, const __be64 *end,
-               u64 factor, void *data)
+static enum walker_status gfs2_hole_walker(struct metapath *mp,
+                                          unsigned int ptrs)
 {
-       struct gfs2_hole_walker_args *args = data;
-       const __be64 *ptr;
+       const __be64 *start, *ptr, *end;
+       unsigned int hgt;
+
+       hgt = mp->mp_aheight - 1;
+       start = metapointer(hgt, mp);
+       end = start + ptrs;
 
        for (ptr = start; ptr < end; ptr++) {
                if (*ptr) {
-                       args->blocks += (ptr - start) * factor;
+                       mp->mp_list[hgt] += ptr - start;
                        if (mp->mp_aheight == mp->mp_fheight)
                                return WALK_STOP;
-                       return ptr;  /* increase height */
+                       return WALK_FOLLOW;
                }
        }
-       args->blocks += (end - start) * factor;
-       return WALK_NEXT;
+       return WALK_CONTINUE;
 }
 
 /**
@@ -557,12 +583,24 @@ static const __be64 *gfs2_hole_walker(struct metapath *mp,
 static int gfs2_hole_size(struct inode *inode, sector_t lblock, u64 len,
                          struct metapath *mp, struct iomap *iomap)
 {
-       struct gfs2_hole_walker_args args = { };
-       int ret = 0;
+       struct metapath clone;
+       u64 hole_size;
+       int ret;
 
-       ret = gfs2_walk_metadata(inode, lblock, len, mp, gfs2_hole_walker, &args);
-       if (!ret)
-               iomap->length = args.blocks << inode->i_blkbits;
+       clone_metapath(&clone, mp);
+       ret = gfs2_walk_metadata(inode, &clone, len, gfs2_hole_walker);
+       if (ret < 0)
+               goto out;
+
+       if (ret == 1)
+               hole_size = metapath_to_block(GFS2_SB(inode), &clone) - lblock;
+       else
+               hole_size = len;
+       iomap->length = hole_size << inode->i_blkbits;
+       ret = 0;
+
+out:
+       release_metapath(&clone);
        return ret;
 }
 
@@ -1002,11 +1040,16 @@ static void gfs2_iomap_page_done(struct inode *inode, loff_t pos,
                                 unsigned copied, struct page *page,
                                 struct iomap *iomap)
 {
+       struct gfs2_trans *tr = current->journal_info;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
 
        if (page && !gfs2_is_stuffed(ip))
                gfs2_page_add_databufs(ip, page, offset_in_page(pos), copied);
+
+       if (tr->tr_num_buf_new)
+               __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+
        gfs2_trans_end(sdp);
 }
 
@@ -1099,8 +1142,6 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
                tr = current->journal_info;
                if (tr->tr_num_buf_new)
                        __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
-               else
-                       gfs2_trans_add_meta(ip->i_gl, mp->mp_bh[0]);
 
                gfs2_trans_end(sdp);
        }
@@ -1181,10 +1222,16 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
 
        if (ip->i_qadata && ip->i_qadata->qa_qd_num)
                gfs2_quota_unlock(ip);
+
+       if (unlikely(!written))
+               goto out_unlock;
+
        if (iomap->flags & IOMAP_F_SIZE_CHANGED)
                mark_inode_dirty(inode);
-       gfs2_write_unlock(inode);
+       set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
 
+out_unlock:
+       gfs2_write_unlock(inode);
 out:
        return 0;
 }
index e2a66e12fbc634f1eb913ef80f504dbd470edd69..cfb48bd088e12a0bbd8847e2b78e7ba14cb26fd8 100644 (file)
@@ -202,7 +202,7 @@ struct async_list {
 
        struct file             *file;
        off_t                   io_end;
-       size_t                  io_pages;
+       size_t                  io_len;
 };
 
 struct io_ring_ctx {
@@ -333,7 +333,8 @@ struct io_kiocb {
 #define REQ_F_IO_DRAIN         16      /* drain existing IO first */
 #define REQ_F_IO_DRAINED       32      /* drain done */
 #define REQ_F_LINK             64      /* linked sqes */
-#define REQ_F_FAIL_LINK                128     /* fail rest of links */
+#define REQ_F_LINK_DONE                128     /* linked sqes done */
+#define REQ_F_FAIL_LINK                256     /* fail rest of links */
        u64                     user_data;
        u32                     result;
        u32                     sequence;
@@ -429,7 +430,7 @@ static inline bool io_sequence_defer(struct io_ring_ctx *ctx,
        if ((req->flags & (REQ_F_IO_DRAIN|REQ_F_IO_DRAINED)) != REQ_F_IO_DRAIN)
                return false;
 
-       return req->sequence > ctx->cached_cq_tail + ctx->sq_ring->dropped;
+       return req->sequence != ctx->cached_cq_tail + ctx->sq_ring->dropped;
 }
 
 static struct io_kiocb *io_get_deferred_req(struct io_ring_ctx *ctx)
@@ -632,6 +633,7 @@ static void io_req_link_next(struct io_kiocb *req)
                        nxt->flags |= REQ_F_LINK;
                }
 
+               nxt->flags |= REQ_F_LINK_DONE;
                INIT_WORK(&nxt->work, io_sq_wq_submit_work);
                queue_work(req->ctx->sqo_wq, &nxt->work);
        }
@@ -677,6 +679,13 @@ static void io_put_req(struct io_kiocb *req)
                io_free_req(req);
 }
 
+static unsigned io_cqring_events(struct io_cq_ring *ring)
+{
+       /* See comment at the top of this file */
+       smp_rmb();
+       return READ_ONCE(ring->r.tail) - READ_ONCE(ring->r.head);
+}
+
 /*
  * Find and free completed poll iocbs
  */
@@ -769,7 +778,7 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
 static int io_iopoll_getevents(struct io_ring_ctx *ctx, unsigned int *nr_events,
                                long min)
 {
-       while (!list_empty(&ctx->poll_list)) {
+       while (!list_empty(&ctx->poll_list) && !need_resched()) {
                int ret;
 
                ret = io_do_iopoll(ctx, nr_events, min);
@@ -796,6 +805,12 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
                unsigned int nr_events = 0;
 
                io_iopoll_getevents(ctx, &nr_events, 1);
+
+               /*
+                * Ensure we allow local-to-the-cpu processing to take place,
+                * in this case we need to ensure that we reap all events.
+                */
+               cond_resched();
        }
        mutex_unlock(&ctx->uring_lock);
 }
@@ -803,11 +818,42 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
 static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
                           long min)
 {
-       int ret = 0;
+       int iters, ret = 0;
+
+       /*
+        * We disallow the app entering submit/complete with polling, but we
+        * still need to lock the ring to prevent racing with polled issue
+        * that got punted to a workqueue.
+        */
+       mutex_lock(&ctx->uring_lock);
 
+       iters = 0;
        do {
                int tmin = 0;
 
+               /*
+                * Don't enter poll loop if we already have events pending.
+                * If we do, we can potentially be spinning for commands that
+                * already triggered a CQE (eg in error).
+                */
+               if (io_cqring_events(ctx->cq_ring))
+                       break;
+
+               /*
+                * If a submit got punted to a workqueue, we can have the
+                * application entering polling for a command before it gets
+                * issued. That app will hold the uring_lock for the duration
+                * of the poll right here, so we need to take a breather every
+                * now and then to ensure that the issue has a chance to add
+                * the poll to the issued list. Otherwise we can spin here
+                * forever, while the workqueue is stuck trying to acquire the
+                * very same mutex.
+                */
+               if (!(++iters & 7)) {
+                       mutex_unlock(&ctx->uring_lock);
+                       mutex_lock(&ctx->uring_lock);
+               }
+
                if (*nr_events < min)
                        tmin = min - *nr_events;
 
@@ -817,6 +863,7 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
                ret = 0;
        } while (min && !*nr_events && !need_resched());
 
+       mutex_unlock(&ctx->uring_lock);
        return ret;
 }
 
@@ -1064,8 +1111,42 @@ static int io_import_fixed(struct io_ring_ctx *ctx, int rw,
         */
        offset = buf_addr - imu->ubuf;
        iov_iter_bvec(iter, rw, imu->bvec, imu->nr_bvecs, offset + len);
-       if (offset)
-               iov_iter_advance(iter, offset);
+
+       if (offset) {
+               /*
+                * Don't use iov_iter_advance() here, as it's really slow for
+                * using the latter parts of a big fixed buffer - it iterates
+                * over each segment manually. We can cheat a bit here, because
+                * we know that:
+                *
+                * 1) it's a BVEC iter, we set it up
+                * 2) all bvecs are PAGE_SIZE in size, except potentially the
+                *    first and last bvec
+                *
+                * So just find our index, and adjust the iterator afterwards.
+                * If the offset is within the first bvec (or the whole first
+                * bvec, just use iov_iter_advance(). This makes it easier
+                * since we can just skip the first segment, which may not
+                * be PAGE_SIZE aligned.
+                */
+               const struct bio_vec *bvec = imu->bvec;
+
+               if (offset <= bvec->bv_len) {
+                       iov_iter_advance(iter, offset);
+               } else {
+                       unsigned long seg_skip;
+
+                       /* skip first vec */
+                       offset -= bvec->bv_len;
+                       seg_skip = 1 + (offset >> PAGE_SHIFT);
+
+                       iter->bvec = bvec + seg_skip;
+                       iter->nr_segs -= seg_skip;
+                       iter->count -= bvec->bv_len + offset;
+                       iter->iov_offset = offset & ~PAGE_MASK;
+               }
+       }
+
        return 0;
 }
 
@@ -1120,28 +1201,26 @@ static void io_async_list_note(int rw, struct io_kiocb *req, size_t len)
        off_t io_end = kiocb->ki_pos + len;
 
        if (filp == async_list->file && kiocb->ki_pos == async_list->io_end) {
-               unsigned long max_pages;
+               unsigned long max_bytes;
 
                /* Use 8x RA size as a decent limiter for both reads/writes */
-               max_pages = filp->f_ra.ra_pages;
-               if (!max_pages)
-                       max_pages = VM_READAHEAD_PAGES;
-               max_pages *= 8;
-
-               /* If max pages are exceeded, reset the state */
-               len >>= PAGE_SHIFT;
-               if (async_list->io_pages + len <= max_pages) {
+               max_bytes = filp->f_ra.ra_pages << (PAGE_SHIFT + 3);
+               if (!max_bytes)
+                       max_bytes = VM_READAHEAD_PAGES << (PAGE_SHIFT + 3);
+
+               /* If max len are exceeded, reset the state */
+               if (async_list->io_len + len <= max_bytes) {
                        req->flags |= REQ_F_SEQ_PREV;
-                       async_list->io_pages += len;
+                       async_list->io_len += len;
                } else {
                        io_end = 0;
-                       async_list->io_pages = 0;
+                       async_list->io_len = 0;
                }
        }
 
        /* New file? Reset state. */
        if (async_list->file != filp) {
-               async_list->io_pages = 0;
+               async_list->io_len = 0;
                async_list->file = filp;
        }
        async_list->io_end = io_end;
@@ -1630,6 +1709,8 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        INIT_LIST_HEAD(&poll->wait.entry);
        init_waitqueue_func_entry(&poll->wait, io_poll_wake);
 
+       INIT_LIST_HEAD(&req->list);
+
        mask = vfs_poll(poll->file, &ipt.pt) & poll->events;
 
        spin_lock_irq(&ctx->completion_lock);
@@ -1800,6 +1881,7 @@ restart:
        do {
                struct sqe_submit *s = &req->submit;
                const struct io_uring_sqe *sqe = s->sqe;
+               unsigned int flags = req->flags;
 
                /* Ensure we clear previously set non-block flag */
                req->rw.ki_flags &= ~IOCB_NOWAIT;
@@ -1844,6 +1926,10 @@ restart:
                /* async context always use a copy of the sqe */
                kfree(sqe);
 
+               /* req from defer and link list needn't decrease async cnt */
+               if (flags & (REQ_F_IO_DRAINED | REQ_F_LINK_DONE))
+                       goto out;
+
                if (!async_list)
                        break;
                if (!list_empty(&req_list)) {
@@ -1891,6 +1977,7 @@ restart:
                }
        }
 
+out:
        if (cur_mm) {
                set_fs(old_fs);
                unuse_mm(cur_mm);
@@ -1917,6 +2004,10 @@ static bool io_add_to_prev_work(struct async_list *list, struct io_kiocb *req)
        ret = true;
        spin_lock(&list->lock);
        list_add_tail(&req->list, &list->list);
+       /*
+        * Ensure we see a simultaneous modification from io_sq_wq_submit_work()
+        */
+       smp_mb();
        if (!atomic_read(&list->cnt)) {
                list_del_init(&req->list);
                ret = false;
@@ -1977,6 +2068,15 @@ static int io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
 {
        int ret;
 
+       ret = io_req_defer(ctx, req, s->sqe);
+       if (ret) {
+               if (ret != -EIOCBQUEUED) {
+                       io_free_req(req);
+                       io_cqring_add_event(ctx, s->sqe->user_data, ret);
+               }
+               return 0;
+       }
+
        ret = __io_submit_sqe(ctx, req, s, true);
        if (ret == -EAGAIN && !(req->flags & REQ_F_NOWAIT)) {
                struct io_uring_sqe *sqe_copy;
@@ -2049,13 +2149,6 @@ err:
                return;
        }
 
-       ret = io_req_defer(ctx, req, s->sqe);
-       if (ret) {
-               if (ret != -EIOCBQUEUED)
-                       goto err_req;
-               return;
-       }
-
        /*
         * If we already have a head request, queue this one for async
         * submittal once the head completes. If we don't have a head but
@@ -2232,15 +2325,7 @@ static int io_sq_thread(void *data)
                        unsigned nr_events = 0;
 
                        if (ctx->flags & IORING_SETUP_IOPOLL) {
-                               /*
-                                * We disallow the app entering submit/complete
-                                * with polling, but we still need to lock the
-                                * ring to prevent racing with polled issue
-                                * that got punted to a workqueue.
-                                */
-                               mutex_lock(&ctx->uring_lock);
                                io_iopoll_check(ctx, &nr_events, 0);
-                               mutex_unlock(&ctx->uring_lock);
                        } else {
                                /*
                                 * Normal IO, just pretend everything completed.
@@ -2385,13 +2470,6 @@ static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit)
        return submit;
 }
 
-static unsigned io_cqring_events(struct io_cq_ring *ring)
-{
-       /* See comment at the top of this file */
-       smp_rmb();
-       return READ_ONCE(ring->r.tail) - READ_ONCE(ring->r.head);
-}
-
 /*
  * Wait until events become available, if we don't already have some. The
  * application must reap them itself, as they reside on the shared cq ring.
@@ -3142,9 +3220,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                min_complete = min(min_complete, ctx->cq_entries);
 
                if (ctx->flags & IORING_SETUP_IOPOLL) {
-                       mutex_lock(&ctx->uring_lock);
                        ret = io_iopoll_check(ctx, &nr_events, min_complete);
-                       mutex_unlock(&ctx->uring_lock);
                } else {
                        ret = io_cqring_wait(ctx, min_complete, sig, sigsz);
                }
index 2d165388d9524fe101f31913742b8f52a598de3f..93cd11938bf55a5912e346398c47cbe1cbaaffea 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-or-newer
+# SPDX-License-Identifier: GPL-2.0-or-later
 #
 # Copyright (c) 2019 Oracle.
 # All Rights Reserved.
index 6464ea4acba9418f489fe8d5f867f55ef232b4e3..d28d30b1304397eac7c92a4be3f60e02a9a536d7 100644 (file)
@@ -1463,7 +1463,6 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
                        p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
 
                disconnect = disconnect_mount(p, how);
-
                if (mnt_has_parent(p)) {
                        mnt_add_count(p->mnt_parent, -1);
                        if (!disconnect) {
@@ -1471,10 +1470,11 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
                                list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts);
                        } else {
                                umount_mnt(p);
-                               hlist_add_head(&p->mnt_umount, &unmounted);
                        }
                }
                change_mnt_propagation(p, MS_PRIVATE);
+               if (disconnect)
+                       hlist_add_head(&p->mnt_umount, &unmounted);
        }
 }
 
index 0ff3facf81dac61fe99c6eff078e0a23b000d2e4..071b90a45933a4b95c176e8042a29130e07a71f1 100644 (file)
@@ -153,7 +153,7 @@ again:
                /* Block nfs4_proc_unlck */
                mutex_lock(&sp->so_delegreturn_mutex);
                seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
-               err = nfs4_open_delegation_recall(ctx, state, stateid, type);
+               err = nfs4_open_delegation_recall(ctx, state, stateid);
                if (!err)
                        err = nfs_delegation_claim_locks(state, stateid);
                if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
@@ -1046,6 +1046,22 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp)
        nfs4_schedule_state_manager(clp);
 }
 
+static void
+nfs_delegation_test_free_expired(struct inode *inode,
+               nfs4_stateid *stateid,
+               const struct cred *cred)
+{
+       struct nfs_server *server = NFS_SERVER(inode);
+       const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops;
+       int status;
+
+       if (!cred)
+               return;
+       status = ops->test_and_free_expired(server, stateid, cred);
+       if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
+               nfs_remove_bad_delegation(inode, stateid);
+}
+
 /**
  * nfs_reap_expired_delegations - reap expired delegations
  * @clp: nfs_client to process
@@ -1057,7 +1073,6 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp)
  */
 void nfs_reap_expired_delegations(struct nfs_client *clp)
 {
-       const struct nfs4_minor_version_ops *ops = clp->cl_mvops;
        struct nfs_delegation *delegation;
        struct nfs_server *server;
        struct inode *inode;
@@ -1088,11 +1103,7 @@ restart:
                        nfs4_stateid_copy(&stateid, &delegation->stateid);
                        clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
                        rcu_read_unlock();
-                       if (cred != NULL &&
-                           ops->test_and_free_expired(server, &stateid, cred) < 0) {
-                               nfs_revoke_delegation(inode, &stateid);
-                               nfs_inode_find_state_and_recover(inode, &stateid);
-                       }
+                       nfs_delegation_test_free_expired(inode, &stateid, cred);
                        put_cred(cred);
                        if (nfs4_server_rebooted(clp)) {
                                nfs_inode_mark_test_expired_delegation(server,inode);
index 5799777df5ec860d8eaee84d2ca495b31ea31d09..9eb87ae4c98276632ab799e5b66487df9cdcd3e4 100644 (file)
@@ -63,7 +63,7 @@ void nfs_reap_expired_delegations(struct nfs_client *clp);
 
 /* NFSv4 delegation-related procedures */
 int nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, const nfs4_stateid *stateid, int issync);
-int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid, fmode_t type);
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
 int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid);
 bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred);
 bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
index 8d501093660f4a052a781d61c46a507fa4c7c1ca..0adfd88401108029c2fb065db3fd8307580aa427 100644 (file)
@@ -1487,7 +1487,7 @@ static int nfs_finish_open(struct nfs_open_context *ctx,
        if (S_ISREG(file->f_path.dentry->d_inode->i_mode))
                nfs_file_set_open_context(file, ctx);
        else
-               err = -ESTALE;
+               err = -EOPENSTALE;
 out:
        return err;
 }
index 0cb44240616889f62616f7804be7dd909c3b9de1..222d7115db713a76d1e4312ec1c22752e38f3709 100644 (file)
@@ -401,15 +401,21 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
        unsigned long bytes = 0;
        struct nfs_direct_req *dreq = hdr->dreq;
 
-       if (test_bit(NFS_IOHDR_REDO, &hdr->flags))
-               goto out_put;
-
        spin_lock(&dreq->lock);
-       if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && (hdr->good_bytes == 0))
+       if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
                dreq->error = hdr->error;
-       else
+
+       if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+               spin_unlock(&dreq->lock);
+               goto out_put;
+       }
+
+       if (hdr->good_bytes != 0)
                nfs_direct_good_bytes(dreq, hdr);
 
+       if (test_bit(NFS_IOHDR_EOF, &hdr->flags))
+               dreq->error = 0;
+
        spin_unlock(&dreq->lock);
 
        while (!list_empty(&hdr->pages)) {
@@ -782,16 +788,19 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
        bool request_commit = false;
        struct nfs_page *req = nfs_list_entry(hdr->pages.next);
 
-       if (test_bit(NFS_IOHDR_REDO, &hdr->flags))
-               goto out_put;
-
        nfs_init_cinfo_from_dreq(&cinfo, dreq);
 
        spin_lock(&dreq->lock);
 
        if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
                dreq->error = hdr->error;
-       if (dreq->error == 0) {
+
+       if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+               spin_unlock(&dreq->lock);
+               goto out_put;
+       }
+
+       if (hdr->good_bytes != 0) {
                nfs_direct_good_bytes(dreq, hdr);
                if (nfs_write_need_commit(hdr)) {
                        if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES)
index b04e20d28162d489424606df91f452a0a64c2d4c..5657b7f2611f19e8449e7e51e8b363ef20d573f1 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
 #include <linux/nfs_page.h>
 #include <linux/module.h>
 #include <linux/sched/mm.h>
@@ -928,7 +929,9 @@ retry:
        pgm = &pgio->pg_mirrors[0];
        pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize;
 
-       pgio->pg_maxretrans = io_maxretrans;
+       if (NFS_SERVER(pgio->pg_inode)->flags &
+                       (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
+               pgio->pg_maxretrans = io_maxretrans;
        return;
 out_nolseg:
        if (pgio->pg_error < 0)
@@ -940,6 +943,7 @@ out_mds:
                        pgio->pg_lseg);
        pnfs_put_lseg(pgio->pg_lseg);
        pgio->pg_lseg = NULL;
+       pgio->pg_maxretrans = 0;
        nfs_pageio_reset_read_mds(pgio);
 }
 
@@ -1000,7 +1004,9 @@ retry:
                pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].wsize;
        }
 
-       pgio->pg_maxretrans = io_maxretrans;
+       if (NFS_SERVER(pgio->pg_inode)->flags &
+                       (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
+               pgio->pg_maxretrans = io_maxretrans;
        return;
 
 out_mds:
@@ -1010,6 +1016,7 @@ out_mds:
                        pgio->pg_lseg);
        pnfs_put_lseg(pgio->pg_lseg);
        pgio->pg_lseg = NULL;
+       pgio->pg_maxretrans = 0;
        nfs_pageio_reset_write_mds(pgio);
 }
 
@@ -1148,8 +1155,6 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
                break;
        case -NFS4ERR_RETRY_UNCACHED_REP:
                break;
-       case -EAGAIN:
-               return -NFS4ERR_RESET_TO_PNFS;
        /* Invalidate Layout errors */
        case -NFS4ERR_PNFS_NO_LAYOUT:
        case -ESTALE:           /* mapped NFS4ERR_STALE */
@@ -1210,7 +1215,6 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task,
        case -EBADHANDLE:
        case -ELOOP:
        case -ENOSPC:
-       case -EAGAIN:
                break;
        case -EJUKEBOX:
                nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY);
@@ -1445,16 +1449,6 @@ static void ff_layout_read_prepare_v4(struct rpc_task *task, void *data)
        ff_layout_read_prepare_common(task, hdr);
 }
 
-static void
-ff_layout_io_prepare_transmit(struct rpc_task *task,
-               void *data)
-{
-       struct nfs_pgio_header *hdr = data;
-
-       if (!pnfs_is_valid_lseg(hdr->lseg))
-               rpc_exit(task, -EAGAIN);
-}
-
 static void ff_layout_read_call_done(struct rpc_task *task, void *data)
 {
        struct nfs_pgio_header *hdr = data;
@@ -1740,7 +1734,6 @@ static void ff_layout_commit_release(void *data)
 
 static const struct rpc_call_ops ff_layout_read_call_ops_v3 = {
        .rpc_call_prepare = ff_layout_read_prepare_v3,
-       .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
        .rpc_call_done = ff_layout_read_call_done,
        .rpc_count_stats = ff_layout_read_count_stats,
        .rpc_release = ff_layout_read_release,
@@ -1748,7 +1741,6 @@ static const struct rpc_call_ops ff_layout_read_call_ops_v3 = {
 
 static const struct rpc_call_ops ff_layout_read_call_ops_v4 = {
        .rpc_call_prepare = ff_layout_read_prepare_v4,
-       .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
        .rpc_call_done = ff_layout_read_call_done,
        .rpc_count_stats = ff_layout_read_count_stats,
        .rpc_release = ff_layout_read_release,
@@ -1756,7 +1748,6 @@ static const struct rpc_call_ops ff_layout_read_call_ops_v4 = {
 
 static const struct rpc_call_ops ff_layout_write_call_ops_v3 = {
        .rpc_call_prepare = ff_layout_write_prepare_v3,
-       .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
        .rpc_call_done = ff_layout_write_call_done,
        .rpc_count_stats = ff_layout_write_count_stats,
        .rpc_release = ff_layout_write_release,
@@ -1764,7 +1755,6 @@ static const struct rpc_call_ops ff_layout_write_call_ops_v3 = {
 
 static const struct rpc_call_ops ff_layout_write_call_ops_v4 = {
        .rpc_call_prepare = ff_layout_write_prepare_v4,
-       .rpc_call_prepare_transmit = ff_layout_io_prepare_transmit,
        .rpc_call_done = ff_layout_write_call_done,
        .rpc_count_stats = ff_layout_write_count_stats,
        .rpc_release = ff_layout_write_release,
index 53507aa96b0b63df96dc504abd7dc952c50d00d8..3800ab6f08fa8f91465f6a881a89098cd413eafa 100644 (file)
@@ -114,6 +114,10 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
        struct rb_node **p, *parent;
        int diff;
 
+       nfss->fscache_key = NULL;
+       nfss->fscache = NULL;
+       if (!(nfss->options & NFS_OPTION_FSCACHE))
+               return;
        if (!uniq) {
                uniq = "";
                ulen = 1;
@@ -226,10 +230,11 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
 void nfs_fscache_init_inode(struct inode *inode)
 {
        struct nfs_fscache_inode_auxdata auxdata;
+       struct nfs_server *nfss = NFS_SERVER(inode);
        struct nfs_inode *nfsi = NFS_I(inode);
 
        nfsi->fscache = NULL;
-       if (!S_ISREG(inode->i_mode))
+       if (!(nfss->fscache && S_ISREG(inode->i_mode)))
                return;
 
        memset(&auxdata, 0, sizeof(auxdata));
index 25a75e40d91d983f1ce7124ccef80d8ddff9050d..ad041cfbf9ec0fe616441dc653225c30f0983ca8 100644 (file)
@@ -182,7 +182,7 @@ static inline void nfs_fscache_wait_on_invalidate(struct inode *inode)
  */
 static inline const char *nfs_server_fscache_state(struct nfs_server *server)
 {
-       if (server->fscache && (server->options & NFS_OPTION_FSCACHE))
+       if (server->fscache)
                return "yes";
        return "no ";
 }
index 8a1758200b579198d24b562905a24765006f87ca..2a03bfeec10a409a577eb2d773648c032d692d6e 100644 (file)
@@ -1403,12 +1403,22 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
        if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
                return 0;
 
+       if (!(fattr->valid & NFS_ATTR_FATTR_FILEID)) {
+               /* Only a mounted-on-fileid? Just exit */
+               if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+                       return 0;
        /* Has the inode gone and changed behind our back? */
-       if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)
+       } else if (nfsi->fileid != fattr->fileid) {
+               /* Is this perhaps the mounted-on fileid? */
+               if ((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) &&
+                   nfsi->fileid == fattr->mounted_on_fileid)
+                       return 0;
                return -ESTALE;
+       }
        if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
                return -ESTALE;
 
+
        if (!nfs_file_has_buffered_writers(nfsi)) {
                /* Verify a few of the more important attributes */
                if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && !inode_eq_iversion_raw(inode, fattr->change_attr))
@@ -1768,18 +1778,6 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
 EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc);
 
 
-static inline bool nfs_fileid_valid(struct nfs_inode *nfsi,
-                                   struct nfs_fattr *fattr)
-{
-       bool ret1 = true, ret2 = true;
-
-       if (fattr->valid & NFS_ATTR_FATTR_FILEID)
-               ret1 = (nfsi->fileid == fattr->fileid);
-       if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
-               ret2 = (nfsi->fileid == fattr->mounted_on_fileid);
-       return ret1 || ret2;
-}
-
 /*
  * Many nfs protocol calls return the new file attributes after
  * an operation.  Here we update the inode to reflect the state
@@ -1810,7 +1808,16 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                        nfs_display_fhandle_hash(NFS_FH(inode)),
                        atomic_read(&inode->i_count), fattr->valid);
 
-       if (!nfs_fileid_valid(nfsi, fattr)) {
+       if (!(fattr->valid & NFS_ATTR_FATTR_FILEID)) {
+               /* Only a mounted-on-fileid? Just exit */
+               if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+                       return 0;
+       /* Has the inode gone and changed behind our back? */
+       } else if (nfsi->fileid != fattr->fileid) {
+               /* Is this perhaps the mounted-on fileid? */
+               if ((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) &&
+                   nfsi->fileid == fattr->mounted_on_fileid)
+                       return 0;
                printk(KERN_ERR "NFS: server %s error: fileid changed\n"
                        "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n",
                        NFS_SERVER(inode)->nfs_client->cl_hostname,
index a2346a2f8361d56c0608af517adf5c74a7d52404..e64f810223be6b961c865e92b45afa40800a45c2 100644 (file)
@@ -775,3 +775,13 @@ static inline bool nfs_error_is_fatal(int err)
        }
 }
 
+static inline bool nfs_error_is_fatal_on_server(int err)
+{
+       switch (err) {
+       case 0:
+       case -ERESTARTSYS:
+       case -EINTR:
+               return false;
+       }
+       return nfs_error_is_fatal(err);
+}
index d778dad9a75eb1263f05e241026a2b8216241c0a..3564da1ba8a1c78d82463628c3084e0586441be9 100644 (file)
@@ -465,7 +465,8 @@ static inline void nfs4_schedule_session_recovery(struct nfs4_session *session,
 
 extern struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *, const struct cred *, gfp_t);
 extern void nfs4_put_state_owner(struct nfs4_state_owner *);
-extern void nfs4_purge_state_owners(struct nfs_server *);
+extern void nfs4_purge_state_owners(struct nfs_server *, struct list_head *);
+extern void nfs4_free_state_owners(struct list_head *head);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
 extern void nfs4_close_state(struct nfs4_state *, fmode_t);
index 616393a01c062ba99c79dd202166ef63691ece19..da6204025a2db09987791599b0bdbdcd0fc9953f 100644 (file)
@@ -758,9 +758,12 @@ out:
 
 static void nfs4_destroy_server(struct nfs_server *server)
 {
+       LIST_HEAD(freeme);
+
        nfs_server_return_all_delegations(server);
        unset_pnfs_layoutdriver(server);
-       nfs4_purge_state_owners(server);
+       nfs4_purge_state_owners(server, &freeme);
+       nfs4_free_state_owners(&freeme);
 }
 
 /*
index 96db471ca2e5c5413edf5ffe120097cb88d079ee..339663d04bf83b28f3f4426eba8419d4e750146f 100644 (file)
@@ -73,13 +73,13 @@ nfs4_file_open(struct inode *inode, struct file *filp)
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                switch (err) {
-               case -EPERM:
-               case -EACCES:
-               case -EDQUOT:
-               case -ENOSPC:
-               case -EROFS:
-                       goto out_put_ctx;
                default:
+                       goto out_put_ctx;
+               case -ENOENT:
+               case -ESTALE:
+               case -EISDIR:
+               case -ENOTDIR:
+               case -ELOOP:
                        goto out_drop;
                }
        }
index 39896afc6edf548aad9fb21cbcfce8b377074b7d..1406858bae6c95187c1190d3bb3b64bc5f317c58 100644 (file)
@@ -1683,6 +1683,14 @@ static void nfs_state_set_open_stateid(struct nfs4_state *state,
        write_sequnlock(&state->seqlock);
 }
 
+static void nfs_state_clear_open_state_flags(struct nfs4_state *state)
+{
+       clear_bit(NFS_O_RDWR_STATE, &state->flags);
+       clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+       clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+       clear_bit(NFS_OPEN_STATE, &state->flags);
+}
+
 static void nfs_state_set_delegation(struct nfs4_state *state,
                const nfs4_stateid *deleg_stateid,
                fmode_t fmode)
@@ -1907,8 +1915,9 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
        if (data->o_res.delegation_type != 0)
                nfs4_opendata_check_deleg(data, state);
 update:
-       update_open_stateid(state, &data->o_res.stateid, NULL,
-                           data->o_arg.fmode);
+       if (!update_open_stateid(state, &data->o_res.stateid,
+                               NULL, data->o_arg.fmode))
+               return ERR_PTR(-EAGAIN);
        refcount_inc(&state->count);
 
        return state;
@@ -1973,8 +1982,11 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
 
        if (data->o_res.delegation_type != 0)
                nfs4_opendata_check_deleg(data, state);
-       update_open_stateid(state, &data->o_res.stateid, NULL,
-                       data->o_arg.fmode);
+       if (!update_open_stateid(state, &data->o_res.stateid,
+                               NULL, data->o_arg.fmode)) {
+               nfs4_put_open_state(state);
+               state = ERR_PTR(-EAGAIN);
+       }
 out:
        nfs_release_seqid(data->o_arg.seqid);
        return state;
@@ -2074,13 +2086,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
 {
        int ret;
 
-       /* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */
-       clear_bit(NFS_O_RDWR_STATE, &state->flags);
-       clear_bit(NFS_O_WRONLY_STATE, &state->flags);
-       clear_bit(NFS_O_RDONLY_STATE, &state->flags);
        /* memory barrier prior to reading state->n_* */
-       clear_bit(NFS_DELEGATED_STATE, &state->flags);
-       clear_bit(NFS_OPEN_STATE, &state->flags);
        smp_rmb();
        ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
        if (ret != 0)
@@ -2156,6 +2162,8 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
        ctx = nfs4_state_find_open_context(state);
        if (IS_ERR(ctx))
                return -EAGAIN;
+       clear_bit(NFS_DELEGATED_STATE, &state->flags);
+       nfs_state_clear_open_state_flags(state);
        ret = nfs4_do_open_reclaim(ctx, state);
        put_nfs_open_context(ctx);
        return ret;
@@ -2171,18 +2179,17 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
                case -ENOENT:
                case -EAGAIN:
                case -ESTALE:
+               case -ETIMEDOUT:
                        break;
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
                case -NFS4ERR_BAD_HIGH_SLOT:
                case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
                case -NFS4ERR_DEADSESSION:
-                       set_bit(NFS_DELEGATED_STATE, &state->flags);
                        nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
                        return -EAGAIN;
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_STALE_STATEID:
-                       set_bit(NFS_DELEGATED_STATE, &state->flags);
                        /* Don't recall a delegation if it was lost */
                        nfs4_schedule_lease_recovery(server->nfs_client);
                        return -EAGAIN;
@@ -2203,7 +2210,6 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
                        return -EAGAIN;
                case -NFS4ERR_DELAY:
                case -NFS4ERR_GRACE:
-                       set_bit(NFS_DELEGATED_STATE, &state->flags);
                        ssleep(1);
                        return -EAGAIN;
                case -ENOMEM:
@@ -2219,8 +2225,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
 }
 
 int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
-               struct nfs4_state *state, const nfs4_stateid *stateid,
-               fmode_t type)
+               struct nfs4_state *state, const nfs4_stateid *stateid)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_opendata *opendata;
@@ -2231,20 +2236,23 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
        if (IS_ERR(opendata))
                return PTR_ERR(opendata);
        nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
-       nfs_state_clear_delegation(state);
-       switch (type & (FMODE_READ|FMODE_WRITE)) {
-       case FMODE_READ|FMODE_WRITE:
-       case FMODE_WRITE:
+       if (!test_bit(NFS_O_RDWR_STATE, &state->flags)) {
                err = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
                if (err)
-                       break;
+                       goto out;
+       }
+       if (!test_bit(NFS_O_WRONLY_STATE, &state->flags)) {
                err = nfs4_open_recover_helper(opendata, FMODE_WRITE);
                if (err)
-                       break;
-               /* Fall through */
-       case FMODE_READ:
+                       goto out;
+       }
+       if (!test_bit(NFS_O_RDONLY_STATE, &state->flags)) {
                err = nfs4_open_recover_helper(opendata, FMODE_READ);
+               if (err)
+                       goto out;
        }
+       nfs_state_clear_delegation(state);
+out:
        nfs4_opendata_put(opendata);
        return nfs4_handle_delegation_recall_error(server, state, stateid, NULL, err);
 }
@@ -2492,6 +2500,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data,
        if (!ctx) {
                nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 1);
                data->is_recover = true;
+               task_setup_data.flags |= RPC_TASK_TIMEOUT;
        } else {
                nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 0);
                pnfs_lgopen_prepare(data, ctx);
@@ -2698,6 +2707,7 @@ static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
 {
        /* NFSv4.0 doesn't allow for delegation recovery on open expire */
        nfs40_clear_delegation_stateid(state);
+       nfs_state_clear_open_state_flags(state);
        return nfs4_open_expired(sp, state);
 }
 
@@ -2740,13 +2750,13 @@ out_free:
        return -NFS4ERR_EXPIRED;
 }
 
-static void nfs41_check_delegation_stateid(struct nfs4_state *state)
+static int nfs41_check_delegation_stateid(struct nfs4_state *state)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        nfs4_stateid stateid;
        struct nfs_delegation *delegation;
        const struct cred *cred = NULL;
-       int status;
+       int status, ret = NFS_OK;
 
        /* Get the delegation credential for use by test/free_stateid */
        rcu_read_lock();
@@ -2754,20 +2764,15 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
        if (delegation == NULL) {
                rcu_read_unlock();
                nfs_state_clear_delegation(state);
-               return;
+               return NFS_OK;
        }
 
        nfs4_stateid_copy(&stateid, &delegation->stateid);
-       if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
-               rcu_read_unlock();
-               nfs_state_clear_delegation(state);
-               return;
-       }
 
        if (!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED,
                                &delegation->flags)) {
                rcu_read_unlock();
-               return;
+               return NFS_OK;
        }
 
        if (delegation->cred)
@@ -2777,9 +2782,24 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
        trace_nfs4_test_delegation_stateid(state, NULL, status);
        if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
                nfs_finish_clear_delegation_stateid(state, &stateid);
+       else
+               ret = status;
 
-       if (delegation->cred)
-               put_cred(cred);
+       put_cred(cred);
+       return ret;
+}
+
+static void nfs41_delegation_recover_stateid(struct nfs4_state *state)
+{
+       nfs4_stateid tmp;
+
+       if (test_bit(NFS_DELEGATED_STATE, &state->flags) &&
+           nfs4_copy_delegation_stateid(state->inode, state->state,
+                               &tmp, NULL) &&
+           nfs4_stateid_match_other(&state->stateid, &tmp))
+               nfs_state_set_delegation(state, &tmp, state->state);
+       else
+               nfs_state_clear_delegation(state);
 }
 
 /**
@@ -2849,21 +2869,12 @@ static int nfs41_check_open_stateid(struct nfs4_state *state)
        const struct cred *cred = state->owner->so_cred;
        int status;
 
-       if (test_bit(NFS_OPEN_STATE, &state->flags) == 0) {
-               if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)  {
-                       if (nfs4_have_delegation(state->inode, state->state))
-                               return NFS_OK;
-                       return -NFS4ERR_OPENMODE;
-               }
+       if (test_bit(NFS_OPEN_STATE, &state->flags) == 0)
                return -NFS4ERR_BAD_STATEID;
-       }
        status = nfs41_test_and_free_expired_stateid(server, stateid, cred);
        trace_nfs4_test_open_stateid(state, NULL, status);
        if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID) {
-               clear_bit(NFS_O_RDONLY_STATE, &state->flags);
-               clear_bit(NFS_O_WRONLY_STATE, &state->flags);
-               clear_bit(NFS_O_RDWR_STATE, &state->flags);
-               clear_bit(NFS_OPEN_STATE, &state->flags);
+               nfs_state_clear_open_state_flags(state);
                stateid->type = NFS4_INVALID_STATEID_TYPE;
                return status;
        }
@@ -2876,7 +2887,11 @@ static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
 {
        int status;
 
-       nfs41_check_delegation_stateid(state);
+       status = nfs41_check_delegation_stateid(state);
+       if (status != NFS_OK)
+               return status;
+       nfs41_delegation_recover_stateid(state);
+
        status = nfs41_check_expired_locks(state);
        if (status != NFS_OK)
                return status;
@@ -3201,7 +3216,7 @@ static int _nfs4_do_setattr(struct inode *inode,
 
        if (nfs4_copy_delegation_stateid(inode, FMODE_WRITE, &arg->stateid, &delegation_cred)) {
                /* Use that stateid */
-       } else if (ctx != NULL) {
+       } else if (ctx != NULL && ctx->state) {
                struct nfs_lock_context *l_ctx;
                if (!nfs4_valid_open_stateid(ctx->state))
                        return -EBADF;
index 9afd051a487605f8fe043ded2b4e0e25dcfd51bb..cad4e064b328747e29fdc20578c53f28bf438607 100644 (file)
@@ -624,24 +624,39 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
 /**
  * nfs4_purge_state_owners - Release all cached state owners
  * @server: nfs_server with cached state owners to release
+ * @head: resulting list of state owners
  *
  * Called at umount time.  Remaining state owners will be on
  * the LRU with ref count of zero.
+ * Note that the state owners are not freed, but are added
+ * to the list @head, which can later be used as an argument
+ * to nfs4_free_state_owners.
  */
-void nfs4_purge_state_owners(struct nfs_server *server)
+void nfs4_purge_state_owners(struct nfs_server *server, struct list_head *head)
 {
        struct nfs_client *clp = server->nfs_client;
        struct nfs4_state_owner *sp, *tmp;
-       LIST_HEAD(doomed);
 
        spin_lock(&clp->cl_lock);
        list_for_each_entry_safe(sp, tmp, &server->state_owners_lru, so_lru) {
-               list_move(&sp->so_lru, &doomed);
+               list_move(&sp->so_lru, head);
                nfs4_remove_state_owner_locked(sp);
        }
        spin_unlock(&clp->cl_lock);
+}
 
-       list_for_each_entry_safe(sp, tmp, &doomed, so_lru) {
+/**
+ * nfs4_purge_state_owners - Release all cached state owners
+ * @head: resulting list of state owners
+ *
+ * Frees a list of state owners that was generated by
+ * nfs4_purge_state_owners
+ */
+void nfs4_free_state_owners(struct list_head *head)
+{
+       struct nfs4_state_owner *sp, *tmp;
+
+       list_for_each_entry_safe(sp, tmp, head, so_lru) {
                list_del(&sp->so_lru);
                nfs4_free_state_owner(sp);
        }
@@ -1463,7 +1478,7 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
                nfs4_schedule_state_manager(clp);
 }
 
-static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
+static void nfs4_state_mark_open_context_bad(struct nfs4_state *state, int err)
 {
        struct inode *inode = state->inode;
        struct nfs_inode *nfsi = NFS_I(inode);
@@ -1474,6 +1489,8 @@ static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
                if (ctx->state != state)
                        continue;
                set_bit(NFS_CONTEXT_BAD, &ctx->flags);
+               pr_warn("NFSv4: state recovery failed for open file %pd2, "
+                               "error = %d\n", ctx->dentry, err);
        }
        rcu_read_unlock();
 }
@@ -1481,7 +1498,7 @@ static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
 static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error)
 {
        set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags);
-       nfs4_state_mark_open_context_bad(state);
+       nfs4_state_mark_open_context_bad(state, error);
 }
 
 
@@ -1512,6 +1529,7 @@ restart:
                switch (status) {
                case 0:
                        break;
+               case -ETIMEDOUT:
                case -ESTALE:
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_STALE_STATEID:
@@ -1605,6 +1623,7 @@ static int __nfs4_reclaim_open_state(struct nfs4_state_owner *sp, struct nfs4_st
 static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs4_state_recovery_ops *ops)
 {
        struct nfs4_state *state;
+       unsigned int loop = 0;
        int status = 0;
 
        /* Note: we rely on the sp->so_states list being ordered 
@@ -1631,8 +1650,10 @@ restart:
 
                switch (status) {
                default:
-                       if (status >= 0)
+                       if (status >= 0) {
+                               loop = 0;
                                break;
+                       }
                        printk(KERN_ERR "NFS: %s: unhandled error %d\n", __func__, status);
                        /* Fall through */
                case -ENOENT:
@@ -1646,6 +1667,10 @@ restart:
                        break;
                case -EAGAIN:
                        ssleep(1);
+                       if (loop++ < 10) {
+                               set_bit(ops->state_flag_bit, &state->flags);
+                               break;
+                       }
                        /* Fall through */
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_STALE_STATEID:
@@ -1658,11 +1683,13 @@ restart:
                case -NFS4ERR_EXPIRED:
                case -NFS4ERR_NO_GRACE:
                        nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state);
+                       /* Fall through */
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
                case -NFS4ERR_BAD_HIGH_SLOT:
                case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+               case -ETIMEDOUT:
                        goto out_err;
                }
                nfs4_put_open_state(state);
@@ -1856,12 +1883,13 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
        struct nfs4_state_owner *sp;
        struct nfs_server *server;
        struct rb_node *pos;
+       LIST_HEAD(freeme);
        int status = 0;
 
 restart:
        rcu_read_lock();
        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
-               nfs4_purge_state_owners(server);
+               nfs4_purge_state_owners(server, &freeme);
                spin_lock(&clp->cl_lock);
                for (pos = rb_first(&server->state_owners);
                     pos != NULL;
@@ -1890,6 +1918,7 @@ restart:
                spin_unlock(&clp->cl_lock);
        }
        rcu_read_unlock();
+       nfs4_free_state_owners(&freeme);
        return 0;
 }
 
@@ -1945,7 +1974,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
                return -EPERM;
        case -EACCES:
        case -NFS4ERR_DELAY:
-       case -ETIMEDOUT:
        case -EAGAIN:
                ssleep(1);
                break;
@@ -2574,7 +2602,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
                }
 
                /* Now recover expired state... */
-               if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
+               if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
                        section = "reclaim nograce";
                        status = nfs4_do_reclaim(clp,
                                clp->cl_mvops->nograce_recovery_ops);
@@ -2582,6 +2610,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
                                continue;
                        if (status < 0)
                                goto out_error;
+                       clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
                }
 
                nfs4_end_drain_session(clp);
index ed4e1b07447bde1280a41a98120689aafc258ab6..20b3717cd7ca83b8bb9efad78c9099b0d7a144a2 100644 (file)
@@ -590,7 +590,7 @@ static void nfs_pgio_rpcsetup(struct nfs_pgio_header *hdr,
        }
 
        hdr->res.fattr   = &hdr->fattr;
-       hdr->res.count   = count;
+       hdr->res.count   = 0;
        hdr->res.eof     = 0;
        hdr->res.verf    = &hdr->verf;
        nfs_fattr_init(&hdr->fattr);
@@ -1251,20 +1251,23 @@ static void nfs_pageio_complete_mirror(struct nfs_pageio_descriptor *desc,
 int nfs_pageio_resend(struct nfs_pageio_descriptor *desc,
                      struct nfs_pgio_header *hdr)
 {
-       LIST_HEAD(failed);
+       LIST_HEAD(pages);
 
        desc->pg_io_completion = hdr->io_completion;
        desc->pg_dreq = hdr->dreq;
-       while (!list_empty(&hdr->pages)) {
-               struct nfs_page *req = nfs_list_entry(hdr->pages.next);
+       list_splice_init(&hdr->pages, &pages);
+       while (!list_empty(&pages)) {
+               struct nfs_page *req = nfs_list_entry(pages.next);
 
                if (!nfs_pageio_add_request(desc, req))
-                       nfs_list_move_request(req, &failed);
+                       break;
        }
        nfs_pageio_complete(desc);
-       if (!list_empty(&failed)) {
-               list_move(&failed, &hdr->pages);
-               return desc->pg_error < 0 ? desc->pg_error : -EIO;
+       if (!list_empty(&pages)) {
+               int err = desc->pg_error < 0 ? desc->pg_error : -EIO;
+               hdr->completion_ops->error_cleanup(&pages, err);
+               nfs_set_pgio_error(hdr, err, hdr->io_start);
+               return err;
        }
        return 0;
 }
index 75bd5b552ba47acf7a680b22cbe3c1d3b569e050..4525d5acae3868c04440da5d51db0128ed2644bc 100644 (file)
@@ -1903,12 +1903,6 @@ lookup_again:
                goto out_unlock;
        }
 
-       if (!nfs4_valid_open_stateid(ctx->state)) {
-               trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
-                               PNFS_UPDATE_LAYOUT_INVALID_OPEN);
-               goto out_unlock;
-       }
-
        /*
         * Choose a stateid for the LAYOUTGET. If we don't have a layout
         * stateid, or it has been invalidated, then we must use the open
@@ -1939,6 +1933,7 @@ lookup_again:
                                        iomode == IOMODE_RW ? FMODE_WRITE : FMODE_READ,
                                        NULL, &stateid, NULL);
                if (status != 0) {
+                       lseg = ERR_PTR(status);
                        trace_pnfs_update_layout(ino, pos, count,
                                        iomode, lo, lseg,
                                        PNFS_UPDATE_LAYOUT_INVALID_OPEN);
index c0046c3489103c3ed9e4e8760d6db67b8bc1bca8..82af4809b869a63851ce8d49f4e0d982bdc6305c 100644 (file)
@@ -627,11 +627,16 @@ static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
                        /* Add this address as an alias */
                        rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
                                        rpc_clnt_test_and_add_xprt, NULL);
-               } else
-                       clp = get_v3_ds_connect(mds_srv,
-                                       (struct sockaddr *)&da->da_addr,
-                                       da->da_addrlen, IPPROTO_TCP,
-                                       timeo, retrans);
+                       continue;
+               }
+               clp = get_v3_ds_connect(mds_srv,
+                               (struct sockaddr *)&da->da_addr,
+                               da->da_addrlen, IPPROTO_TCP,
+                               timeo, retrans);
+               if (IS_ERR(clp))
+                       continue;
+               clp->cl_rpcclient->cl_softerr = 0;
+               clp->cl_rpcclient->cl_softrtry = 0;
        }
 
        if (IS_ERR(clp)) {
index 5552fa8b6e1289afe35a9b62595f1fe533cc1ecb..0f7288b94633b66b37718a6b2a8a8167961285d3 100644 (file)
@@ -594,7 +594,8 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
                /* Emulate the eof flag, which isn't normally needed in NFSv2
                 * as it is guaranteed to always return the file attributes
                 */
-               if (hdr->args.offset + hdr->res.count >= hdr->res.fattr->size)
+               if ((hdr->res.count == 0 && hdr->args.count > 0) ||
+                   hdr->args.offset + hdr->res.count >= hdr->res.fattr->size)
                        hdr->res.eof = 1;
        }
        return 0;
@@ -615,8 +616,10 @@ static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task,
 
 static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
 {
-       if (task->tk_status >= 0)
+       if (task->tk_status >= 0) {
+               hdr->res.count = hdr->args.count;
                nfs_writeback_update_inode(hdr);
+       }
        return 0;
 }
 
index c19841c82b6a3213203d1e964e5fcd85e8c96e1a..cfe0b586eadd4d0ed5bae36a00bfabf85ea90fe9 100644 (file)
@@ -91,19 +91,25 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
 }
 EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
 
-static void nfs_readpage_release(struct nfs_page *req)
+static void nfs_readpage_release(struct nfs_page *req, int error)
 {
        struct inode *inode = d_inode(nfs_req_openctx(req)->dentry);
+       struct page *page = req->wb_page;
 
        dprintk("NFS: read done (%s/%llu %d@%lld)\n", inode->i_sb->s_id,
                (unsigned long long)NFS_FILEID(inode), req->wb_bytes,
                (long long)req_offset(req));
 
+       if (nfs_error_is_fatal_on_server(error) && error != -ETIMEDOUT)
+               SetPageError(page);
        if (nfs_page_group_sync_on_bit(req, PG_UNLOCKPAGE)) {
-               if (PageUptodate(req->wb_page))
-                       nfs_readpage_to_fscache(inode, req->wb_page, 0);
+               struct address_space *mapping = page_file_mapping(page);
 
-               unlock_page(req->wb_page);
+               if (PageUptodate(page))
+                       nfs_readpage_to_fscache(inode, page, 0);
+               else if (!PageError(page) && !PagePrivate(page))
+                       generic_error_remove_page(mapping, page);
+               unlock_page(page);
        }
        nfs_release_request(req);
 }
@@ -131,7 +137,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
                             &nfs_async_read_completion_ops);
        if (!nfs_pageio_add_request(&pgio, new)) {
                nfs_list_remove_request(new);
-               nfs_readpage_release(new);
+               nfs_readpage_release(new, pgio.pg_error);
        }
        nfs_pageio_complete(&pgio);
 
@@ -153,6 +159,7 @@ static void nfs_page_group_set_uptodate(struct nfs_page *req)
 static void nfs_read_completion(struct nfs_pgio_header *hdr)
 {
        unsigned long bytes = 0;
+       int error;
 
        if (test_bit(NFS_IOHDR_REDO, &hdr->flags))
                goto out;
@@ -179,14 +186,19 @@ static void nfs_read_completion(struct nfs_pgio_header *hdr)
                                zero_user_segment(page, start, end);
                        }
                }
+               error = 0;
                bytes += req->wb_bytes;
                if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
                        if (bytes <= hdr->good_bytes)
                                nfs_page_group_set_uptodate(req);
+                       else {
+                               error = hdr->error;
+                               xchg(&nfs_req_openctx(req)->error, error);
+                       }
                } else
                        nfs_page_group_set_uptodate(req);
                nfs_list_remove_request(req);
-               nfs_readpage_release(req);
+               nfs_readpage_release(req, error);
        }
 out:
        hdr->release(hdr);
@@ -213,7 +225,7 @@ nfs_async_read_error(struct list_head *head, int error)
        while (!list_empty(head)) {
                req = nfs_list_entry(head->next);
                nfs_list_remove_request(req);
-               nfs_readpage_release(req);
+               nfs_readpage_release(req, error);
        }
 }
 
@@ -337,8 +349,13 @@ int nfs_readpage(struct file *file, struct page *page)
                        goto out;
        }
 
+       xchg(&ctx->error, 0);
        error = nfs_readpage_async(ctx, inode, page);
-
+       if (!error) {
+               error = wait_on_page_locked_killable(page);
+               if (!PageUptodate(page) && !error)
+                       error = xchg(&ctx->error, 0);
+       }
 out:
        put_nfs_open_context(ctx);
        return error;
@@ -372,8 +389,8 @@ readpage_async_filler(void *data, struct page *page)
                zero_user_segment(page, len, PAGE_SIZE);
        if (!nfs_pageio_add_request(desc->pgio, new)) {
                nfs_list_remove_request(new);
-               nfs_readpage_release(new);
                error = desc->pgio->pg_error;
+               nfs_readpage_release(new, error);
                goto out;
        }
        return 0;
index 628631e2e34fe630f6e24a814f43551d93484135..703f595dce90c1bfb8dfad1ca589221cc7f6f0b5 100644 (file)
@@ -2260,6 +2260,7 @@ nfs_compare_remount_data(struct nfs_server *nfss,
            data->acdirmin != nfss->acdirmin / HZ ||
            data->acdirmax != nfss->acdirmax / HZ ||
            data->timeo != (10U * nfss->client->cl_timeout->to_initval / HZ) ||
+           (data->options & NFS_OPTION_FSCACHE) != (nfss->options & NFS_OPTION_FSCACHE) ||
            data->nfs_server.port != nfss->port ||
            data->nfs_server.addrlen != nfss->nfs_client->cl_addrlen ||
            !rpc_cmp_addr((struct sockaddr *)&data->nfs_server.address,
index 92d9cadc61027c642bcab5755be7c5d221e7b0b1..85ca49549b39bdf5b9bea4e65dbb52d15945231b 100644 (file)
@@ -57,6 +57,7 @@ static const struct rpc_call_ops nfs_commit_ops;
 static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
 static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
 static const struct nfs_rw_ops nfs_rw_write_ops;
+static void nfs_inode_remove_request(struct nfs_page *req);
 static void nfs_clear_request_commit(struct nfs_page *req);
 static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
                                      struct inode *inode);
@@ -591,23 +592,13 @@ release_request:
 
 static void nfs_write_error(struct nfs_page *req, int error)
 {
+       nfs_set_pageerror(page_file_mapping(req->wb_page));
        nfs_mapping_set_error(req->wb_page, error);
+       nfs_inode_remove_request(req);
        nfs_end_page_writeback(req);
        nfs_release_request(req);
 }
 
-static bool
-nfs_error_is_fatal_on_server(int err)
-{
-       switch (err) {
-       case 0:
-       case -ERESTARTSYS:
-       case -EINTR:
-               return false;
-       }
-       return nfs_error_is_fatal(err);
-}
-
 /*
  * Find an associated nfs write request, and prepare to flush it out
  * May return an error if the user signalled nfs_wait_on_request().
@@ -615,7 +606,6 @@ nfs_error_is_fatal_on_server(int err)
 static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
                                struct page *page)
 {
-       struct address_space *mapping;
        struct nfs_page *req;
        int ret = 0;
 
@@ -630,12 +620,11 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
 
        /* If there is a fatal error that covers this write, just exit */
-       ret = 0;
-       mapping = page_file_mapping(page);
-       if (test_bit(AS_ENOSPC, &mapping->flags) ||
-           test_bit(AS_EIO, &mapping->flags))
+       ret = pgio->pg_error;
+       if (nfs_error_is_fatal_on_server(ret))
                goto out_launder;
 
+       ret = 0;
        if (!nfs_pageio_add_request(pgio, req)) {
                ret = pgio->pg_error;
                /*
@@ -647,6 +636,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
                } else
                        ret = -EAGAIN;
                nfs_redirty_request(req);
+               pgio->pg_error = 0;
        } else
                nfs_add_stats(page_file_mapping(page)->host,
                                NFSIOS_WRITEPAGES, 1);
@@ -666,7 +656,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc,
        ret = nfs_page_async_flush(pgio, page);
        if (ret == -EAGAIN) {
                redirty_page_for_writepage(wbc, page);
-               ret = 0;
+               ret = AOP_WRITEPAGE_ACTIVATE;
        }
        return ret;
 }
@@ -685,10 +675,11 @@ static int nfs_writepage_locked(struct page *page,
        nfs_pageio_init_write(&pgio, inode, 0,
                                false, &nfs_async_write_completion_ops);
        err = nfs_do_writepage(page, wbc, &pgio);
+       pgio.pg_error = 0;
        nfs_pageio_complete(&pgio);
        if (err < 0)
                return err;
-       if (pgio.pg_error < 0)
+       if (nfs_error_is_fatal(pgio.pg_error))
                return pgio.pg_error;
        return 0;
 }
@@ -698,7 +689,8 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
        int ret;
 
        ret = nfs_writepage_locked(page, wbc);
-       unlock_page(page);
+       if (ret != AOP_WRITEPAGE_ACTIVATE)
+               unlock_page(page);
        return ret;
 }
 
@@ -707,7 +699,8 @@ static int nfs_writepages_callback(struct page *page, struct writeback_control *
        int ret;
 
        ret = nfs_do_writepage(page, wbc, data);
-       unlock_page(page);
+       if (ret != AOP_WRITEPAGE_ACTIVATE)
+               unlock_page(page);
        return ret;
 }
 
@@ -733,13 +726,14 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
                                &nfs_async_write_completion_ops);
        pgio.pg_io_completion = ioc;
        err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio);
+       pgio.pg_error = 0;
        nfs_pageio_complete(&pgio);
        nfs_io_completion_put(ioc);
 
        if (err < 0)
                goto out_err;
        err = pgio.pg_error;
-       if (err < 0)
+       if (nfs_error_is_fatal(err))
                goto out_err;
        return 0;
 out_err:
index 26ad75ae2be042d3372f3bea221a3af0787a4722..96352ab7bd8100af89f2fadfa50825e31221dd7b 100644 (file)
@@ -571,7 +571,7 @@ nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data)
  */
 static int nfsd_reply_cache_stats_show(struct seq_file *m, void *v)
 {
-       struct nfsd_net *nn = v;
+       struct nfsd_net *nn = m->private;
 
        seq_printf(m, "max entries:           %u\n", nn->max_drc_entries);
        seq_printf(m, "num entries:           %u\n",
index 13c548733860cca6414b23bc30caea2d64c69b02..3cf4f6aa48d605499b9b8b766084a50661e7d3a8 100644 (file)
@@ -1171,13 +1171,17 @@ static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode)
        return inode;
 }
 
-static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, struct nfsdfs_client *ncl)
 {
        struct inode *inode;
 
        inode = nfsd_get_inode(dir->i_sb, mode);
        if (!inode)
                return -ENOMEM;
+       if (ncl) {
+               inode->i_private = ncl;
+               kref_get(&ncl->cl_ref);
+       }
        d_add(dentry, inode);
        inc_nlink(dir);
        fsnotify_mkdir(dir, dentry);
@@ -1194,17 +1198,14 @@ static struct dentry *nfsd_mkdir(struct dentry *parent, struct nfsdfs_client *nc
        dentry = d_alloc_name(parent, name);
        if (!dentry)
                goto out_err;
-       ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600);
+       ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600, ncl);
        if (ret)
                goto out_err;
-       if (ncl) {
-               d_inode(dentry)->i_private = ncl;
-               kref_get(&ncl->cl_ref);
-       }
 out:
        inode_unlock(dir);
        return dentry;
 out_err:
+       dput(dentry);
        dentry = ERR_PTR(ret);
        goto out;
 }
@@ -1214,11 +1215,9 @@ static void clear_ncl(struct inode *inode)
        struct nfsdfs_client *ncl = inode->i_private;
 
        inode->i_private = NULL;
-       synchronize_rcu();
        kref_put(&ncl->cl_ref, ncl->cl_release);
 }
 
-
 static struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode)
 {
        struct nfsdfs_client *nc = inode->i_private;
@@ -1232,9 +1231,9 @@ struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
 {
        struct nfsdfs_client *nc;
 
-       rcu_read_lock();
+       inode_lock_shared(inode);
        nc = __get_nfsdfs_client(inode);
-       rcu_read_unlock();
+       inode_unlock_shared(inode);
        return nc;
 }
 /* from __rpc_unlink */
index 385f3aaa244809b0d442d746fb4e76bd391d7bb2..90c830e3758e2dea9af508efed08b48a8509553f 100644 (file)
@@ -3825,7 +3825,6 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
        u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
        int low_bucket = 0, bucket, high_bucket;
        struct ocfs2_xattr_bucket *search;
-       u32 last_hash;
        u64 blkno, lower_blkno = 0;
 
        search = ocfs2_xattr_bucket_new(inode);
@@ -3869,8 +3868,6 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
                if (xh->xh_count)
                        xe = &xh->xh_entries[le16_to_cpu(xh->xh_count) - 1];
 
-               last_hash = le32_to_cpu(xe->xe_name_hash);
-
                /* record lower_blkno which may be the insert place. */
                lower_blkno = blkno;
 
index b5b80469b93d05ce034cd85cf95da35dc37e13c2..a59abe3c669ae13ac7f3fa68bc0fb5f54a781ee4 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -374,6 +374,25 @@ long do_faccessat(int dfd, const char __user *filename, int mode)
                                override_cred->cap_permitted;
        }
 
+       /*
+        * The new set of credentials can *only* be used in
+        * task-synchronous circumstances, and does not need
+        * RCU freeing, unless somebody then takes a separate
+        * reference to it.
+        *
+        * NOTE! This is _only_ true because this credential
+        * is used purely for override_creds() that installs
+        * it as the subjective cred. Other threads will be
+        * accessing ->real_cred, not the subjective cred.
+        *
+        * If somebody _does_ make a copy of this (using the
+        * 'get_current_cred()' function), that will clear the
+        * non_rcu field, because now that other user may be
+        * expecting RCU freeing. But normal thread-synchronous
+        * cred accesses will keep things non-RCY.
+        */
+       override_cred->non_rcu = 1;
+
        old_cred = override_creds(override_cred);
 retry:
        res = user_path_at(dfd, filename, lookup_flags, &path);
index 1f5088dec566b71a37f697edd7419b7813edbb4c..5bbf587f5bc135485d21331039a8085f1e0500f7 100644 (file)
@@ -1811,10 +1811,7 @@ static int generic_remap_check_len(struct inode *inode_in,
        return (remap_flags & REMAP_FILE_DEDUP) ? -EBADE : -EINVAL;
 }
 
-/*
- * Read a page's worth of file data into the page cache.  Return the page
- * locked.
- */
+/* Read a page's worth of file data into the page cache. */
 static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset)
 {
        struct page *page;
@@ -1826,10 +1823,32 @@ static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset)
                put_page(page);
                return ERR_PTR(-EIO);
        }
-       lock_page(page);
        return page;
 }
 
+/*
+ * Lock two pages, ensuring that we lock in offset order if the pages are from
+ * the same file.
+ */
+static void vfs_lock_two_pages(struct page *page1, struct page *page2)
+{
+       /* Always lock in order of increasing index. */
+       if (page1->index > page2->index)
+               swap(page1, page2);
+
+       lock_page(page1);
+       if (page1 != page2)
+               lock_page(page2);
+}
+
+/* Unlock two pages, being careful not to unlock the same page twice. */
+static void vfs_unlock_two_pages(struct page *page1, struct page *page2)
+{
+       unlock_page(page1);
+       if (page1 != page2)
+               unlock_page(page2);
+}
+
 /*
  * Compare extents of two files to see if they are the same.
  * Caller must have locked both inodes to prevent write races.
@@ -1867,10 +1886,24 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
                dest_page = vfs_dedupe_get_page(dest, destoff);
                if (IS_ERR(dest_page)) {
                        error = PTR_ERR(dest_page);
-                       unlock_page(src_page);
                        put_page(src_page);
                        goto out_error;
                }
+
+               vfs_lock_two_pages(src_page, dest_page);
+
+               /*
+                * Now that we've locked both pages, make sure they're still
+                * mapped to the file data we're interested in.  If not,
+                * someone is invalidating pages on us and we lose.
+                */
+               if (!PageUptodate(src_page) || !PageUptodate(dest_page) ||
+                   src_page->mapping != src->i_mapping ||
+                   dest_page->mapping != dest->i_mapping) {
+                       same = false;
+                       goto unlock;
+               }
+
                src_addr = kmap_atomic(src_page);
                dest_addr = kmap_atomic(dest_page);
 
@@ -1882,8 +1915,8 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
 
                kunmap_atomic(dest_addr);
                kunmap_atomic(src_addr);
-               unlock_page(dest_page);
-               unlock_page(src_page);
+unlock:
+               vfs_unlock_two_pages(src_page, dest_page);
                put_page(dest_page);
                put_page(src_page);
 
index 04f09689cd6d5bfb23b9757b7cb01fd1af180924..1600034a929bb1c89df6ce7134ecaad994bd1491 100644 (file)
@@ -119,6 +119,7 @@ static int traverse(struct seq_file *m, loff_t offset)
                }
                if (seq_has_overflowed(m))
                        goto Eoverflow;
+               p = m->op->next(m, p, &m->index);
                if (pos + m->count > offset) {
                        m->from = offset - pos;
                        m->count -= m->from;
@@ -126,7 +127,6 @@ static int traverse(struct seq_file *m, loff_t offset)
                }
                pos += m->count;
                m->count = 0;
-               p = m->op->next(m, p, &m->index);
                if (pos == offset)
                        break;
        }
index 113c58f194255e3fc57166467018d5eab565548a..5960578a40760a26bc0ecd88e28177ce748f4380 100644 (file)
@@ -478,13 +478,10 @@ EXPORT_SYMBOL(generic_shutdown_super);
 
 bool mount_capable(struct fs_context *fc)
 {
-       struct user_namespace *user_ns = fc->global ? &init_user_ns
-                                                   : fc->user_ns;
-
        if (!(fc->fs_type->fs_flags & FS_USERNS_MOUNT))
                return capable(CAP_SYS_ADMIN);
        else
-               return ns_capable(user_ns, CAP_SYS_ADMIN);
+               return ns_capable(fc->user_ns, CAP_SYS_ADMIN);
 }
 
 /**
index 80d7301ab76d0c74a8b90cc9bee1c23aa9fbe24b..c0b84e960b20c138b1e3fe1cfe77c13f32a9428e 100644 (file)
@@ -51,7 +51,7 @@
 static void shrink_liability(struct ubifs_info *c, int nr_to_write)
 {
        down_read(&c->vfs_sb->s_umount);
-       writeback_inodes_sb(c->vfs_sb, WB_REASON_FS_FREE_SPACE);
+       writeback_inodes_sb_nr(c->vfs_sb, nr_to_write, WB_REASON_FS_FREE_SPACE);
        up_read(&c->vfs_sb->s_umount);
 }
 
index b52624e28fa1198b938f232322526861114c7be4..3b4b4114f208bfb6bdc1f94803e6d7b5b79bd372 100644 (file)
@@ -129,7 +129,6 @@ static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o)
 static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
 {
        if (orph->del) {
-               spin_unlock(&c->orphan_lock);
                dbg_gen("deleted twice ino %lu", orph->inum);
                return;
        }
@@ -138,7 +137,6 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
                orph->del = 1;
                orph->dnext = c->orph_dnext;
                c->orph_dnext = orph;
-               spin_unlock(&c->orphan_lock);
                dbg_gen("delete later ino %lu", orph->inum);
                return;
        }
index 2c0803b0ac3aa21190ca84ca65f59f2e5de1069b..8c1d571334bc82ff46e3d5da2e934df523c4a6c7 100644 (file)
@@ -609,6 +609,10 @@ static int init_constants_early(struct ubifs_info *c)
        c->max_bu_buf_len = UBIFS_MAX_BULK_READ * UBIFS_MAX_DATA_NODE_SZ;
        if (c->max_bu_buf_len > c->leb_size)
                c->max_bu_buf_len = c->leb_size;
+
+       /* Log is ready, preserve one LEB for commits. */
+       c->min_log_bytes = c->leb_size;
+
        return 0;
 }
 
index ccbdbd62f0d8ecf16a19f2f191d5809e317da9d5..fe6d804a38dc2d64b9397a6bf68e53b4c938f656 100644 (file)
@@ -880,6 +880,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
        /* len == 0 means wake all */
        struct userfaultfd_wake_range range = { .len = 0, };
        unsigned long new_flags;
+       bool still_valid;
 
        WRITE_ONCE(ctx->released, true);
 
@@ -895,8 +896,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
         * taking the mmap_sem for writing.
         */
        down_write(&mm->mmap_sem);
-       if (!mmget_still_valid(mm))
-               goto skip_mm;
+       still_valid = mmget_still_valid(mm);
        prev = NULL;
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                cond_resched();
@@ -907,19 +907,20 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
                        continue;
                }
                new_flags = vma->vm_flags & ~(VM_UFFD_MISSING | VM_UFFD_WP);
-               prev = vma_merge(mm, prev, vma->vm_start, vma->vm_end,
-                                new_flags, vma->anon_vma,
-                                vma->vm_file, vma->vm_pgoff,
-                                vma_policy(vma),
-                                NULL_VM_UFFD_CTX);
-               if (prev)
-                       vma = prev;
-               else
-                       prev = vma;
+               if (still_valid) {
+                       prev = vma_merge(mm, prev, vma->vm_start, vma->vm_end,
+                                        new_flags, vma->anon_vma,
+                                        vma->vm_file, vma->vm_pgoff,
+                                        vma_policy(vma),
+                                        NULL_VM_UFFD_CTX);
+                       if (prev)
+                               vma = prev;
+                       else
+                               prev = vma;
+               }
                vma->vm_flags = new_flags;
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
        }
-skip_mm:
        up_write(&mm->mmap_sem);
        mmput(mm);
 wakeup:
index baf0b72c0a37deddd4936556a985cb020bf5ff4d..07aad70f39319f46b670dfef948f3b49d16f786a 100644 (file)
@@ -3835,15 +3835,28 @@ xfs_bmapi_read(
        XFS_STATS_INC(mp, xs_blk_mapr);
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
+       if (!ifp) {
+               /* No CoW fork?  Return a hole. */
+               if (whichfork == XFS_COW_FORK) {
+                       mval->br_startoff = bno;
+                       mval->br_startblock = HOLESTARTBLOCK;
+                       mval->br_blockcount = len;
+                       mval->br_state = XFS_EXT_NORM;
+                       *nmap = 1;
+                       return 0;
+               }
 
-       /* No CoW fork?  Return a hole. */
-       if (whichfork == XFS_COW_FORK && !ifp) {
-               mval->br_startoff = bno;
-               mval->br_startblock = HOLESTARTBLOCK;
-               mval->br_blockcount = len;
-               mval->br_state = XFS_EXT_NORM;
-               *nmap = 1;
-               return 0;
+               /*
+                * A missing attr ifork implies that the inode says we're in
+                * extents or btree format but failed to pass the inode fork
+                * verifier while trying to load it.  Treat that as a file
+                * corruption too.
+                */
+#ifdef DEBUG
+               xfs_alert(mp, "%s: inode %llu missing fork %d",
+                               __func__, ip->i_ino, whichfork);
+#endif /* DEBUG */
+               return -EFSCORRUPTED;
        }
 
        if (!(ifp->if_flags & XFS_IFEXTENTS)) {
index d1c77fd0815da89cca4882c7bd4c19efac357745..0bf56e94bfe93cb00a87a92e3112346ca21ec7ca 100644 (file)
@@ -487,10 +487,8 @@ xfs_da3_split(
        ASSERT(state->path.active == 0);
        oldblk = &state->path.blk[0];
        error = xfs_da3_root_split(state, oldblk, addblk);
-       if (error) {
-               addblk->bp = NULL;
-               return error;   /* GROT: dir is inconsistent */
-       }
+       if (error)
+               goto out;
 
        /*
         * Update pointers to the node which used to be block 0 and just got
@@ -505,7 +503,10 @@ xfs_da3_split(
         */
        node = oldblk->bp->b_addr;
        if (node->hdr.info.forw) {
-               ASSERT(be32_to_cpu(node->hdr.info.forw) == addblk->blkno);
+               if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) {
+                       error = -EFSCORRUPTED;
+                       goto out;
+               }
                node = addblk->bp->b_addr;
                node->hdr.info.back = cpu_to_be32(oldblk->blkno);
                xfs_trans_log_buf(state->args->trans, addblk->bp,
@@ -514,15 +515,19 @@ xfs_da3_split(
        }
        node = oldblk->bp->b_addr;
        if (node->hdr.info.back) {
-               ASSERT(be32_to_cpu(node->hdr.info.back) == addblk->blkno);
+               if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) {
+                       error = -EFSCORRUPTED;
+                       goto out;
+               }
                node = addblk->bp->b_addr;
                node->hdr.info.forw = cpu_to_be32(oldblk->blkno);
                xfs_trans_log_buf(state->args->trans, addblk->bp,
                                  XFS_DA_LOGRANGE(node, &node->hdr.info,
                                  sizeof(node->hdr.info)));
        }
+out:
        addblk->bp = NULL;
-       return 0;
+       return error;
 }
 
 /*
index afcc6642690a8d85aebab8849321b01c50016b98..1fc44efc344df9ebfd22597b57447e3b77cfb836 100644 (file)
@@ -741,7 +741,8 @@ xfs_dir2_leafn_lookup_for_entry(
        ents = dp->d_ops->leaf_ents_p(leaf);
 
        xfs_dir3_leaf_check(dp, bp);
-       ASSERT(leafhdr.count > 0);
+       if (leafhdr.count <= 0)
+               return -EFSCORRUPTED;
 
        /*
         * Look up the hash value in the leaf entries.
index 94c4f1de1922f31ea5f9ffe395792fe3a918c531..77ff9f97bcda53747c0d79e4f82e9337d475fc2d 100644 (file)
@@ -278,7 +278,11 @@ xchk_da_btree_block_check_sibling(
        /* Compare upper level pointer to sibling pointer. */
        if (ds->state->altpath.blk[level].blkno != sibling)
                xchk_da_set_corrupt(ds, level);
-       xfs_trans_brelse(ds->dargs.trans, ds->state->altpath.blk[level].bp);
+       if (ds->state->altpath.blk[level].bp) {
+               xfs_trans_brelse(ds->dargs.trans,
+                               ds->state->altpath.blk[level].bp);
+               ds->state->altpath.blk[level].bp = NULL;
+       }
 out:
        return error;
 }
index 7fcf7569743f47a250f0bf2356f7c040b78cc59c..7bd7534f5051bb571fc1933df695d5405301c0b9 100644 (file)
@@ -547,63 +547,12 @@ xfs_file_compat_ioctl(
        struct inode            *inode = file_inode(filp);
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
-       void                    __user *arg = (void __user *)p;
+       void                    __user *arg = compat_ptr(p);
        int                     error;
 
        trace_xfs_file_compat_ioctl(ip);
 
        switch (cmd) {
-       /* No size or alignment issues on any arch */
-       case XFS_IOC_DIOINFO:
-       case XFS_IOC_FSGEOMETRY_V4:
-       case XFS_IOC_FSGEOMETRY:
-       case XFS_IOC_AG_GEOMETRY:
-       case XFS_IOC_FSGETXATTR:
-       case XFS_IOC_FSSETXATTR:
-       case XFS_IOC_FSGETXATTRA:
-       case XFS_IOC_FSSETDM:
-       case XFS_IOC_GETBMAP:
-       case XFS_IOC_GETBMAPA:
-       case XFS_IOC_GETBMAPX:
-       case XFS_IOC_FSCOUNTS:
-       case XFS_IOC_SET_RESBLKS:
-       case XFS_IOC_GET_RESBLKS:
-       case XFS_IOC_FSGROWFSLOG:
-       case XFS_IOC_GOINGDOWN:
-       case XFS_IOC_ERROR_INJECTION:
-       case XFS_IOC_ERROR_CLEARALL:
-       case FS_IOC_GETFSMAP:
-       case XFS_IOC_SCRUB_METADATA:
-       case XFS_IOC_BULKSTAT:
-       case XFS_IOC_INUMBERS:
-               return xfs_file_ioctl(filp, cmd, p);
-#if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
-       /*
-        * These are handled fine if no alignment issues.  To support x32
-        * which uses native 64-bit alignment we must emit these cases in
-        * addition to the ia-32 compat set below.
-        */
-       case XFS_IOC_ALLOCSP:
-       case XFS_IOC_FREESP:
-       case XFS_IOC_RESVSP:
-       case XFS_IOC_UNRESVSP:
-       case XFS_IOC_ALLOCSP64:
-       case XFS_IOC_FREESP64:
-       case XFS_IOC_RESVSP64:
-       case XFS_IOC_UNRESVSP64:
-       case XFS_IOC_FSGEOMETRY_V1:
-       case XFS_IOC_FSGROWFSDATA:
-       case XFS_IOC_FSGROWFSRT:
-       case XFS_IOC_ZERO_RANGE:
-#ifdef CONFIG_X86_X32
-       /*
-        * x32 special: this gets a different cmd number from the ia-32 compat
-        * case below; the associated data will match native 64-bit alignment.
-        */
-       case XFS_IOC_SWAPEXT:
-#endif
-               return xfs_file_ioctl(filp, cmd, p);
-#endif
 #if defined(BROKEN_X86_ALIGNMENT)
        case XFS_IOC_ALLOCSP_32:
        case XFS_IOC_FREESP_32:
@@ -705,6 +654,7 @@ xfs_file_compat_ioctl(
        case XFS_IOC_FSSETDM_BY_HANDLE_32:
                return xfs_compat_fssetdm_by_handle(filp, arg);
        default:
-               return -ENOIOCTLCMD;
+               /* try the native version */
+               return xfs_file_ioctl(filp, cmd, (unsigned long)arg);
        }
 }
index ff3c1fae53571e79d139e9117efc8ccc4ec751bd..fe285d123d69f1eb8c749ad145a02ea36c96904a 100644 (file)
@@ -793,6 +793,7 @@ xfs_setattr_nonsize(
 
 out_cancel:
        xfs_trans_cancel(tp);
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
 out_dqrele:
        xfs_qm_dqrele(udqp);
        xfs_qm_dqrele(gdqp);
index a8a06bb78ea8e3c942d3d6c45f25f5999ff0a6c3..f5c955d35be4342467815f45ce49b02a89813931 100644 (file)
@@ -272,6 +272,7 @@ xfs_bulkstat_to_bstat(
        struct xfs_bstat                *bs1,
        const struct xfs_bulkstat       *bstat)
 {
+       /* memset is needed here because of padding holes in the structure. */
        memset(bs1, 0, sizeof(struct xfs_bstat));
        bs1->bs_ino = bstat->bs_ino;
        bs1->bs_mode = bstat->bs_mode;
@@ -388,6 +389,8 @@ xfs_inumbers_to_inogrp(
        struct xfs_inogrp               *ig1,
        const struct xfs_inumbers       *ig)
 {
+       /* memset is needed here because of padding holes in the structure. */
+       memset(ig1, 0, sizeof(struct xfs_inogrp));
        ig1->xi_startino = ig->xi_startino;
        ig1->xi_alloccount = ig->xi_alloccount;
        ig1->xi_allocmask = ig->xi_allocmask;
index 00e9f5c388d366031fd8c5b713655a718c0a9287..7fc3c1ad36bcd0e490058c78f39e5883505da1c6 100644 (file)
@@ -429,10 +429,7 @@ xfs_log_reserve(
 
        ASSERT(*ticp == NULL);
        tic = xlog_ticket_alloc(log, unit_bytes, cnt, client, permanent,
-                               KM_SLEEP | KM_MAYFAIL);
-       if (!tic)
-               return -ENOMEM;
-
+                               KM_SLEEP);
        *ticp = tic;
 
        xlog_grant_push_ail(log, tic->t_cnt ? tic->t_unit_res * tic->t_cnt
index 0c954cad74493cf6fb9002b93101baeb7717e3f3..a339bd5fa260471428e27809808899c39ff949e0 100644 (file)
@@ -32,7 +32,7 @@ xfs_break_leased_layouts(
        struct xfs_inode        *ip = XFS_I(inode);
        int                     error;
 
-       while ((error = break_layout(inode, false) == -EWOULDBLOCK)) {
+       while ((error = break_layout(inode, false)) == -EWOULDBLOCK) {
                xfs_iunlock(ip, *iolock);
                *did_unlock = true;
                error = break_layout(inode, true);
index c4ec7afd1170a7550df8704b2bb71ae450c927f5..edbe37b7f636de145a0eeab9b837aee3120f3a77 100644 (file)
@@ -1190,11 +1190,11 @@ xfs_reflink_remap_blocks(
 }
 
 /*
- * Grab the exclusive iolock for a data copy from src to dest, making
- * sure to abide vfs locking order (lowest pointer value goes first) and
- * breaking the pnfs layout leases on dest before proceeding.  The loop
- * is needed because we cannot call the blocking break_layout() with the
- * src iolock held, and therefore have to back out both locks.
+ * Grab the exclusive iolock for a data copy from src to dest, making sure to
+ * abide vfs locking order (lowest pointer value goes first) and breaking the
+ * layout leases before proceeding.  The loop is needed because we cannot call
+ * the blocking break_layout() with the iolocks held, and therefore have to
+ * back out both locks.
  */
 static int
 xfs_iolock_two_inodes_and_break_layout(
@@ -1203,33 +1203,44 @@ xfs_iolock_two_inodes_and_break_layout(
 {
        int                     error;
 
-retry:
-       if (src < dest) {
-               inode_lock_shared(src);
-               inode_lock_nested(dest, I_MUTEX_NONDIR2);
-       } else {
-               /* src >= dest */
-               inode_lock(dest);
-       }
+       if (src > dest)
+               swap(src, dest);
 
-       error = break_layout(dest, false);
-       if (error == -EWOULDBLOCK) {
-               inode_unlock(dest);
-               if (src < dest)
-                       inode_unlock_shared(src);
+retry:
+       /* Wait to break both inodes' layouts before we start locking. */
+       error = break_layout(src, true);
+       if (error)
+               return error;
+       if (src != dest) {
                error = break_layout(dest, true);
                if (error)
                        return error;
-               goto retry;
        }
+
+       /* Lock one inode and make sure nobody got in and leased it. */
+       inode_lock(src);
+       error = break_layout(src, false);
        if (error) {
+               inode_unlock(src);
+               if (error == -EWOULDBLOCK)
+                       goto retry;
+               return error;
+       }
+
+       if (src == dest)
+               return 0;
+
+       /* Lock the other inode and make sure nobody got in and leased it. */
+       inode_lock_nested(dest, I_MUTEX_NONDIR2);
+       error = break_layout(dest, false);
+       if (error) {
+               inode_unlock(src);
                inode_unlock(dest);
-               if (src < dest)
-                       inode_unlock_shared(src);
+               if (error == -EWOULDBLOCK)
+                       goto retry;
                return error;
        }
-       if (src > dest)
-               inode_lock_shared_nested(src, I_MUTEX_NONDIR2);
+
        return 0;
 }
 
@@ -1247,10 +1258,10 @@ xfs_reflink_remap_unlock(
 
        xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
        if (!same_inode)
-               xfs_iunlock(src, XFS_MMAPLOCK_SHARED);
+               xfs_iunlock(src, XFS_MMAPLOCK_EXCL);
        inode_unlock(inode_out);
        if (!same_inode)
-               inode_unlock_shared(inode_in);
+               inode_unlock(inode_in);
 }
 
 /*
@@ -1325,7 +1336,7 @@ xfs_reflink_remap_prep(
        if (same_inode)
                xfs_ilock(src, XFS_MMAPLOCK_EXCL);
        else
-               xfs_lock_two_inodes(src, XFS_MMAPLOCK_SHARED, dest,
+               xfs_lock_two_inodes(src, XFS_MMAPLOCK_EXCL, dest,
                                XFS_MMAPLOCK_EXCL);
 
        /* Check file eligibility and prepare for block sharing. */
index bb6cb347018c07cda6a0cd90570938dd4ac5d2d1..f6947da70d715fc7fdd6d67fd7845ac0d1d4b23f 100644 (file)
 
 #define p4d_alloc(mm, pgd, address)    (pgd)
 #define p4d_offset(pgd, start)         (pgd)
-#define p4d_none(p4d)                  0
-#define p4d_bad(p4d)                   0
-#define p4d_present(p4d)               1
+
+#ifndef __ASSEMBLY__
+static inline int p4d_none(p4d_t p4d)
+{
+       return 0;
+}
+
+static inline int p4d_bad(p4d_t p4d)
+{
+       return 0;
+}
+
+static inline int p4d_present(p4d_t p4d)
+{
+       return 1;
+}
+#endif
+
 #define p4d_ERROR(p4d)                 do { } while (0)
 #define p4d_clear(p4d)                 pgd_clear(p4d)
 #define p4d_val(p4d)                   pgd_val(p4d)
index 8666fe7f35d77dc423ae24c19f2be8f63ba2144c..02970b11f71f47b5e2ef93853d24587af530e702 100644 (file)
@@ -118,26 +118,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 static inline int
 arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
 {
-       int oldval = 0, ret;
-
-       pagefault_disable();
-
-       switch (op) {
-       case FUTEX_OP_SET:
-       case FUTEX_OP_ADD:
-       case FUTEX_OP_OR:
-       case FUTEX_OP_ANDN:
-       case FUTEX_OP_XOR:
-       default:
-               ret = -ENOSYS;
-       }
-
-       pagefault_enable();
-
-       if (!ret)
-               *oval = oldval;
-
-       return ret;
+       return -ENOSYS;
 }
 
 static inline int
index c64bea7a52bebd5c7332203e1e3a78bfa69b84c3..e9f20b813a699a3fb7630fe76aba3d1ab60c892e 100644 (file)
@@ -7,24 +7,6 @@
 #include <linux/compiler.h>
 #include <linux/log2.h>
 
-/*
- * Runtime evaluation of get_order()
- */
-static inline __attribute_const__
-int __get_order(unsigned long size)
-{
-       int order;
-
-       size--;
-       size >>= PAGE_SHIFT;
-#if BITS_PER_LONG == 32
-       order = fls(size);
-#else
-       order = fls64(size);
-#endif
-       return order;
-}
-
 /**
  * get_order - Determine the allocation order of a memory size
  * @size: The size for which to get the order
@@ -43,19 +25,27 @@ int __get_order(unsigned long size)
  * to hold an object of the specified size.
  *
  * The result is undefined if the size is 0.
- *
- * This function may be used to initialise variables with compile time
- * evaluations of constants.
  */
-#define get_order(n)                                           \
-(                                                              \
-       __builtin_constant_p(n) ? (                             \
-               ((n) == 0UL) ? BITS_PER_LONG - PAGE_SHIFT :     \
-               (((n) < (1UL << PAGE_SHIFT)) ? 0 :              \
-                ilog2((n) - 1) - PAGE_SHIFT + 1)               \
-       ) :                                                     \
-       __get_order(n)                                          \
-)
+static inline __attribute_const__ int get_order(unsigned long size)
+{
+       if (__builtin_constant_p(size)) {
+               if (!size)
+                       return BITS_PER_LONG - PAGE_SHIFT;
+
+               if (size < (1UL << PAGE_SHIFT))
+                       return 0;
+
+               return ilog2((size) - 1) - PAGE_SHIFT + 1;
+       }
+
+       size--;
+       size >>= PAGE_SHIFT;
+#if BITS_PER_LONG == 32
+       return fls(size);
+#else
+       return fls64(size);
+#endif
+}
 
 #endif /* __ASSEMBLY__ */
 
index 72d51d1e9dd9ea33ea83b7c6fcdbdc0cc1f250ef..5cf2c5dd8b1e63d19a52f61fd8393133f73af25b 100644 (file)
@@ -149,6 +149,8 @@ struct drm_client_buffer {
 struct drm_client_buffer *
 drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
 void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
+void *drm_client_buffer_vmap(struct drm_client_buffer *buffer);
+void drm_client_buffer_vunmap(struct drm_client_buffer *buffer);
 
 int drm_client_modeset_create(struct drm_client_dev *client);
 void drm_client_modeset_free(struct drm_client_dev *client);
index 759d462d028bb7d32459c6e86e6e48564bb809a2..f57eea0481e0fd18a79d0c1178108619ae5e0a38 100644 (file)
@@ -852,6 +852,13 @@ struct drm_mode_config {
        /* dumb ioctl parameters */
        uint32_t preferred_depth, prefer_shadow;
 
+       /**
+        * @prefer_shadow_fbdev:
+        *
+        * Hint to framebuffer emulation to prefer shadow-fb rendering.
+        */
+       bool prefer_shadow_fbdev;
+
        /**
         * @quirk_addfb_prefer_xbgr_30bpp:
         *
index 16c769a7f979e387f58d65e094f9531213ad1f8b..6db030439e29c287ece08ab5353080fcfe0de39f 100644 (file)
@@ -34,6 +34,7 @@ struct kvm_pmu {
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
 u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
+void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);
 void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu);
 void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu);
 void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val);
@@ -71,6 +72,7 @@ static inline u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
 {
        return 0;
 }
+static inline void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) {}
index 46bbc949c20a0c8bfd89f24665b7b5c169e4d4ea..7a30524a80ee8793b446d745c225c5864f50cdc7 100644 (file)
@@ -350,6 +350,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
 void kvm_vgic_load(struct kvm_vcpu *vcpu);
 void kvm_vgic_put(struct kvm_vcpu *vcpu);
+void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu);
 
 #define irqchip_in_kernel(k)   (!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)    ((k)->arch.vgic.initialized)
index 689a582312887d05b1d81212454e02560e36c4de..12811091fd50bcd485d28c87d4e235890bb6ac92 100644 (file)
@@ -181,6 +181,7 @@ struct blkcg_policy {
 
 extern struct blkcg blkcg_root;
 extern struct cgroup_subsys_state * const blkcg_root_css;
+extern bool blkcg_debug_stats;
 
 struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg,
                                      struct request_queue *q, bool update_hint);
index 55cb455cfcb067f2ccdbdc84d6d2ba9c78deaaf8..a5dfbaf2470d7cbf31f8b339b469f0c85fbaea9d 100644 (file)
@@ -170,6 +170,8 @@ struct ccp_aes_engine {
        enum ccp_aes_mode mode;
        enum ccp_aes_action action;
 
+       u32 authsize;
+
        struct scatterlist *key;
        u32 key_len;            /* In bytes */
 
index 5e58bb29b1a36b55e86bf8951cd04eaf149853e5..11cdc7c60480f503aa510b5b54368ac66df45a86 100644 (file)
@@ -30,7 +30,8 @@ static inline struct ceph_buffer *ceph_buffer_get(struct ceph_buffer *b)
 
 static inline void ceph_buffer_put(struct ceph_buffer *b)
 {
-       kref_put(&b->kref, ceph_buffer_release);
+       if (b)
+               kref_put(&b->kref, ceph_buffer_release);
 }
 
 extern int ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end);
index 3c096c7a51dc6105bbc90abab34f01786e36beca..853a8f1813947c4e745e0bc4b5c05a9d2197a650 100644 (file)
@@ -359,6 +359,7 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
 /**
  * devm_clk_bulk_get_optional - managed get multiple optional consumer clocks
  * @dev: device for clock "consumer"
+ * @num_clks: the number of clk_bulk_data
  * @clks: pointer to the clk_bulk_data table of consumer
  *
  * Behaves the same as devm_clk_bulk_get() except where there is no clock
index f0fd5636fddbebd8a55d235dbd3cc8a41e398ae0..5e88e7e33abecd9ec88003b51fdd34ab611f6eb7 100644 (file)
@@ -24,7 +24,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
                        long ______r;                                   \
                        static struct ftrace_likely_data                \
                                __aligned(4)                            \
-                               __section("_ftrace_annotated_branch")   \
+                               __section(_ftrace_annotated_branch)     \
                                ______f = {                             \
                                .data.func = __func__,                  \
                                .data.file = __FILE__,                  \
@@ -60,7 +60,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 #define __trace_if_value(cond) ({                      \
        static struct ftrace_branch_data                \
                __aligned(4)                            \
-               __section("_ftrace_branch")             \
+               __section(_ftrace_branch)               \
                __if_trace = {                          \
                        .func = __func__,               \
                        .file = __FILE__,               \
@@ -118,7 +118,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
        ".popsection\n\t"
 
 /* Annotate a C jump table to allow objtool to follow the code flow */
-#define __annotate_jump_table __section(".rodata..c_jump_table")
+#define __annotate_jump_table __section(.rodata..c_jump_table)
 
 #else
 #define annotate_reachable()
@@ -298,7 +298,7 @@ unsigned long read_word_at_a_time(const void *addr)
  * visible to the compiler.
  */
 #define __ADDRESSABLE(sym) \
-       static void * __section(".discard.addressable") __used \
+       static void * __section(.discard.addressable) __used \
                __PASTE(__addressable_##sym, __LINE__) = (void *)&sym;
 
 /**
index 6b6c7396a584521aba86bcf2dd1ed0344f98ed76..cb732643471b118f188427ee06338ae0571830ac 100644 (file)
@@ -50,7 +50,6 @@ struct cn_dev {
 
        u32 seq, groups;
        struct sock *nls;
-       void (*input) (struct sk_buff *skb);
 
        struct cn_queue_dev *cbdev;
 };
index 7eb43a038330856293556d7952719cbf241509fb..f7a30e0099bee63bd80c4963a1eac3019dfb888b 100644 (file)
@@ -145,7 +145,11 @@ struct cred {
        struct user_struct *user;       /* real user ID subscription */
        struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
        struct group_info *group_info;  /* supplementary groups for euid/fsgid */
-       struct rcu_head rcu;            /* RCU deletion hook */
+       /* RCU deletion */
+       union {
+               int non_rcu;                    /* Can we skip RCU deletion? */
+               struct rcu_head rcu;            /* RCU deletion hook */
+       };
 } __randomize_layout;
 
 extern void __put_cred(struct cred *);
@@ -246,6 +250,7 @@ static inline const struct cred *get_cred(const struct cred *cred)
        if (!cred)
                return cred;
        validate_creds(cred);
+       nonconst_cred->non_rcu = 0;
        return get_new_cred(nonconst_cred);
 }
 
@@ -257,6 +262,7 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred)
        if (!atomic_inc_not_zero(&nonconst_cred->usage))
                return NULL;
        validate_creds(cred);
+       nonconst_cred->non_rcu = 0;
        return cred;
 }
 
index c330b75c6c57cdbd46a360bff2b50c96bde4d515..6717adee33f0199627c04c6e5b9363552e97a574 100644 (file)
@@ -915,6 +915,8 @@ struct dev_links_info {
  *             This identifies the device type and carries type-specific
  *             information.
  * @mutex:     Mutex to synchronize calls to its driver.
+ * @lockdep_mutex: An optional debug lock that a subsystem can use as a
+ *             peer lock to gain localized lockdep coverage of the device_lock.
  * @bus:       Type of bus device is on.
  * @driver:    Which driver has allocated this
  * @platform_data: Platform data specific to the device.
@@ -998,6 +1000,9 @@ struct device {
                                           core doesn't touch it */
        void            *driver_data;   /* Driver data, set and get with
                                           dev_set_drvdata/dev_get_drvdata */
+#ifdef CONFIG_PROVE_LOCKING
+       struct mutex            lockdep_mutex;
+#endif
        struct mutex            mutex;  /* mutex to synchronize calls to
                                         * its driver.
                                         */
@@ -1383,6 +1388,7 @@ extern int (*platform_notify_remove)(struct device *dev);
  */
 extern struct device *get_device(struct device *dev);
 extern void put_device(struct device *dev);
+extern bool kill_device(struct device *dev);
 
 #ifdef CONFIG_DEVTMPFS
 extern int devtmpfs_create_node(struct device *dev);
index d3a0fbfff2bb0931dddd8fd0d65ab544bc8f76b0..9fa4b3f88c397a790ce3d0d8a7042d5cea3107bd 100644 (file)
@@ -272,62 +272,6 @@ dim_update_sample_with_comps(u16 event_ctr, u64 packets, u64 bytes, u64 comps,
 
 /* Net DIM */
 
-/*
- * Net DIM profiles:
- *        There are different set of profiles for each CQ period mode.
- *        There are different set of profiles for RX/TX CQs.
- *        Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES
- */
-#define NET_DIM_PARAMS_NUM_PROFILES 5
-#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
-#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128
-#define NET_DIM_DEF_PROFILE_CQE 1
-#define NET_DIM_DEF_PROFILE_EQE 1
-
-#define NET_DIM_RX_EQE_PROFILES { \
-       {1,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-       {8,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-       {64,  NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-       {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-       {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-}
-
-#define NET_DIM_RX_CQE_PROFILES { \
-       {2,  256},             \
-       {8,  128},             \
-       {16, 64},              \
-       {32, 64},              \
-       {64, 64}               \
-}
-
-#define NET_DIM_TX_EQE_PROFILES { \
-       {1,   NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
-       {8,   NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
-       {32,  NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
-       {64,  NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
-       {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}   \
-}
-
-#define NET_DIM_TX_CQE_PROFILES { \
-       {5,  128},  \
-       {8,  64},  \
-       {16, 32},  \
-       {32, 32},  \
-       {64, 32}   \
-}
-
-static const struct dim_cq_moder
-rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
-       NET_DIM_RX_EQE_PROFILES,
-       NET_DIM_RX_CQE_PROFILES,
-};
-
-static const struct dim_cq_moder
-tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
-       NET_DIM_TX_EQE_PROFILES,
-       NET_DIM_TX_CQE_PROFILES,
-};
-
 /**
  *     net_dim_get_rx_moderation - provide a CQ moderation object for the given RX profile
  *     @cq_period_mode: CQ period mode
index c05d4e661489b3625a2e83874cc87d4a51edf875..03f8e98e3bcc94b781bc66928d7e5e9c667dbe8b 100644 (file)
@@ -160,10 +160,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
 static inline struct page *dma_alloc_contiguous(struct device *dev, size_t size,
                gfp_t gfp)
 {
-       int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
-       size_t align = get_order(PAGE_ALIGN(size));
-
-       return alloc_pages_node(node, gfp, align);
+       return NULL;
 }
 
 static inline void dma_free_contiguous(struct device *dev, struct page *page,
index e11b115dd0e44b32d0ffbbc3cc20181a8452526c..f7d1eea32c78b21ee9e1f02d20d8dd22ec35cc01 100644 (file)
@@ -689,8 +689,8 @@ static inline int dma_coerce_mask_and_coherent(struct device *dev, u64 mask)
  */
 static inline bool dma_addressing_limited(struct device *dev)
 {
-       return min_not_zero(*dev->dma_mask, dev->bus_dma_mask) <
-               dma_get_required_mask(dev);
+       return min_not_zero(dma_get_mask(dev), dev->bus_dma_mask) <
+                           dma_get_required_mask(dev);
 }
 
 #ifdef CONFIG_ARCH_HAS_SETUP_DMA_OPS
index 3813211a9aadef0e2dc2f96267faf914cad2987d..0bff3d7fac92c95e324928a0aadc48e6d4ffd35f 100644 (file)
@@ -42,13 +42,18 @@ void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
                dma_addr_t dma_addr, unsigned long attrs);
 long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
                dma_addr_t dma_addr);
-
-#ifdef CONFIG_ARCH_HAS_DMA_MMAP_PGPROT
 pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
                unsigned long attrs);
+
+#ifdef CONFIG_MMU
+pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs);
 #else
-# define arch_dma_mmap_pgprot(dev, prot, attrs)        pgprot_noncached(prot)
-#endif
+static inline pgprot_t dma_pgprot(struct device *dev, pgprot_t prot,
+               unsigned long attrs)
+{
+       return prot;    /* no protection bits supported without page tables */
+}
+#endif /* CONFIG_MMU */
 
 #ifdef CONFIG_DMA_NONCOHERENT_CACHE_SYNC
 void arch_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
index 17cd0078377cae91dc86d63541b1bd6b87141b0a..1dd014c9c87b57ade5d86311635d24aa8e78e2c1 100644 (file)
@@ -45,7 +45,6 @@ struct elevator_mq_ops {
        struct request *(*dispatch_request)(struct blk_mq_hw_ctx *);
        bool (*has_work)(struct blk_mq_hw_ctx *);
        void (*completed_request)(struct request *, u64);
-       void (*started_request)(struct request *);
        void (*requeue_request)(struct request *);
        struct request *(*former_request)(struct request_queue *, struct request *);
        struct request *(*next_request)(struct request_queue *, struct request *);
index ff65d22cf336935c9406930496dc8a8f57a0cbd0..92c6e31fb008ee80073e310797e27d0e72d428c2 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <net/sch_generic.h>
 
+#include <asm/byteorder.h>
 #include <uapi/linux/filter.h>
 #include <uapi/linux/bpf.h>
 
@@ -747,6 +748,18 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default)
        return size <= size_default && (size & (size - 1)) == 0;
 }
 
+static inline u8
+bpf_ctx_narrow_load_shift(u32 off, u32 size, u32 size_default)
+{
+       u8 load_off = off & (size_default - 1);
+
+#ifdef __LITTLE_ENDIAN
+       return load_off * 8;
+#else
+       return (size_default - (load_off + size)) * 8;
+#endif
+}
+
 #define bpf_ctx_wide_access_ok(off, size, type, field)                 \
        (size == sizeof(__u64) &&                                       \
        off >= offsetof(type, field) &&                                 \
index 56b8e358af5c1e6c6e02663a6722909e0a13d70d..997a530ff4e9d038d1e705c582833f8f6817a436 100644 (file)
@@ -2598,6 +2598,12 @@ extern struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
                                               void *holder);
 extern struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode,
                                              void *holder);
+extern struct block_device *bd_start_claiming(struct block_device *bdev,
+                                             void *holder);
+extern void bd_finish_claiming(struct block_device *bdev,
+                              struct block_device *whole, void *holder);
+extern void bd_abort_claiming(struct block_device *bdev,
+                             struct block_device *whole, void *holder);
 extern void blkdev_put(struct block_device *bdev, fmode_t mode);
 extern int __blkdev_reread_part(struct block_device *bdev);
 extern int blkdev_reread_part(struct block_device *bdev);
index fb07b503dc453ddfe16c5f0f959d46be01ad55ba..f33881688f42b2d6605d4f868546fbc06b1cd778 100644 (file)
@@ -510,22 +510,18 @@ alloc_pages(gfp_t gfp_mask, unsigned int order)
 }
 extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order,
                        struct vm_area_struct *vma, unsigned long addr,
-                       int node, bool hugepage);
-#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
-       alloc_pages_vma(gfp_mask, order, vma, addr, numa_node_id(), true)
+                       int node);
 #else
 #define alloc_pages(gfp_mask, order) \
                alloc_pages_node(numa_node_id(), gfp_mask, order)
-#define alloc_pages_vma(gfp_mask, order, vma, addr, node, false)\
-       alloc_pages(gfp_mask, order)
-#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
+#define alloc_pages_vma(gfp_mask, order, vma, addr, node)\
        alloc_pages(gfp_mask, order)
 #endif
 #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
 #define alloc_page_vma(gfp_mask, vma, addr)                    \
-       alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id(), false)
+       alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id())
 #define alloc_page_vma_node(gfp_mask, vma, addr, node)         \
-       alloc_pages_vma(gfp_mask, 0, vma, addr, node, false)
+       alloc_pages_vma(gfp_mask, 0, vma, addr, node)
 
 extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
 extern unsigned long get_zeroed_page(gfp_t gfp_mask);
index 40915b461f18d9179ed15efd57aed380b52392fa..f757a58191a6256368e9e0f7b17623b0500e2c0e 100644 (file)
@@ -241,30 +241,6 @@ static inline int irq_to_gpio(unsigned irq)
        return -EINVAL;
 }
 
-static inline int
-gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
-                      unsigned int gpio_offset, unsigned int pin_offset,
-                      unsigned int npins)
-{
-       WARN_ON(1);
-       return -EINVAL;
-}
-
-static inline int
-gpiochip_add_pingroup_range(struct gpio_chip *chip,
-                       struct pinctrl_dev *pctldev,
-                       unsigned int gpio_offset, const char *pin_group)
-{
-       WARN_ON(1);
-       return -EINVAL;
-}
-
-static inline void
-gpiochip_remove_pin_ranges(struct gpio_chip *chip)
-{
-       WARN_ON(1);
-}
-
 static inline int devm_gpio_request(struct device *dev, unsigned gpio,
                                    const char *label)
 {
index 9ddcf50a3c5924ad754d40029a3b0dd707ac556f..a7f08fb0f8653224ec2f87b11fad89d554b771c3 100644 (file)
@@ -247,7 +247,7 @@ static inline void gpiod_put(struct gpio_desc *desc)
        might_sleep();
 
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
 }
 
 static inline void devm_gpiod_unhinge(struct device *dev,
@@ -256,7 +256,7 @@ static inline void devm_gpiod_unhinge(struct device *dev,
        might_sleep();
 
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
 }
 
 static inline void gpiod_put_array(struct gpio_descs *descs)
@@ -264,7 +264,7 @@ static inline void gpiod_put_array(struct gpio_descs *descs)
        might_sleep();
 
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(descs);
 }
 
 static inline struct gpio_desc *__must_check
@@ -317,7 +317,7 @@ static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
        might_sleep();
 
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
 }
 
 static inline void devm_gpiod_put_array(struct device *dev,
@@ -326,32 +326,32 @@ static inline void devm_gpiod_put_array(struct device *dev,
        might_sleep();
 
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(descs);
 }
 
 
 static inline int gpiod_get_direction(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -ENOSYS;
 }
 static inline int gpiod_direction_input(struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -ENOSYS;
 }
 static inline int gpiod_direction_output(struct gpio_desc *desc, int value)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -ENOSYS;
 }
 static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -ENOSYS;
 }
 
@@ -359,7 +359,7 @@ static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
 static inline int gpiod_get_value(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return 0;
 }
 static inline int gpiod_get_array_value(unsigned int array_size,
@@ -368,13 +368,13 @@ static inline int gpiod_get_array_value(unsigned int array_size,
                                        unsigned long *value_bitmap)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc_array);
        return 0;
 }
 static inline void gpiod_set_value(struct gpio_desc *desc, int value)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
 }
 static inline int gpiod_set_array_value(unsigned int array_size,
                                        struct gpio_desc **desc_array,
@@ -382,13 +382,13 @@ static inline int gpiod_set_array_value(unsigned int array_size,
                                        unsigned long *value_bitmap)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc_array);
        return 0;
 }
 static inline int gpiod_get_raw_value(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return 0;
 }
 static inline int gpiod_get_raw_array_value(unsigned int array_size,
@@ -397,13 +397,13 @@ static inline int gpiod_get_raw_array_value(unsigned int array_size,
                                            unsigned long *value_bitmap)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc_array);
        return 0;
 }
 static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
 }
 static inline int gpiod_set_raw_array_value(unsigned int array_size,
                                            struct gpio_desc **desc_array,
@@ -411,14 +411,14 @@ static inline int gpiod_set_raw_array_value(unsigned int array_size,
                                            unsigned long *value_bitmap)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc_array);
        return 0;
 }
 
 static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return 0;
 }
 static inline int gpiod_get_array_value_cansleep(unsigned int array_size,
@@ -427,13 +427,13 @@ static inline int gpiod_get_array_value_cansleep(unsigned int array_size,
                                     unsigned long *value_bitmap)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc_array);
        return 0;
 }
 static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
 }
 static inline int gpiod_set_array_value_cansleep(unsigned int array_size,
                                            struct gpio_desc **desc_array,
@@ -441,13 +441,13 @@ static inline int gpiod_set_array_value_cansleep(unsigned int array_size,
                                            unsigned long *value_bitmap)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc_array);
        return 0;
 }
 static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return 0;
 }
 static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
@@ -456,14 +456,14 @@ static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
                                               unsigned long *value_bitmap)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc_array);
        return 0;
 }
 static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc,
                                                int value)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
 }
 static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
                                                struct gpio_desc **desc_array,
@@ -471,41 +471,41 @@ static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
                                                unsigned long *value_bitmap)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc_array);
        return 0;
 }
 
 static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -ENOSYS;
 }
 
 static inline int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -ENOSYS;
 }
 
 static inline int gpiod_is_active_low(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return 0;
 }
 static inline int gpiod_cansleep(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return 0;
 }
 
 static inline int gpiod_to_irq(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -EINVAL;
 }
 
@@ -513,7 +513,7 @@ static inline int gpiod_set_consumer_name(struct gpio_desc *desc,
                                          const char *name)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -EINVAL;
 }
 
@@ -525,7 +525,7 @@ static inline struct gpio_desc *gpio_to_desc(unsigned gpio)
 static inline int desc_to_gpio(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
-       WARN_ON(1);
+       WARN_ON(desc);
        return -EINVAL;
 }
 
index b8a08b2a10ca058a192086ab3507d66ccbe984f1..7ef56dc18050a22a9e2968fc80d3f5bf991ae74c 100644 (file)
@@ -484,60 +484,6 @@ long hmm_range_dma_unmap(struct hmm_range *range,
  */
 #define HMM_RANGE_DEFAULT_TIMEOUT 1000
 
-/* This is a temporary helper to avoid merge conflict between trees. */
-static inline bool hmm_vma_range_done(struct hmm_range *range)
-{
-       bool ret = hmm_range_valid(range);
-
-       hmm_range_unregister(range);
-       return ret;
-}
-
-/* This is a temporary helper to avoid merge conflict between trees. */
-static inline int hmm_vma_fault(struct hmm_mirror *mirror,
-                               struct hmm_range *range, bool block)
-{
-       long ret;
-
-       /*
-        * With the old API the driver must set each individual entries with
-        * the requested flags (valid, write, ...). So here we set the mask to
-        * keep intact the entries provided by the driver and zero out the
-        * default_flags.
-        */
-       range->default_flags = 0;
-       range->pfn_flags_mask = -1UL;
-
-       ret = hmm_range_register(range, mirror,
-                                range->start, range->end,
-                                PAGE_SHIFT);
-       if (ret)
-               return (int)ret;
-
-       if (!hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT)) {
-               /*
-                * The mmap_sem was taken by driver we release it here and
-                * returns -EAGAIN which correspond to mmap_sem have been
-                * drop in the old API.
-                */
-               up_read(&range->vma->vm_mm->mmap_sem);
-               return -EAGAIN;
-       }
-
-       ret = hmm_range_fault(range, block);
-       if (ret <= 0) {
-               if (ret == -EBUSY || !ret) {
-                       /* Same as above, drop mmap_sem to match old API. */
-                       up_read(&range->vma->vm_mm->mmap_sem);
-                       ret = -EBUSY;
-               } else if (ret == -EAGAIN)
-                       ret = -EBUSY;
-               hmm_range_unregister(range);
-               return ret;
-       }
-       return 0;
-}
-
 /* Below are for HMM internal use only! Not to be used by device driver! */
 static inline void hmm_mm_init(struct mm_struct *mm)
 {
index 8b728750a62580c6ed05fe93fc5aada94e145ac1..69e813bcb947ef59c1fc23e541a938d5c179d197 100644 (file)
@@ -80,6 +80,9 @@ extern int register_pppox_proto(int proto_num, const struct pppox_proto *pp);
 extern void unregister_pppox_proto(int proto_num);
 extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
 extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+extern int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+
+#define PPPOEIOCSFWD32    _IOW(0xB1 ,0, compat_size_t)
 
 /* PPPoX socket states */
 enum {
index b4f5403383fc9be106fad4cde572909df920c00c..9661416a9bb473da8bb329477b548a22fce4eaae 100644 (file)
@@ -41,11 +41,11 @@ struct rmnet_map_ul_csum_header {
        __be16 csum_start_offset;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
        u16 csum_insert_offset:14;
-       u16 udp_ip4_ind:1;
+       u16 udp_ind:1;
        u16 csum_enabled:1;
 #elif defined (__BIG_ENDIAN_BITFIELD)
        u16 csum_enabled:1;
-       u16 udp_ip4_ind:1;
+       u16 udp_ind:1;
        u16 csum_insert_offset:14;
 #else
 #error "Please fix <asm/byteorder.h>"
index ceabb01a6a7d939b8d7149e1e06877bd635829cd..1ecb6b45812c9dfd70d9eb77a48baf5eafef74d9 100644 (file)
@@ -48,7 +48,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0618", 0 },
        { "ELAN0619", 0 },
        { "ELAN061A", 0 },
-       { "ELAN061B", 0 },
+/*     { "ELAN061B", 0 }, not working on the Lenovo Legion Y7000 */
        { "ELAN061C", 0 },
        { "ELAN061D", 0 },
        { "ELAN061E", 0 },
index f2ae8a006ff8b279b9b86d68d49fcb8b62d70531..4fc6454f7ebb470a2ec20d0b2cab94b2df89ae38 100644 (file)
@@ -346,7 +346,6 @@ enum {
 #define QI_PC_PASID_SEL                (QI_PC_TYPE | QI_PC_GRAN(1))
 
 #define QI_EIOTLB_ADDR(addr)   ((u64)(addr) & VTD_PAGE_MASK)
-#define QI_EIOTLB_GL(gl)       (((u64)gl) << 7)
 #define QI_EIOTLB_IH(ih)       (((u64)ih) << 6)
 #define QI_EIOTLB_AM(am)       (((u64)am))
 #define QI_EIOTLB_PASID(pasid)         (((u64)pasid) << 32)
@@ -378,8 +377,6 @@ enum {
 #define QI_RESP_INVALID                0x1
 #define QI_RESP_FAILURE                0xf
 
-#define QI_GRAN_ALL_ALL                        0
-#define QI_GRAN_NONG_ALL               1
 #define QI_GRAN_NONG_PASID             2
 #define QI_GRAN_PSI_PASID              3
 
index 781b96ac706fcfae04eeba9be925c0e1cc5db879..a0637abffee88b0f0b12f3c6520cd5d2d77e779d 100644 (file)
@@ -155,6 +155,7 @@ struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
 void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
 void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
        unsigned long start_pfn);
+bool has_iova_flush_queue(struct iova_domain *iovad);
 int init_iova_flush_queue(struct iova_domain *iovad,
                          iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
@@ -235,6 +236,11 @@ static inline void init_iova_domain(struct iova_domain *iovad,
 {
 }
 
+static inline bool has_iova_flush_queue(struct iova_domain *iovad)
+{
+       return false;
+}
+
 static inline int init_iova_flush_queue(struct iova_domain *iovad,
                                        iova_flush_cb flush_cb,
                                        iova_entry_dtor entry_dtor)
index 91f391cd272e094d3d74683f08ac226fe8e1ce20..50028338a4cc081dc0f9dfcda8394804962dc1de 100644 (file)
@@ -94,11 +94,11 @@ struct keyring_index_key {
        union {
                struct {
 #ifdef __LITTLE_ENDIAN /* Put desc_len at the LSB of x */
-                       u     desc_len;
-                       char    desc[sizeof(long) - 1]; /* First few chars of description */
+                       u16     desc_len;
+                       char    desc[sizeof(long) - 2]; /* First few chars of description */
 #else
-                       char    desc[sizeof(long) - 1]; /* First few chars of description */
-                       u     desc_len;
+                       char    desc[sizeof(long) - 2]; /* First few chars of description */
+                       u16     desc_len;
 #endif
                };
                unsigned long x;
index 5c5b5867024cd80b69b96f29721faa6871c64dc5..fcb46b3374c60967993cf6123172c35a7cac4277 100644 (file)
@@ -861,8 +861,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
 
-bool kvm_arch_has_vcpu_debugfs(void);
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu);
+#ifdef __KVM_HAVE_ARCH_VCPU_DEBUGFS
+void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu);
+#endif
 
 int kvm_arch_hardware_enable(void);
 void kvm_arch_hardware_disable(void);
@@ -872,6 +873,7 @@ int kvm_arch_check_processor_compat(void);
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu);
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu);
 
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
 /*
index cbd9d8495690212fc689d3ce3a7caf0812d45523..88e1e6304a7193bca45a14500f7ade4632dbd335 100644 (file)
@@ -117,6 +117,7 @@ struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode);
 unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,
                        resource_size_t hw_addr, resource_size_t size);
 int logic_pio_register_range(struct logic_pio_hwaddr *newrange);
+void logic_pio_unregister_range(struct logic_pio_hwaddr *range);
 resource_size_t logic_pio_to_hwaddr(unsigned long pio);
 unsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr);
 
index 44c41462be334dac8edbc365c293d7014bed29e9..2cd4359cb38cb4fa44d8099b89cee0811eee22ff 100644 (file)
@@ -668,6 +668,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
 
 void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
                        int val);
+void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val);
 
 static inline void mod_lruvec_state(struct lruvec *lruvec,
                                    enum node_stat_item idx, int val)
@@ -1072,6 +1073,14 @@ static inline void mod_lruvec_page_state(struct page *page,
        mod_node_page_state(page_pgdat(page), idx, val);
 }
 
+static inline void __mod_lruvec_slab_state(void *p, enum node_stat_item idx,
+                                          int val)
+{
+       struct page *page = virt_to_head_page(p);
+
+       __mod_node_page_state(page_pgdat(page), idx, val);
+}
+
 static inline
 unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
                                            gfp_t gfp_mask,
@@ -1159,6 +1168,16 @@ static inline void __dec_lruvec_page_state(struct page *page,
        __mod_lruvec_page_state(page, idx, -1);
 }
 
+static inline void __inc_lruvec_slab_state(void *p, enum node_stat_item idx)
+{
+       __mod_lruvec_slab_state(p, idx, 1);
+}
+
+static inline void __dec_lruvec_slab_state(void *p, enum node_stat_item idx)
+{
+       __mod_lruvec_slab_state(p, idx, -1);
+}
+
 /* idx can be of type enum memcg_stat_item or node_stat_item */
 static inline void inc_memcg_state(struct mem_cgroup *memcg,
                                   int idx)
index 5228c62af41659bb7d5ae0e7db00969b9f16ef73..bac395f1d00a0f9691b12ec6841f2401a10ca4fc 100644 (file)
@@ -139,6 +139,8 @@ struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp,
 struct mempolicy *get_task_policy(struct task_struct *p);
 struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
                unsigned long addr);
+struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
+                                               unsigned long addr);
 bool vma_policy_mof(struct vm_area_struct *vma);
 
 extern void numa_default_policy(void);
index ce9839c8bc1a6ca539628f078fc8bf7471a84ce7..c2f056b5766df377a02414c5081134b12688efa6 100644 (file)
@@ -446,11 +446,11 @@ enum {
 };
 
 enum {
-       MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x20,
+       MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x1,
 };
 
 enum {
-       MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x20,
+       MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x1,
 };
 
 enum {
index 04a569568eacb738bcc52a9389f96eb4fcafdd7f..f049af3f3cd838c85d87e02d5e13f5a39d1ffec0 100644 (file)
@@ -220,6 +220,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_handle *handler,
 
 struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
 void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
+u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
 void mlx5_fc_query_cached(struct mlx5_fc *counter,
                          u64 *bytes, u64 *packets, u64 *lastuse);
 int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
index b3d5752657d9893fbc83bdaf577d872ed9bde5a4..b8b570c30b5ed967bd5acc38fe2e3f4a6c7025fa 100644 (file)
@@ -5975,10 +5975,12 @@ struct mlx5_ifc_modify_cq_in_bits {
 
        struct mlx5_ifc_cqc_bits cq_context;
 
-       u8         reserved_at_280[0x40];
+       u8         reserved_at_280[0x60];
 
        u8         cq_umem_valid[0x1];
-       u8         reserved_at_2c1[0x5bf];
+       u8         reserved_at_2e1[0x1f];
+
+       u8         reserved_at_300[0x580];
 
        u8         pas[0][0x40];
 };
@@ -10052,9 +10054,8 @@ struct mlx5_ifc_tls_static_params_bits {
 };
 
 struct mlx5_ifc_tls_progress_params_bits {
-       u8         valid[0x1];
-       u8         reserved_at_1[0x7];
-       u8         pd[0x18];
+       u8         reserved_at_0[0x8];
+       u8         tisn[0x18];
 
        u8         next_record_tcp_sn[0x20];
 
index 3a37a89eb7a7c363c4ac795b8ed782e657e3c6fe..6a7a1083b6fb796d89d47beba775b3dd57255c3f 100644 (file)
@@ -159,7 +159,16 @@ struct page {
                        /** @pgmap: Points to the hosting device page map. */
                        struct dev_pagemap *pgmap;
                        void *zone_device_data;
-                       unsigned long _zd_pad_1;        /* uses mapping */
+                       /*
+                        * ZONE_DEVICE private pages are counted as being
+                        * mapped so the next 3 words hold the mapping, index,
+                        * and private fields from the source anonymous or
+                        * page cache page while the page is migrated to device
+                        * private memory.
+                        * ZONE_DEVICE MEMORY_DEVICE_FS_DAX pages also
+                        * use the mapping, index, and private fields when
+                        * pmem backed DAX files are mapped.
+                        */
                };
 
                /** @rcu_head: You can use this to free a page by RCU. */
index d77d717c620cbe3362b5787086b546f08b938f46..3f38c30d2f13d1e3b86408a6edf1e0eb8ef52778 100644 (file)
@@ -215,8 +215,9 @@ enum node_stat_item {
        NR_INACTIVE_FILE,       /*  "     "     "   "       "         */
        NR_ACTIVE_FILE,         /*  "     "     "   "       "         */
        NR_UNEVICTABLE,         /*  "     "     "   "       "         */
-       NR_SLAB_RECLAIMABLE,
-       NR_SLAB_UNRECLAIMABLE,
+       NR_SLAB_RECLAIMABLE,    /* Please do not reorder this item */
+       NR_SLAB_UNRECLAIMABLE,  /* and this one without looking at
+                                * memcg_flush_percpu_vmstats() first. */
        NR_ISOLATED_ANON,       /* Temporary isolated pages from anon lru */
        NR_ISOLATED_FILE,       /* Temporary isolated pages from file lru */
        WORKINGSET_NODES,
index b2c1648f7e5d12e03c63c90f58dce9e504be08bb..5714fd35a83c43ca40c854ef5b1ddf8350da8aef 100644 (file)
@@ -814,6 +814,7 @@ struct tee_client_device_id {
 /**
  * struct wmi_device_id - WMI device identifier
  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
+ * @context: pointer to driver specific data
  */
 struct wmi_device_id {
        const char guid_string[UUID_STRING_LEN+1];
index 91d6275292a5cbf9eba0cd9211d2cd77a8900275..19df78341fb32bb6e69628a111c16661644f6d94 100644 (file)
@@ -1,7 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /****************************************************************************
- * ip_conntrack_h323_asn1.h - BER and PER decoding library for H.323
- *                           conntrack/NAT module.
+ * BER and PER decoding library for H.323 conntrack/NAT module.
  *
  * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
index 7a6871ac8784f56d1ba12f5530eb7232da9066ba..74c6f9241944d2fd6e70f59139d01c1099dcaf9d 100644 (file)
@@ -4,6 +4,9 @@
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  */
 
+#ifndef _NF_CONNTRACK_H323_TYPES_H
+#define _NF_CONNTRACK_H323_TYPES_H
+
 typedef struct TransportAddress_ipAddress {    /* SEQUENCE */
        int options;            /* No use */
        unsigned int ip;
@@ -931,3 +934,5 @@ typedef struct RasMessage { /* CHOICE */
                InfoRequestResponse infoRequestResponse;
        };
 } RasMessage;
+
+#endif /* _NF_CONNTRACK_H323_TYPES_H */
index 0cf857012f11fcf290a081b3cda67522996931f3..844f89e1b039119e5c86e49b52ffafcff350cbcd 100644 (file)
@@ -1164,7 +1164,7 @@ static inline int of_property_read_string_index(const struct device_node *np,
 }
 
 /**
- * of_property_read_bool - Findfrom a property
+ * of_property_read_bool - Find a property
  * @np:                device node from which the property value is to be read.
  * @propname:  name of the property to be searched.
  *
index 1dda31825ec4ae78c8852f15288a80c4a651bcf3..71283739ffd239c5790dd57f408411451fa68220 100644 (file)
@@ -32,6 +32,7 @@
 
 #endif /* CONFIG_SPARSEMEM */
 
+#ifndef BUILD_VDSO32_64
 /*
  * page->flags layout:
  *
 #define LAST_CPUPID_SHIFT 0
 #endif
 
-#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
+#ifdef CONFIG_KASAN_SW_TAGS
+#define KASAN_TAG_WIDTH 8
+#else
+#define KASAN_TAG_WIDTH 0
+#endif
+
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT+KASAN_TAG_WIDTH \
+       <= BITS_PER_LONG - NR_PAGEFLAGS
 #define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT
 #else
 #define LAST_CPUPID_WIDTH 0
 #endif
 
-#ifdef CONFIG_KASAN_SW_TAGS
-#define KASAN_TAG_WIDTH 8
 #if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH+LAST_CPUPID_WIDTH+KASAN_TAG_WIDTH \
        > BITS_PER_LONG - NR_PAGEFLAGS
-#error "KASAN: not enough bits in page flags for tag"
-#endif
-#else
-#define KASAN_TAG_WIDTH 0
+#error "Not enough bits in page flags"
 #endif
 
 /*
 #define LAST_CPUPID_NOT_IN_PAGE_FLAGS
 #endif
 
+#endif
 #endif /* _LINUX_PAGE_FLAGS_LAYOUT */
index b848517da64c3945e4f0bfe2fc6210ce801f165b..f91cb8898ff0af60d751f7c026c7b9f852fe620b 100644 (file)
@@ -152,6 +152,8 @@ enum pageflags {
        PG_savepinned = PG_dirty,
        /* Has a grant mapping of another (foreign) domain's page. */
        PG_foreign = PG_owner_priv_1,
+       /* Remapped by swiotlb-xen. */
+       PG_xen_remapped = PG_owner_priv_1,
 
        /* SLOB */
        PG_slob_free = PG_private,
@@ -329,6 +331,8 @@ PAGEFLAG(Pinned, pinned, PF_NO_COMPOUND)
        TESTSCFLAG(Pinned, pinned, PF_NO_COMPOUND)
 PAGEFLAG(SavePinned, savepinned, PF_NO_COMPOUND);
 PAGEFLAG(Foreign, foreign, PF_NO_COMPOUND);
+PAGEFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND)
+       TESTCLEARFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND)
 
 PAGEFLAG(Reserved, reserved, PF_NO_COMPOUND)
        __CLEARPAGEFLAG(Reserved, reserved, PF_NO_COMPOUND)
index 9e700d9f9f287d0db0bf770cd5c4ee2a564db94c..82e4cd1b7ac3cb50346492a27163da53bb206e2c 100644 (file)
@@ -1567,8 +1567,10 @@ extern bool pcie_ports_native;
 
 #ifdef CONFIG_PCIEASPM
 bool pcie_aspm_support_enabled(void);
+bool pcie_aspm_enabled(struct pci_dev *pdev);
 #else
 static inline bool pcie_aspm_support_enabled(void) { return false; }
+static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
 #endif
 
 #ifdef CONFIG_PCIEAER
index 462b90b73f939d475e800b7b8cec0cf96f6152d4..2fb9c8ffaf10a5b3ff654095a190c7c9df912fff 100644 (file)
@@ -1107,6 +1107,7 @@ int genphy_c45_an_disable_aneg(struct phy_device *phydev);
 int genphy_c45_read_mdix(struct phy_device *phydev);
 int genphy_c45_pma_read_abilities(struct phy_device *phydev);
 int genphy_c45_read_status(struct phy_device *phydev);
+int genphy_c45_config_aneg(struct phy_device *phydev);
 
 /* The gen10g_* functions are the old Clause 45 stub */
 int gen10g_config_aneg(struct phy_device *phydev);
index 1e5d86ebdaeb54cb5718ff10c8a8f74adc3a8efc..52bc8e487ef7d3442b562ffd9907027e53a310c4 100644 (file)
@@ -11,6 +11,7 @@ struct fixed_phy_status {
 };
 
 struct device_node;
+struct gpio_desc;
 
 #if IS_ENABLED(CONFIG_FIXED_PHY)
 extern int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier);
index 8dc1811487f5212ec89665269302f19db4c497c5..9f51932bd543f68e0d18d93dfe7c1bdaa047e616 100644 (file)
@@ -1092,7 +1092,15 @@ struct task_struct {
        u64                             last_sum_exec_runtime;
        struct callback_head            numa_work;
 
-       struct numa_group               *numa_group;
+       /*
+        * This pointer is only modified for current in syscall and
+        * pagefault context (and for tasks being destroyed), so it can be read
+        * from any of the following contexts:
+        *  - RCU read-side critical section
+        *  - current->numa_group from everywhere
+        *  - task's runqueue locked, task not running
+        */
+       struct numa_group __rcu         *numa_group;
 
        /*
         * numa_faults is an array split into four regions:
index e7dd04a84ba89d79507d461cee5b839269ff0b8a..3988762efe15c0e5a80602e2c9acb6a5820a740e 100644 (file)
@@ -19,7 +19,7 @@
 extern void task_numa_fault(int last_node, int node, int pages, int flags);
 extern pid_t task_numa_group_id(struct task_struct *p);
 extern void set_numabalancing_state(bool enabled);
-extern void task_numa_free(struct task_struct *p);
+extern void task_numa_free(struct task_struct *p, bool final);
 extern bool should_numa_migrate_memory(struct task_struct *p, struct page *page,
                                        int src_nid, int dst_cpu);
 #else
@@ -34,7 +34,7 @@ static inline pid_t task_numa_group_id(struct task_struct *p)
 static inline void set_numabalancing_state(bool enabled)
 {
 }
-static inline void task_numa_free(struct task_struct *p)
+static inline void task_numa_free(struct task_struct *p, bool final)
 {
 }
 static inline bool should_numa_migrate_memory(struct task_struct *p,
index b5d99482d3fe18e5f9c2eceb606a75458ae7e969..1a5f88316b081463a4e76bb8b48aa312f75162d5 100644 (file)
@@ -282,6 +282,9 @@ extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
 extern void exit_signals(struct task_struct *tsk);
 extern void kernel_sigaction(int, __sighandler_t);
 
+#define SIG_KTHREAD ((__force __sighandler_t)2)
+#define SIG_KTHREAD_KERNEL ((__force __sighandler_t)3)
+
 static inline void allow_signal(int sig)
 {
        /*
@@ -289,7 +292,17 @@ static inline void allow_signal(int sig)
         * know it'll be handled, so that they don't get converted to
         * SIGKILL or just silently dropped.
         */
-       kernel_sigaction(sig, (__force __sighandler_t)2);
+       kernel_sigaction(sig, SIG_KTHREAD);
+}
+
+static inline void allow_kernel_signal(int sig)
+{
+       /*
+        * Kernel threads handle their own signals. Let the signal code
+        * know signals sent by the kernel will be handled, so that they
+        * don't get silently dropped.
+        */
+       kernel_sigaction(sig, SIG_KTHREAD_KERNEL);
 }
 
 static inline void disallow_signal(int sig)
index d8af86d995d6fe0b7fe8afc3a21d7d8faac2d7ce..ba5583522d249444361314dc12ef63d5e6d5e79a 100644 (file)
@@ -1374,6 +1374,14 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
        to->l4_hash = from->l4_hash;
 };
 
+static inline void skb_copy_decrypted(struct sk_buff *to,
+                                     const struct sk_buff *from)
+{
+#ifdef CONFIG_TLS_DEVICE
+       to->decrypted = from->decrypted;
+#endif
+}
+
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
 {
index 50ced8aba9dbf6c2cd4a0a1ef1598bdd58822821..e4b3fb4bb77c7004d9164c6ba85f3be37eea741f 100644 (file)
@@ -354,7 +354,13 @@ static inline void sk_psock_restore_proto(struct sock *sk,
        sk->sk_write_space = psock->saved_write_space;
 
        if (psock->sk_proto) {
-               sk->sk_prot = psock->sk_proto;
+               struct inet_connection_sock *icsk = inet_csk(sk);
+               bool has_ulp = !!icsk->icsk_ulp_data;
+
+               if (has_ulp)
+                       tcp_update_ulp(sk, psock->sk_proto);
+               else
+                       sk->sk_prot = psock->sk_proto;
                psock->sk_proto = NULL;
        }
 }
index 97523818cb14e0676cdc22c6b748f5b643ddc9ec..fc0bed59fc84ef8e6631d3c275853d52a46f84aa 100644 (file)
@@ -292,6 +292,9 @@ struct ucred {
 #define MSG_BATCH      0x40000 /* sendmmsg(): more messages coming */
 #define MSG_EOF         MSG_FIN
 #define MSG_NO_SHARED_FRAGS 0x80000 /* sendpage() internal : page frags are not shared */
+#define MSG_SENDPAGE_DECRYPTED 0x100000 /* sendpage() internal : page may carry
+                                         * plain text and require encryption
+                                         */
 
 #define MSG_ZEROCOPY   0x4000000       /* Use user data in kernel path */
 #define MSG_FASTOPEN   0x20000000      /* Send data in TCP SYN */
index baa3ecdb882f2428ca1dad0159f794bd71ecff3a..27536b961552c21217b9ccad96a0ecec71243342 100644 (file)
@@ -98,7 +98,6 @@ typedef void                  (*rpc_action)(struct rpc_task *);
 
 struct rpc_call_ops {
        void (*rpc_call_prepare)(struct rpc_task *, void *);
-       void (*rpc_call_prepare_transmit)(struct rpc_task *, void *);
        void (*rpc_call_done)(struct rpc_task *, void *);
        void (*rpc_count_stats)(struct rpc_task *, void *);
        void (*rpc_release)(void *);
index 88145da7d14078ff4af7594271d7411d7c8eba61..f7c561c4dcdd5fa5d1376ac0d75fad959729c48e 100644 (file)
@@ -1402,4 +1402,23 @@ static inline unsigned int ksys_personality(unsigned int personality)
        return old;
 }
 
+/* for __ARCH_WANT_SYS_IPC */
+long ksys_semtimedop(int semid, struct sembuf __user *tsops,
+                    unsigned int nsops,
+                    const struct __kernel_timespec __user *timeout);
+long ksys_semget(key_t key, int nsems, int semflg);
+long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);
+long ksys_msgget(key_t key, int msgflg);
+long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
+long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
+                long msgtyp, int msgflg);
+long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz,
+                int msgflg);
+long ksys_shmget(key_t key, size_t size, int shmflg);
+long ksys_shmdt(char __user *shmaddr);
+long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
+long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
+                           unsigned int nsops,
+                           const struct old_timespec32 __user *timeout);
+
 #endif
index 7acb953298a73118028ae04052fab9249529380f..84ff2844df2a8bc240b7186b7258fbef20c62940 100644 (file)
@@ -57,6 +57,7 @@ struct tk_read_base {
  * @cs_was_changed_seq:        The sequence number of clocksource change events
  * @next_leap_ktime:   CLOCK_MONOTONIC time value of a pending leap-second
  * @raw_sec:           CLOCK_MONOTONIC_RAW  time in seconds
+ * @monotonic_to_boot: CLOCK_MONOTONIC to CLOCK_BOOTTIME offset
  * @cycle_interval:    Number of clock cycles in one NTP interval
  * @xtime_interval:    Number of clock shifted nano seconds in one NTP
  *                     interval.
@@ -84,6 +85,9 @@ struct tk_read_base {
  *
  * wall_to_monotonic is no longer the boot time, getboottime must be
  * used instead.
+ *
+ * @monotonic_to_boottime is a timespec64 representation of @offs_boot to
+ * accelerate the VDSO update for CLOCK_BOOTTIME.
  */
 struct timekeeper {
        struct tk_read_base     tkr_mono;
@@ -99,6 +103,7 @@ struct timekeeper {
        u8                      cs_was_changed_seq;
        ktime_t                 next_leap_ktime;
        u64                     raw_sec;
+       struct timespec64       monotonic_to_boot;
 
        /* The following members are for timekeeping internal use */
        u64                     cycle_interval;
index 5150436783e8e44e920a62a045e181e70fb98887..30a8cdcfd4a4f2c72e89eefcbf71e2bb6764dcd2 100644 (file)
@@ -548,6 +548,7 @@ extern int trace_event_get_offsets(struct trace_event_call *call);
 
 #define is_signed_type(type)   (((type)(-1)) < (type)1)
 
+int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set);
 int trace_set_clr_event(const char *system, const char *event, int set);
 
 /*
index 83d35d993e8c91cda28eb4f6f0ff222750a4a1db..e87826e23d593026f4d2fb2432f418f716585b67 100644 (file)
@@ -1457,7 +1457,7 @@ typedef void (*usb_complete_t)(struct urb *);
  * field rather than determining a dma address themselves.
  *
  * Note that transfer_buffer must still be set if the controller
- * does not support DMA (as indicated by bus.uses_dma) and when talking
+ * does not support DMA (as indicated by hcd_uses_dma()) and when talking
  * to root hub. If you have to trasfer between highmem zone and the device
  * on such controller, create a bounce buffer or bail out with an error.
  * If transfer_buffer cannot be set (is in highmem) and the controller is DMA
index bab27ccc8ff564eb70d364746e1fc317c0fd3fb2..a20e7815d814cb1fd6f84c91730d8584f8381fe4 100644 (file)
@@ -422,6 +422,9 @@ static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
        return hcd->high_prio_bh.completing_ep == ep;
 }
 
+#define hcd_uses_dma(hcd) \
+       (IS_ENABLED(CONFIG_HAS_DMA) && (hcd)->self.uses_dma)
+
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
 extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
                int status);
index b6f77cf60dd7bbf8154aa56a3ea0bb2631221981..30c515520fb28c69873aad6d0b498a59679f46ab 100644 (file)
@@ -126,6 +126,19 @@ static inline int waitqueue_active(struct wait_queue_head *wq_head)
        return !list_empty(&wq_head->head);
 }
 
+/**
+ * wq_has_single_sleeper - check if there is only one sleeper
+ * @wq_head: wait queue head
+ *
+ * Returns true of wq_head has only one sleeper on the list.
+ *
+ * Please refer to the comment for waitqueue_active.
+ */
+static inline bool wq_has_single_sleeper(struct wait_queue_head *wq_head)
+{
+       return list_is_singular(&wq_head->head);
+}
+
 /**
  * wq_has_sleeper - check if there are any waiting processes
  * @wq_head: wait queue head
index f37d12877754b05a3f534097d7fd7c957326c94e..adcc6a97db6123e7a19ed43e59659f4874b9b5a0 100644 (file)
@@ -308,6 +308,7 @@ do {                                                                             \
                                                                             \
   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):                          \
     R##_e = X##_e;                                                          \
+         /* Fall through */                                                 \
   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):                           \
   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):                              \
   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                                     \
@@ -318,6 +319,7 @@ do {                                                                             \
                                                                             \
   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):                          \
     R##_e = Y##_e;                                                          \
+         /* Fall through */                                                 \
   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):                           \
   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):                              \
   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                                     \
@@ -415,6 +417,7 @@ do {                                                        \
   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):         \
   case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                \
     R##_s = X##_s;                                     \
+       /* Fall through */                              \
                                                        \
   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):         \
   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):      \
@@ -428,6 +431,7 @@ do {                                                        \
   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):         \
   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                \
     R##_s = Y##_s;                                     \
+       /* Fall through */                              \
                                                        \
   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):      \
   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):     \
@@ -493,6 +497,7 @@ do {                                                        \
                                                        \
   case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):     \
     FP_SET_EXCEPTION(FP_EX_DIVZERO);                   \
+         /* Fall through */                            \
   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):                \
   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):      \
     R##_c = FP_CLS_INF;                                        \
diff --git a/include/misc/charlcd.h b/include/misc/charlcd.h
deleted file mode 100644 (file)
index 8cf6c18..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Character LCD driver for Linux
- *
- * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
- * Copyright (C) 2016-2017 Glider bvba
- */
-
-struct charlcd {
-       const struct charlcd_ops *ops;
-       const unsigned char *char_conv; /* Optional */
-
-       int ifwidth;                    /* 4-bit or 8-bit (default) */
-       int height;
-       int width;
-       int bwidth;                     /* Default set by charlcd_alloc() */
-       int hwidth;                     /* Default set by charlcd_alloc() */
-
-       void *drvdata;                  /* Set by charlcd_alloc() */
-};
-
-struct charlcd_ops {
-       /* Required */
-       void (*write_cmd)(struct charlcd *lcd, int cmd);
-       void (*write_data)(struct charlcd *lcd, int data);
-
-       /* Optional */
-       void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
-       void (*clear_fast)(struct charlcd *lcd);
-       void (*backlight)(struct charlcd *lcd, int on);
-};
-
-struct charlcd *charlcd_alloc(unsigned int drvdata_size);
-void charlcd_free(struct charlcd *lcd);
-
-int charlcd_register(struct charlcd *lcd);
-int charlcd_unregister(struct charlcd *lcd);
-
-void charlcd_poke(struct charlcd *lcd);
index c61a1bf4e3de544dd41886e9126b7ff20eb829c3..3a1a72990fceb7744725b65dd65a0827ad1d9636 100644 (file)
@@ -15,6 +15,7 @@
 struct tcf_idrinfo {
        struct mutex    lock;
        struct idr      action_idr;
+       struct net      *net;
 };
 
 struct tc_action_ops;
@@ -108,7 +109,7 @@ struct tc_action_net {
 };
 
 static inline
-int tc_action_net_init(struct tc_action_net *tn,
+int tc_action_net_init(struct net *net, struct tc_action_net *tn,
                       const struct tc_action_ops *ops)
 {
        int err = 0;
@@ -117,6 +118,7 @@ int tc_action_net_init(struct tc_action_net *tn,
        if (!tn->idrinfo)
                return -ENOMEM;
        tn->ops = ops;
+       tn->idrinfo->net = net;
        mutex_init(&tn->idrinfo->lock);
        idr_init(&tn->idrinfo->action_idr);
        return err;
index becdad57685908a4b07bb3df890260483aa3e36a..3f62b347b04a7bfee96425a173922cbe6d390cb3 100644 (file)
@@ -206,7 +206,7 @@ static inline int ipv6_mc_may_pull(struct sk_buff *skb,
                                   unsigned int len)
 {
        if (skb_transport_offset(skb) + ipv6_transport_len(skb) < len)
-               return -EINVAL;
+               return 0;
 
        return pskb_may_pull(skb, len);
 }
index ded574b32c2089c2140397a30d985ff7c1c550f0..ffc95b382eb56cac8b32ec2c022eb3a9e19159ad 100644 (file)
@@ -278,6 +278,7 @@ struct hci_dev {
        __u16           conn_info_min_age;
        __u16           conn_info_max_age;
        __u16           auth_payload_timeout;
+       __u8            min_enc_key_size;
        __u8            ssp_debug_mode;
        __u8            hw_error_code;
        __u32           clock;
index 88c27153a4bcca14a6bf6f5e424832d5047b7f89..26e2ad2c702786781d326f01c7bb824775a82d37 100644 (file)
@@ -4170,7 +4170,7 @@ struct sta_opmode_info {
        u8 rx_nss;
 };
 
-#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)ERR_PTR(-ENODATA))
+#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)(long)(-ENODATA))
 
 /**
  * struct wiphy_vendor_command - vendor command definition
@@ -7320,6 +7320,21 @@ void cfg80211_pmsr_complete(struct wireless_dev *wdev,
                            struct cfg80211_pmsr_request *req,
                            gfp_t gfp);
 
+/**
+ * cfg80211_iftype_allowed - check whether the interface can be allowed
+ * @wiphy: the wiphy
+ * @iftype: interface type
+ * @is_4addr: use_4addr flag, must be '0' when check_swif is '1'
+ * @check_swif: check iftype against software interfaces
+ *
+ * Check whether the interface is allowed to operate; additionally, this API
+ * can be used to check iftype against the software interfaces when
+ * check_swif is '1'.
+ */
+bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
+                            bool is_4addr, u8 check_swif);
+
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
index db337299e81e87eed3dec9ba074021d4dd10991c..b16d21636d6969113549f7d943037694914a50d1 100644 (file)
@@ -2,8 +2,8 @@
 #define _NET_FLOW_OFFLOAD_H
 
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <net/flow_dissector.h>
-#include <net/sch_generic.h>
 
 struct flow_match {
        struct flow_dissector   *dissector;
@@ -249,6 +249,10 @@ enum flow_block_binder_type {
        FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
 };
 
+struct flow_block {
+       struct list_head cb_list;
+};
+
 struct netlink_ext_ack;
 
 struct flow_block_offload {
@@ -256,29 +260,33 @@ struct flow_block_offload {
        enum flow_block_binder_type binder_type;
        bool block_shared;
        struct net *net;
+       struct flow_block *block;
        struct list_head cb_list;
        struct list_head *driver_block_list;
        struct netlink_ext_ack *extack;
 };
 
+enum tc_setup_type;
+typedef int flow_setup_cb_t(enum tc_setup_type type, void *type_data,
+                           void *cb_priv);
+
 struct flow_block_cb {
        struct list_head        driver_list;
        struct list_head        list;
-       struct net              *net;
-       tc_setup_cb_t           *cb;
+       flow_setup_cb_t         *cb;
        void                    *cb_ident;
        void                    *cb_priv;
        void                    (*release)(void *cb_priv);
        unsigned int            refcnt;
 };
 
-struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
+struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
                                          void *cb_ident, void *cb_priv,
                                          void (*release)(void *cb_priv));
 void flow_block_cb_free(struct flow_block_cb *block_cb);
 
-struct flow_block_cb *flow_block_cb_lookup(struct flow_block_offload *offload,
-                                          tc_setup_cb_t *cb, void *cb_ident);
+struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
+                                          flow_setup_cb_t *cb, void *cb_ident);
 
 void *flow_block_cb_priv(struct flow_block_cb *block_cb);
 void flow_block_cb_incref(struct flow_block_cb *block_cb);
@@ -296,11 +304,12 @@ static inline void flow_block_cb_remove(struct flow_block_cb *block_cb,
        list_move(&block_cb->list, &offload->cb_list);
 }
 
-bool flow_block_cb_is_busy(tc_setup_cb_t *cb, void *cb_ident,
+bool flow_block_cb_is_busy(flow_setup_cb_t *cb, void *cb_ident,
                           struct list_head *driver_block_list);
 
 int flow_block_cb_setup_simple(struct flow_block_offload *f,
-                              struct list_head *driver_list, tc_setup_cb_t *cb,
+                              struct list_head *driver_list,
+                              flow_setup_cb_t *cb,
                               void *cb_ident, void *cb_priv, bool ingress_only);
 
 enum flow_cls_command {
@@ -333,4 +342,9 @@ flow_cls_offload_flow_rule(struct flow_cls_offload *flow_cmd)
        return flow_cmd->rule;
 }
 
+static inline void flow_block_init(struct flow_block *flow_block)
+{
+       INIT_LIST_HEAD(&flow_block->cb_list);
+}
+
 #endif /* _NET_FLOW_OFFLOAD_H */
index 010f26b31c89b375f4cabf6572d51f0383c93f0e..bac79e817776c6e65ed37f5b5c6af61a5df59ec0 100644 (file)
@@ -171,7 +171,7 @@ int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
 void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
                              struct sk_buff *parent);
 void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
-                           void *reasm_data);
+                           void *reasm_data, bool try_coalesce);
 struct sk_buff *inet_frag_pull_head(struct inet_frag_queue *q);
 
 #endif
index 4c81846ccce8c2e16e3effd0ab4573e07887255c..ab1ca9e238d2726507596b8a5408bc97a9f5e3d0 100644 (file)
@@ -513,7 +513,7 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
                          struct netlink_callback *cb);
 
 int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
-                    unsigned char *flags, bool skip_oif);
+                    u8 rt_family, unsigned char *flags, bool skip_oif);
 int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
-                   int nh_weight);
+                   int nh_weight, u8 rt_family);
 #endif  /* _NET_FIB_H */
index 4a9da951a794efbf9183c0a2e3d3ca94ec88f9d5..ab40d7afdc541703e4e314fea1cb33950d2201f6 100644 (file)
@@ -52,7 +52,7 @@ struct bpf_prog;
 #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
 
 struct net {
-       refcount_t              passive;        /* To decided when the network
+       refcount_t              passive;        /* To decide when the network
                                                 * namespace should be freed.
                                                 */
        refcount_t              count;          /* To decided when the network
@@ -61,7 +61,6 @@ struct net {
        spinlock_t              rules_mod_lock;
 
        u32                     hash_mix;
-       atomic64_t              cookie_gen;
 
        struct list_head        list;           /* list of network namespaces */
        struct list_head        exit_list;      /* To linked to call pernet exit
index 93ce6b0daaba9accf8dd270653b51f4a3d815c02..573429be4d59a0f7e2dba9f6cfb2cb917ed7325c 100644 (file)
@@ -76,6 +76,11 @@ struct nf_conntrack_expect_policy {
 #define NF_CT_EXPECT_CLASS_DEFAULT     0
 #define NF_CT_EXPECT_MAX_CNT           255
 
+/* Allow to reuse expectations with the same tuples from different master
+ * conntracks.
+ */
+#define NF_CT_EXP_F_SKIP_MASTER        0x1
+
 int nf_conntrack_expect_pernet_init(struct net *net);
 void nf_conntrack_expect_pernet_fini(struct net *net);
 
@@ -122,10 +127,11 @@ void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t,
                       u_int8_t, const __be16 *, const __be16 *);
 void nf_ct_expect_put(struct nf_conntrack_expect *exp);
 int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, 
-                               u32 portid, int report);
-static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect)
+                               u32 portid, int report, unsigned int flags);
+static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect,
+                                      unsigned int flags)
 {
-       return nf_ct_expect_related_report(expect, 0, 0);
+       return nf_ct_expect_related_report(expect, 0, 0, flags);
 }
 
 #endif /*_NF_CONNTRACK_EXPECT_H*/
index 8f00125b06f4b380423738ea4101299cdde3409e..44513b93bd557511500ebb17163b652833c60259 100644 (file)
@@ -68,6 +68,7 @@ struct synproxy_options {
        u8                              options;
        u8                              wscale;
        u16                             mss;
+       u16                             mss_encode;
        u32                             tsval;
        u32                             tsecr;
 };
index 35dfdd9f69b37940b258e5d5e9785e2bee27039b..475d6f28ca677a8b40c106fa08af86971226000e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/rhashtable.h>
 #include <net/netfilter/nf_flow_table.h>
 #include <net/netlink.h>
+#include <net/flow_offload.h>
 
 struct module;
 
@@ -420,8 +421,7 @@ struct nft_set {
        unsigned char                   *udata;
        /* runtime data below here */
        const struct nft_set_ops        *ops ____cacheline_aligned;
-       u16                             flags:13,
-                                       bound:1,
+       u16                             flags:14,
                                        genmask:2;
        u8                              klen;
        u8                              dlen;
@@ -951,7 +951,7 @@ struct nft_stats {
  *     @stats: per-cpu chain stats
  *     @chain: the chain
  *     @dev_name: device name that this base chain is attached to (if any)
- *     @cb_list: list of flow block callbacks (for hardware offload)
+ *     @flow_block: flow block (for hardware offload)
  */
 struct nft_base_chain {
        struct nf_hook_ops              ops;
@@ -961,7 +961,7 @@ struct nft_base_chain {
        struct nft_stats __percpu       *stats;
        struct nft_chain                chain;
        char                            dev_name[IFNAMSIZ];
-       struct list_head                cb_list;
+       struct flow_block               flow_block;
 };
 
 static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain)
@@ -1347,12 +1347,15 @@ struct nft_trans_rule {
 struct nft_trans_set {
        struct nft_set                  *set;
        u32                             set_id;
+       bool                            bound;
 };
 
 #define nft_trans_set(trans)   \
        (((struct nft_trans_set *)trans->data)->set)
 #define nft_trans_set_id(trans)        \
        (((struct nft_trans_set *)trans->data)->set_id)
+#define nft_trans_set_bound(trans)     \
+       (((struct nft_trans_set *)trans->data)->bound)
 
 struct nft_trans_chain {
        bool                            update;
@@ -1383,12 +1386,15 @@ struct nft_trans_table {
 struct nft_trans_elem {
        struct nft_set                  *set;
        struct nft_set_elem             elem;
+       bool                            bound;
 };
 
 #define nft_trans_elem_set(trans)      \
        (((struct nft_trans_elem *)trans->data)->set)
 #define nft_trans_elem(trans)  \
        (((struct nft_trans_elem *)trans->data)->elem)
+#define nft_trans_elem_set_bound(trans)        \
+       (((struct nft_trans_elem *)trans->data)->bound)
 
 struct nft_trans_obj {
        struct nft_object               *obj;
index 3196663a10e30e24880f571fb59a30e2e2cabfb7..c8b9dec376f56599a7403718727b0674681fbcdb 100644 (file)
@@ -73,4 +73,6 @@ int nft_flow_rule_offload_commit(struct net *net);
        (__reg)->key            = __key;                                \
        memset(&(__reg)->mask, 0xff, (__reg)->len);
 
+int nft_chain_offload_priority(struct nft_base_chain *basechain);
+
 #endif
index e4650e5b64a1db760a220fba3b7d4ad50eb54b17..b140c8f1be22d2e9943d7d98ae9e7db3c076f20b 100644 (file)
@@ -684,9 +684,8 @@ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
                              const struct nla_policy *policy,
                              struct netlink_ext_ack *extack)
 {
-       return __nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
-                          nlmsg_attrlen(nlh, hdrlen), policy,
-                          NL_VALIDATE_STRICT, extack);
+       return __nlmsg_parse(nlh, hdrlen, tb, maxtype, policy,
+                            NL_VALIDATE_STRICT, extack);
 }
 
 /**
index 25f1f9a8419b88eba011f1d14c6e1987146b2b26..331ebbc94fe7846ed3563b6050c1d24e0d9a150c 100644 (file)
@@ -141,12 +141,6 @@ static inline unsigned int nexthop_num_path(const struct nexthop *nh)
 
                nh_grp = rcu_dereference_rtnl(nh->nh_grp);
                rc = nh_grp->num_nh;
-       } else {
-               const struct nh_info *nhi;
-
-               nhi = rcu_dereference_rtnl(nh->nh_info);
-               if (nhi->reject_nh)
-                       rc = 0;
        }
 
        return rc;
@@ -167,7 +161,8 @@ struct nexthop *nexthop_mpath_select(const struct nexthop *nh, int nhsel)
 }
 
 static inline
-int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh)
+int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh,
+                           u8 rt_family)
 {
        struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
        int i;
@@ -178,7 +173,7 @@ int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh)
                struct fib_nh_common *nhc = &nhi->fib_nhc;
                int weight = nhg->nh_entries[i].weight;
 
-               if (fib_add_nexthop(skb, nhc, weight) < 0)
+               if (fib_add_nexthop(skb, nhc, weight, rt_family) < 0)
                        return -EMSGSIZE;
        }
 
index 841faadceb6ee47471072f4f9b19ffebecc0798f..98be18ef1ed3400739120e354ba1c5082bc94770 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/workqueue.h>
 #include <net/sch_generic.h>
 #include <net/act_api.h>
-#include <net/flow_offload.h>
 #include <net/net_namespace.h>
 
 /* TC action not accessible from user space */
@@ -126,14 +125,14 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
 }
 
 static inline
-int tc_setup_cb_block_register(struct tcf_block *block, tc_setup_cb_t *cb,
+int tc_setup_cb_block_register(struct tcf_block *block, flow_setup_cb_t *cb,
                               void *cb_priv)
 {
        return 0;
 }
 
 static inline
-void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
+void tc_setup_cb_block_unregister(struct tcf_block *block, flow_setup_cb_t *cb,
                                  void *cb_priv)
 {
 }
@@ -647,7 +646,7 @@ tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common,
 {
        cls_common->chain_index = tp->chain->index;
        cls_common->protocol = tp->protocol;
-       cls_common->prio = tp->prio;
+       cls_common->prio = tp->prio >> 16;
        if (tc_skip_sw(flags) || flags & TCA_CLS_FLAGS_VERBOSE)
                cls_common->extack = extack;
 }
index 37a4df2325b2eff3ad8d17df2c76fde184dd87c1..6b578ce69cd8a2b78d0fcaed3005f435380c4823 100644 (file)
@@ -11,6 +11,7 @@ struct psample_group {
        u32 group_num;
        u32 refcount;
        u32 seq;
+       struct rcu_head rcu;
 };
 
 struct psample_group *psample_group_get(struct net *net, u32 group_num);
index 630a0493f1f31e082ef29a26810946959ab65513..dfce19c9fa9618add7323eeee6e42e6d1a08ad84 100644 (file)
@@ -233,7 +233,7 @@ void rt_del_uncached_list(struct rtable *rt);
 
 int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb,
                       u32 table_id, struct fib_info *fi,
-                      int *fa_index, int fa_start);
+                      int *fa_index, int fa_start, unsigned int flags);
 
 static inline void ip_rt_put(struct rtable *rt)
 {
index 855167bbc3729940f7b44f533a13b0fdb00e558f..6b6b01234dd9d916d969baced8b784bc2740d805 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mutex.h>
 #include <net/gen_stats.h>
 #include <net/rtnetlink.h>
+#include <net/flow_offload.h>
 
 struct Qdisc_ops;
 struct qdisc_walker;
@@ -22,9 +23,6 @@ struct tcf_walker;
 struct module;
 struct bpf_flow_keys;
 
-typedef int tc_setup_cb_t(enum tc_setup_type type,
-                         void *type_data, void *cb_priv);
-
 typedef int tc_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv,
                                    enum tc_setup_type type, void *type_data);
 
@@ -313,7 +311,7 @@ struct tcf_proto_ops {
        void                    (*walk)(struct tcf_proto *tp,
                                        struct tcf_walker *arg, bool rtnl_held);
        int                     (*reoffload)(struct tcf_proto *tp, bool add,
-                                            tc_setup_cb_t *cb, void *cb_priv,
+                                            flow_setup_cb_t *cb, void *cb_priv,
                                             struct netlink_ext_ack *extack);
        void                    (*bind_class)(void *, u32, unsigned long);
        void *                  (*tmplt_create)(struct net *net,
@@ -401,7 +399,7 @@ struct tcf_block {
        refcount_t refcnt;
        struct net *net;
        struct Qdisc *q;
-       struct list_head cb_list;
+       struct flow_block flow_block;
        struct list_head owner_list;
        bool keep_dst;
        unsigned int offloadcnt; /* Number of oddloaded filters */
index 228db3998e46e42156fec16e78f5e627669a9687..2c53f1a1d905409247b1bdafdfaf99d86e430cd0 100644 (file)
@@ -2482,6 +2482,7 @@ static inline bool sk_fullsock(const struct sock *sk)
 
 /* Checks if this SKB belongs to an HW offloaded socket
  * and whether any SW fallbacks are required based on dev.
+ * Check decrypted mark in case skb_orphan() cleared socket.
  */
 static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
                                                   struct net_device *dev)
@@ -2489,8 +2490,15 @@ static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
 #ifdef CONFIG_SOCK_VALIDATE_XMIT
        struct sock *sk = skb->sk;
 
-       if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb)
+       if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb) {
                skb = sk->sk_validate_xmit_skb(sk, dev, skb);
+#ifdef CONFIG_TLS_DEVICE
+       } else if (unlikely(skb->decrypted)) {
+               pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n");
+               kfree_skb(skb);
+               skb = NULL;
+#endif
+       }
 #endif
 
        return skb;
index 8b9ef366426256ee83943f9da05bd1c301ffbf23..cfdc7cb82cad02b12167a168d2cce13def02f0c0 100644 (file)
@@ -54,7 +54,7 @@ static inline u64 tcf_police_rate_bytes_ps(const struct tc_action *act)
        struct tcf_police *police = to_police(act);
        struct tcf_police_params *params;
 
-       params = rcu_dereference_bh(police->params);
+       params = rcu_dereference_bh_rtnl(police->params);
        return params->rate.rate_bytes_ps;
 }
 
@@ -63,7 +63,7 @@ static inline s64 tcf_police_tcfp_burst(const struct tc_action *act)
        struct tcf_police *police = to_police(act);
        struct tcf_police_params *params;
 
-       params = rcu_dereference_bh(police->params);
+       params = rcu_dereference_bh_rtnl(police->params);
        return params->tcfp_burst;
 }
 
index 0a559d4b6f0f019a872e2afad578fc3cd3d02b1b..b4fce0fae645690207be3b4cd289cf27f8578f03 100644 (file)
@@ -44,7 +44,7 @@ static inline int tcf_sample_trunc_size(const struct tc_action *a)
 static inline struct psample_group *
 tcf_sample_psample_group(const struct tc_action *a)
 {
-       return rcu_dereference(to_sample(a)->psample_group);
+       return rcu_dereference_rtnl(to_sample(a)->psample_group);
 }
 
 #endif /* __NET_TC_SAMPLE_H */
index f42d300f0cfaa87520320dd287a7b4750adf7d8a..81e8ade1e6e415779e1a18b39bd2695c9b871152 100644 (file)
@@ -1709,6 +1709,11 @@ static inline struct sk_buff *tcp_rtx_queue_head(const struct sock *sk)
        return skb_rb_first(&sk->tcp_rtx_queue);
 }
 
+static inline struct sk_buff *tcp_rtx_queue_tail(const struct sock *sk)
+{
+       return skb_rb_last(&sk->tcp_rtx_queue);
+}
+
 static inline struct sk_buff *tcp_write_queue_head(const struct sock *sk)
 {
        return skb_peek(&sk->sk_write_queue);
@@ -2103,6 +2108,8 @@ struct tcp_ulp_ops {
 
        /* initialize ulp */
        int (*init)(struct sock *sk);
+       /* update ulp */
+       void (*update)(struct sock *sk, struct proto *p);
        /* cleanup ulp */
        void (*release)(struct sock *sk);
 
@@ -2114,6 +2121,7 @@ void tcp_unregister_ulp(struct tcp_ulp_ops *type);
 int tcp_set_ulp(struct sock *sk, const char *name);
 void tcp_get_available_ulp(char *buf, size_t len);
 void tcp_cleanup_ulp(struct sock *sk);
+void tcp_update_ulp(struct sock *sk, struct proto *p);
 
 #define MODULE_ALIAS_TCP_ULP(name)                             \
        __MODULE_INFO(alias, alias_userspace, name);            \
index 584609174fe007fbaea67da225363e2b91047c3b..41b2d41bb1b81a67731fc064c9dffa33b1c439e9 100644 (file)
@@ -107,9 +107,7 @@ struct tls_device {
 enum {
        TLS_BASE,
        TLS_SW,
-#ifdef CONFIG_TLS_DEVICE
        TLS_HW,
-#endif
        TLS_HW_RECORD,
        TLS_NUM_CONFIG,
 };
@@ -162,6 +160,7 @@ struct tls_sw_context_tx {
        int async_capable;
 
 #define BIT_TX_SCHEDULED       0
+#define BIT_TX_CLOSING         1
        unsigned long tx_bitmask;
 };
 
@@ -272,6 +271,8 @@ struct tls_context {
        unsigned long flags;
 
        /* cache cold stuff */
+       struct proto *sk_proto;
+
        void (*sk_destruct)(struct sock *sk);
        void (*sk_proto_close)(struct sock *sk, long timeout);
 
@@ -355,13 +356,17 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval,
                  unsigned int optlen);
 
 int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx);
+void tls_sw_strparser_arm(struct sock *sk, struct tls_context *ctx);
+void tls_sw_strparser_done(struct tls_context *tls_ctx);
 int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
 int tls_sw_sendpage(struct sock *sk, struct page *page,
                    int offset, size_t size, int flags);
-void tls_sw_close(struct sock *sk, long timeout);
-void tls_sw_free_resources_tx(struct sock *sk);
+void tls_sw_cancel_work_tx(struct tls_context *tls_ctx);
+void tls_sw_release_resources_tx(struct sock *sk);
+void tls_sw_free_ctx_tx(struct tls_context *tls_ctx);
 void tls_sw_free_resources_rx(struct sock *sk);
 void tls_sw_release_resources_rx(struct sock *sk);
+void tls_sw_free_ctx_rx(struct tls_context *tls_ctx);
 int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
                   int nonblock, int flags, int *addr_len);
 bool tls_sw_stream_read(const struct sock *sk);
index b22db30c3d887818fdd20657ef073760f902aa83..aa08a7a5f6ac5836524dd34115cd57e2675e574d 100644 (file)
@@ -983,7 +983,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
 void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
 
 struct xfrm_if_parms {
-       char name[IFNAMSIZ];    /* name of XFRM device */
        int link;               /* ifindex of underlying L2 interface */
        u32 if_id;              /* interface identifyer */
 };
@@ -991,7 +990,6 @@ struct xfrm_if_parms {
 struct xfrm_if {
        struct xfrm_if __rcu *next;     /* next interface in list */
        struct net_device *dev;         /* virtual device associated with interface */
-       struct net_device *phydev;      /* physical device */
        struct net *net;                /* netns for packet i/o */
        struct xfrm_if_parms p;         /* interface parms */
 
index c5f8a9f1706374fece3b342a3b995d9e31ca18d5..4f225175cb91ef6e43a75b29e9b51084b31db413 100644 (file)
@@ -2647,7 +2647,9 @@ struct ib_client {
                        const union ib_gid *gid,
                        const struct sockaddr *addr,
                        void *client_data);
-       struct list_head list;
+
+       refcount_t uses;
+       struct completion uses_zero;
        u32 client_id;
 
        /* kverbs are not required by the client */
index 0eeea520a85315d12cf838b52f4fbc3d6502221e..e06c77d764634a783578987c2c5143b8c6aae657 100644 (file)
@@ -608,7 +608,7 @@ static inline void rvt_qp_wqe_reserve(
 /**
  * rvt_qp_wqe_unreserve - clean reserved operation
  * @qp - the rvt qp
- * @wqe - the send wqe
+ * @flags - send wqe flags
  *
  * This decrements the reserve use count.
  *
@@ -620,11 +620,9 @@ static inline void rvt_qp_wqe_reserve(
  * the compiler does not juggle the order of the s_last
  * ring index and the decrementing of s_reserved_used.
  */
-static inline void rvt_qp_wqe_unreserve(
-       struct rvt_qp *qp,
-       struct rvt_swqe *wqe)
+static inline void rvt_qp_wqe_unreserve(struct rvt_qp *qp, int flags)
 {
-       if (unlikely(wqe->wr.send_flags & RVT_SEND_RESERVE_USED)) {
+       if (unlikely(flags & RVT_SEND_RESERVE_USED)) {
                atomic_dec(&qp->s_reserved_used);
                /* insure no compiler re-order up to s_last change */
                smp_mb__after_atomic();
@@ -853,6 +851,7 @@ rvt_qp_complete_swqe(struct rvt_qp *qp,
        u32 byte_len, last;
        int flags = wqe->wr.send_flags;
 
+       rvt_qp_wqe_unreserve(qp, flags);
        rvt_put_qp_swqe(qp, wqe);
 
        need_completion =
index b0fc6b26bdf531f8a42bf3b398d1d32b6bb6d2e2..83df1ec6664eabbffd851976093a578a5b57177a 100644 (file)
@@ -105,8 +105,7 @@ struct rdma_restrack_entry {
 };
 
 int rdma_restrack_count(struct ib_device *dev,
-                       enum rdma_restrack_type type,
-                       struct pid_namespace *ns);
+                       enum rdma_restrack_type type);
 
 void rdma_restrack_kadd(struct rdma_restrack_entry *res);
 void rdma_restrack_uadd(struct rdma_restrack_entry *res);
index 2d64b53f947cc1e58ef917725d07f4c2c96f3a7e..9b87e1a1c646a389870fa0aa75b047628e919688 100644 (file)
@@ -115,7 +115,7 @@ struct fc_disc_port {
        struct fc_lport    *lp;
        struct list_head   peers;
        struct work_struct rport_work;
-       u32                port_id;
+       u32                port_id;
 };
 
 /**
@@ -155,14 +155,14 @@ struct fc_rport_operations {
  */
 struct fc_rport_libfc_priv {
        struct fc_lport            *local_port;
-       enum fc_rport_state        rp_state;
+       enum fc_rport_state        rp_state;
        u16                        flags;
        #define FC_RP_FLAGS_REC_SUPPORTED       (1 << 0)
        #define FC_RP_FLAGS_RETRY               (1 << 1)
        #define FC_RP_STARTED                   (1 << 2)
        #define FC_RP_FLAGS_CONF_REQ            (1 << 3)
-       unsigned int               e_d_tov;
-       unsigned int               r_a_tov;
+       unsigned int               e_d_tov;
+       unsigned int               r_a_tov;
 };
 
 /**
@@ -191,24 +191,24 @@ struct fc_rport_priv {
        struct fc_lport             *local_port;
        struct fc_rport             *rport;
        struct kref                 kref;
-       enum fc_rport_state         rp_state;
+       enum fc_rport_state         rp_state;
        struct fc_rport_identifiers ids;
        u16                         flags;
-       u16                         max_seq;
+       u16                         max_seq;
        u16                         disc_id;
        u16                         maxframe_size;
-       unsigned int                retries;
-       unsigned int                major_retries;
-       unsigned int                e_d_tov;
-       unsigned int                r_a_tov;
-       struct mutex                rp_mutex;
+       unsigned int                retries;
+       unsigned int                major_retries;
+       unsigned int                e_d_tov;
+       unsigned int                r_a_tov;
+       struct mutex                rp_mutex;
        struct delayed_work         retry_work;
-       enum fc_rport_event         event;
+       enum fc_rport_event         event;
        struct fc_rport_operations  *ops;
-       struct list_head            peers;
-       struct work_struct          event_work;
+       struct list_head            peers;
+       struct work_struct          event_work;
        u32                         supported_classes;
-       u16                         prli_count;
+       u16                         prli_count;
        struct rcu_head             rcu;
        u16                         sp_features;
        u8                          spp_type;
@@ -618,12 +618,12 @@ struct libfc_function_template {
  * @disc_callback: Callback routine called when discovery completes
  */
 struct fc_disc {
-       unsigned char         retry_count;
-       unsigned char         pending;
-       unsigned char         requested;
-       unsigned short        seq_count;
-       unsigned char         buf_len;
-       u16                   disc_id;
+       unsigned char         retry_count;
+       unsigned char         pending;
+       unsigned char         requested;
+       unsigned short        seq_count;
+       unsigned char         buf_len;
+       u16                   disc_id;
 
        struct list_head      rports;
        void                  *priv;
@@ -697,7 +697,7 @@ struct fc_lport {
        struct fc_rport_priv           *ms_rdata;
        struct fc_rport_priv           *ptp_rdata;
        void                           *scsi_priv;
-       struct fc_disc                 disc;
+       struct fc_disc                 disc;
 
        /* Virtual port information */
        struct list_head               vports;
@@ -715,7 +715,7 @@ struct fc_lport {
        u8                             retry_count;
 
        /* Fabric information */
-       u32                            port_id;
+       u32                            port_id;
        u64                            wwpn;
        u64                            wwnn;
        unsigned int                   service_params;
@@ -743,11 +743,11 @@ struct fc_lport {
        struct fc_ns_fts               fcts;
 
        /* Miscellaneous */
-       struct mutex                   lp_mutex;
-       struct list_head               list;
+       struct mutex                   lp_mutex;
+       struct list_head               list;
        struct delayed_work            retry_work;
        void                           *prov[FC_FC4_PROV_SIZE];
-       struct list_head               lport_list;
+       struct list_head               lport_list;
 };
 
 /**
index c50fb297e26576bdbdcc1a6fda82f68beee6ef6d..2568cb0627ec0b388aa100391179993b603c2784 100644 (file)
@@ -31,7 +31,7 @@
  * FIP tunable parameters.
  */
 #define FCOE_CTLR_START_DELAY  2000    /* mS after first adv. to choose FCF */
-#define FCOE_CTRL_SOL_TOV      2000    /* min. solicitation interval (mS) */
+#define FCOE_CTLR_SOL_TOV      2000    /* min. solicitation interval (mS) */
 #define FCOE_CTLR_FCF_LIMIT    20      /* max. number of FCF entries */
 #define FCOE_CTLR_VN2VN_LOGIN_LIMIT 3  /* max. VN2VN rport login retries */
 
@@ -229,6 +229,7 @@ struct fcoe_fcf {
  * @vn_mac:    VN_Node assigned MAC address for data
  */
 struct fcoe_rport {
+       struct fc_rport_priv rdata;
        unsigned long time;
        u16 fcoe_len;
        u16 flags;
index 50f49e043668c0bbcac77e77645ddb99af171ff0..d1a93c73f0062f5305b39cba66264aaccb148358 100644 (file)
@@ -46,7 +46,9 @@ struct mcip_cmd {
 #define CMD_IDU_ENABLE                 0x71
 #define CMD_IDU_DISABLE                        0x72
 #define CMD_IDU_SET_MODE               0x74
+#define CMD_IDU_READ_MODE              0x75
 #define CMD_IDU_SET_DEST               0x76
+#define CMD_IDU_ACK_CIRQ               0x79
 #define CMD_IDU_SET_MASK               0x7C
 
 #define IDU_M_TRIG_LEVEL               0x0
@@ -119,4 +121,13 @@ static inline void __mcip_cmd_data(unsigned int cmd, unsigned int param,
        __mcip_cmd(cmd, param);
 }
 
+/*
+ * Read MCIP register
+ */
+static inline unsigned int __mcip_cmd_read(unsigned int cmd, unsigned int param)
+{
+       __mcip_cmd(cmd, param);
+       return read_aux_reg(ARC_REG_MCIP_READBACK);
+}
+
 #endif
index 3f9d6b6a56915602ec49c5c19651b7057df9d42d..c1036d16ed03b34517608517186fca375c8eda50 100644 (file)
@@ -259,7 +259,7 @@ static inline int qe_alive_during_sleep(void)
 
 /* Structure that defines QE firmware binary files.
  *
- * See Documentation/powerpc/qe_firmware.txt for a description of these
+ * See Documentation/powerpc/qe_firmware.rst for a description of these
  * fields.
  */
 struct qe_firmware {
index c5188ff724d1220b991e7e2c1591f8f396138796..bc88d6f964da9e64a03396381cd1d9aab190e9f1 100644 (file)
@@ -173,10 +173,7 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
        if (snd_BUG_ON(!stream))
                return;
 
-       if (stream->direction == SND_COMPRESS_PLAYBACK)
-               stream->runtime->state = SNDRV_PCM_STATE_SETUP;
-       else
-               stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+       stream->runtime->state = SNDRV_PCM_STATE_SETUP;
 
        wake_up(&stream->runtime->sleep);
 }
index 954563ee22779741d86d20885a7c4a08abb502cb..985a5f583de4c7f10cf161267cd554999dad4bf8 100644 (file)
@@ -141,6 +141,10 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
 {
        struct device *dev = simple_priv_to_dev(priv);
 
+       /* dai might be NULL */
+       if (!dai)
+               return;
+
        if (dai->name)
                dev_dbg(dev, "%s dai name = %s\n",
                        name, dai->name);
index bded69e696d4a27e528878265072b8632565142a..6080ea0facd7cdc27b03f31e802b363a06f92593 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 4bb8ee138ba7f2a88e2ebac6003b6d475cab7144..65e4c20e567cbb2c03f3e0c92c3a4463639703da 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 3d174e20aa530983c77f3554ae968e80c246c39b..5b8de1b1983c2908775a18fbd608c943327dc9bb 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 12867bbd4372ac6237219c78a042fdcee9a5cdb7..10f00c08dbb7a492a2ba4225e12a96e270ba0ffd 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 16528d2b4a504ea455e86ed904a30cbc2d6394f0..a9156b4a062c1b911bd4093c4c01597c197457e6 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 8ae3ad45bdf7ca9ebf7ce2792377925ed2390854..003879401d6336ef1a50e85cfbcfac926249a7b5 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 643f175cb479a412a976bf68b9bbc1ec553ca725..0b71b381b952e4ac396cb33b9a0b957f614cf038 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 41dcabf89899f91b3725e41e0c60f2d268358012..c47b3624092030992e3e7dc071d5c822eff3566d 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 9257d5473d97b5846664f97e949dd07b7c3861f7..fda6e8f6ead4e90dabd2bdd85c925dfd06508829 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index d25c764b10e8b4be247ee8e317e0bfaf8cdfd9c9..dd53d36b34e1c0b7200f220e10045181fe43c8b3 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 /*
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
index 2212adda8f77f7d8cb44b0bdb0b22445b1fcb87d..64e92d56c6a8fab3be92894700fea09942b206ab 100644 (file)
@@ -2,7 +2,7 @@
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM dma_fence
 
-#if !defined(_TRACE_FENCE_H) || defined(TRACE_HEADER_MULTI_READ)
+#if !defined(_TRACE_DMA_FENCE_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_DMA_FENCE_H
 
 #include <linux/tracepoint.h>
index f3a12566bed057143cbc966530f5df525043a67e..6678cf8b235b826aa0c9f5abbe7a5c5b09024ee8 100644 (file)
@@ -3,7 +3,7 @@
 #define TRACE_SYSTEM napi
 
 #if !defined(_TRACE_NAPI_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_NAPI_H_
+#define _TRACE_NAPI_H
 
 #include <linux/netdevice.h>
 #include <linux/tracepoint.h>
@@ -38,7 +38,7 @@ TRACE_EVENT(napi_poll,
 
 #undef NO_DEV
 
-#endif /* _TRACE_NAPI_H_ */
+#endif /* _TRACE_NAPI_H */
 
 /* This part must be outside protection */
 #include <trace/define_trace.h>
index 60d0d8bd336d08705f98468a87b9a31696c83941..0d1a9ebf55ba4415537a345867948a4d34b536c6 100644 (file)
@@ -2,7 +2,7 @@
 #define TRACE_SYSTEM qdisc
 
 #if !defined(_TRACE_QDISC_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_QDISC_H_
+#define _TRACE_QDISC_H
 
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -44,7 +44,7 @@ TRACE_EVENT(qdisc_dequeue,
                  __entry->txq_state, __entry->packets, __entry->skbaddr )
 );
 
-#endif /* _TRACE_QDISC_H_ */
+#endif /* _TRACE_QDISC_H */
 
 /* This part must be outside protection */
 #include <trace/define_trace.h>
index cc1d060cbf133e92460cf91f24c35babccbd9248..a13a62db356553552d0f20871075715d854ada2c 100644 (file)
 #define __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY
 
 enum rxrpc_skb_trace {
-       rxrpc_skb_rx_cleaned,
-       rxrpc_skb_rx_freed,
-       rxrpc_skb_rx_got,
-       rxrpc_skb_rx_lost,
-       rxrpc_skb_rx_purged,
-       rxrpc_skb_rx_received,
-       rxrpc_skb_rx_rotated,
-       rxrpc_skb_rx_seen,
-       rxrpc_skb_tx_cleaned,
-       rxrpc_skb_tx_freed,
-       rxrpc_skb_tx_got,
-       rxrpc_skb_tx_new,
-       rxrpc_skb_tx_rotated,
-       rxrpc_skb_tx_seen,
+       rxrpc_skb_cleaned,
+       rxrpc_skb_freed,
+       rxrpc_skb_got,
+       rxrpc_skb_lost,
+       rxrpc_skb_new,
+       rxrpc_skb_purged,
+       rxrpc_skb_received,
+       rxrpc_skb_rotated,
+       rxrpc_skb_seen,
+       rxrpc_skb_unshared,
+       rxrpc_skb_unshared_nomem,
 };
 
 enum rxrpc_local_trace {
@@ -228,20 +225,17 @@ enum rxrpc_tx_point {
  * Declare tracing information enums and their string mappings for display.
  */
 #define rxrpc_skb_traces \
-       EM(rxrpc_skb_rx_cleaned,                "Rx CLN") \
-       EM(rxrpc_skb_rx_freed,                  "Rx FRE") \
-       EM(rxrpc_skb_rx_got,                    "Rx GOT") \
-       EM(rxrpc_skb_rx_lost,                   "Rx *L*") \
-       EM(rxrpc_skb_rx_purged,                 "Rx PUR") \
-       EM(rxrpc_skb_rx_received,               "Rx RCV") \
-       EM(rxrpc_skb_rx_rotated,                "Rx ROT") \
-       EM(rxrpc_skb_rx_seen,                   "Rx SEE") \
-       EM(rxrpc_skb_tx_cleaned,                "Tx CLN") \
-       EM(rxrpc_skb_tx_freed,                  "Tx FRE") \
-       EM(rxrpc_skb_tx_got,                    "Tx GOT") \
-       EM(rxrpc_skb_tx_new,                    "Tx NEW") \
-       EM(rxrpc_skb_tx_rotated,                "Tx ROT") \
-       E_(rxrpc_skb_tx_seen,                   "Tx SEE")
+       EM(rxrpc_skb_cleaned,                   "CLN") \
+       EM(rxrpc_skb_freed,                     "FRE") \
+       EM(rxrpc_skb_got,                       "GOT") \
+       EM(rxrpc_skb_lost,                      "*L*") \
+       EM(rxrpc_skb_new,                       "NEW") \
+       EM(rxrpc_skb_purged,                    "PUR") \
+       EM(rxrpc_skb_received,                  "RCV") \
+       EM(rxrpc_skb_rotated,                   "ROT") \
+       EM(rxrpc_skb_seen,                      "SEE") \
+       EM(rxrpc_skb_unshared,                  "UNS") \
+       E_(rxrpc_skb_unshared_nomem,            "US0")
 
 #define rxrpc_local_traces \
        EM(rxrpc_local_got,                     "GOT") \
@@ -498,10 +492,10 @@ rxrpc_tx_points;
 #define E_(a, b)       { a, b }
 
 TRACE_EVENT(rxrpc_local,
-           TP_PROTO(struct rxrpc_local *local, enum rxrpc_local_trace op,
+           TP_PROTO(unsigned int local_debug_id, enum rxrpc_local_trace op,
                     int usage, const void *where),
 
-           TP_ARGS(local, op, usage, where),
+           TP_ARGS(local_debug_id, op, usage, where),
 
            TP_STRUCT__entry(
                    __field(unsigned int,       local           )
@@ -511,7 +505,7 @@ TRACE_EVENT(rxrpc_local,
                             ),
 
            TP_fast_assign(
-                   __entry->local = local->debug_id;
+                   __entry->local = local_debug_id;
                    __entry->op = op;
                    __entry->usage = usage;
                    __entry->where = where;
@@ -643,13 +637,14 @@ TRACE_EVENT(rxrpc_call,
 
 TRACE_EVENT(rxrpc_skb,
            TP_PROTO(struct sk_buff *skb, enum rxrpc_skb_trace op,
-                    int usage, int mod_count, const void *where),
+                    int usage, int mod_count, u8 flags,    const void *where),
 
-           TP_ARGS(skb, op, usage, mod_count, where),
+           TP_ARGS(skb, op, usage, mod_count, flags, where),
 
            TP_STRUCT__entry(
                    __field(struct sk_buff *,           skb             )
                    __field(enum rxrpc_skb_trace,       op              )
+                   __field(u8,                         flags           )
                    __field(int,                        usage           )
                    __field(int,                        mod_count       )
                    __field(const void *,               where           )
@@ -657,14 +652,16 @@ TRACE_EVENT(rxrpc_skb,
 
            TP_fast_assign(
                    __entry->skb = skb;
+                   __entry->flags = flags;
                    __entry->op = op;
                    __entry->usage = usage;
                    __entry->mod_count = mod_count;
                    __entry->where = where;
                           ),
 
-           TP_printk("s=%p %s u=%d m=%d p=%pSR",
+           TP_printk("s=%p %cx %s u=%d m=%d p=%pSR",
                      __entry->skb,
+                     __entry->flags & RXRPC_SKB_TX_BUFFER ? 'T' : 'R',
                      __print_symbolic(__entry->op, rxrpc_skb_traces),
                      __entry->usage,
                      __entry->mod_count,
index 0818f628611095ee10c3b873bbed81355f0f2f7b..971cd02d2dafe760107880c72f16db44ba733863 100644 (file)
@@ -1,5 +1,5 @@
 #if !defined(_TRACE_TEGRA_APB_DMA_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_TEGRA_APM_DMA_H
+#define _TRACE_TEGRA_APB_DMA_H
 
 #include <linux/tracepoint.h>
 #include <linux/dmaengine.h>
@@ -55,7 +55,7 @@ TRACE_EVENT(tegra_dma_isr,
        TP_printk("%s: irq %d\n",  __get_str(chan), __entry->irq)
 );
 
-#endif /*  _TRACE_TEGRADMA_H */
+#endif /* _TRACE_TEGRA_APB_DMA_H */
 
 /* This part must be outside protection */
 #include <trace/define_trace.h>
index 1be0e798e36218c1d1bbbf9b46b42b7deb9c9e57..1fc8faa6e97306dfa95335ecba91b3777a843aa9 100644 (file)
@@ -569,7 +569,7 @@ __SYSCALL(__NR_semget, sys_semget)
 __SC_COMP(__NR_semctl, sys_semctl, compat_sys_semctl)
 #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32
 #define __NR_semtimedop 192
-__SC_COMP(__NR_semtimedop, sys_semtimedop, sys_semtimedop_time32)
+__SC_3264(__NR_semtimedop, sys_semtimedop_time32, sys_semtimedop)
 #endif
 #define __NR_semop 193
 __SYSCALL(__NR_semop, sys_semop)
index fa1c753dcdbc7f170a65dbaa8b01683de5e6e942..a5aa7d3ac6a116a7a8d3c08d840c37a70e42e7a4 100644 (file)
@@ -1466,8 +1466,8 @@ union bpf_attr {
  *             If no cookie has been set yet, generate a new cookie. Once
  *             generated, the socket cookie remains stable for the life of the
  *             socket. This helper can be useful for monitoring per socket
- *             networking traffic statistics as it provides a unique socket
- *             identifier per namespace.
+ *             networking traffic statistics as it provides a global socket
+ *             identifier that can be assumed unique.
  *     Return
  *             A 8-byte long non-decreasing number on success, or 0 if the
  *             socket field is missing inside *skb*.
index 2ec3cc99ea4c3f2e8a116078276426e1f6a1524d..cbc1f5813f505b34739b593acf210e0f035d59da 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _UAPI_LINUX_BPFILTER_H
 #define _UAPI_LINUX_BPFILTER_H
 
index 1670f0944227e276ea7fa16e9469bb462c7cf097..782a03eb10869d1610d7edb49e44baf8d5ba1d0c 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
  * Copyright (c) 2015-2018, Intel Corporation.
  */
index 4941628a4fb9b919720d3fd9a949828f2c397fc0..5ec88e7548a9f55e19c1b90f990f2f617ca3c723 100644 (file)
@@ -16,6 +16,7 @@
 #define CAPI_MSG_BASELEN               8
 #define CAPI_DATA_B3_REQ_LEN           (CAPI_MSG_BASELEN+4+4+2+2+2)
 #define CAPI_DATA_B3_RESP_LEN          (CAPI_MSG_BASELEN+4+2)
+#define CAPI_DISCONNECT_B3_RESP_LEN    (CAPI_MSG_BASELEN+4)
 
 /*----- CAPI commands -----*/
 #define CAPI_ALERT                 0x01
index d10b832c58c58a0d8367a09b5f9dae68a1fa3647..0a52b7b093d306e5c4cb47dedcf91a9d0103eef1 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
  * Intel Speed Select Interface: OS to hardware Interface
  * Copyright (c) 2019, Intel Corporation.
index a18b719f49d4dfbbb978270f791fe992cfc8b2a9..784ba0b9690af31b0419e07e1b0cb2261bad5e68 100644 (file)
 
 #define JFFS2_ACL_VERSION              0x0001
 
-// Maybe later...
-//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
-//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
-
-
 #define JFFS2_INO_FLAG_PREREAD   1     /* Do read_inode() for this one at
                                           mount time, don't wait for it to
                                           happen later */
index 070d1bc7e725df318d2297ae671f2a34f8dd5089..20917c59f39c9a2a27bf1b62e907d5e2a31f88a6 100644 (file)
@@ -410,21 +410,6 @@ struct kfd_ioctl_unmap_memory_from_gpu_args {
        __u32 n_success;                /* to/from KFD */
 };
 
-/* Allocate GWS for specific queue
- *
- * @gpu_id:      device identifier
- * @queue_id:    queue's id that GWS is allocated for
- * @num_gws:     how many GWS to allocate
- * @first_gws:   index of the first GWS allocated.
- *               only support contiguous GWS allocation
- */
-struct kfd_ioctl_alloc_queue_gws_args {
-       __u32 gpu_id;           /* to KFD */
-       __u32 queue_id;         /* to KFD */
-       __u32 num_gws;          /* to KFD */
-       __u32 first_gws;        /* from KFD */
-};
-
 struct kfd_ioctl_get_dmabuf_info_args {
        __u64 size;             /* from KFD */
        __u64 metadata_ptr;     /* to KFD */
@@ -544,10 +529,7 @@ enum kfd_mmio_remap {
 #define AMDKFD_IOC_IMPORT_DMABUF               \
                AMDKFD_IOWR(0x1D, struct kfd_ioctl_import_dmabuf_args)
 
-#define AMDKFD_IOC_ALLOC_QUEUE_GWS             \
-               AMDKFD_IOWR(0x1E, struct kfd_ioctl_alloc_queue_gws_args)
-
 #define AMDKFD_COMMAND_START           0x01
-#define AMDKFD_COMMAND_END             0x1F
+#define AMDKFD_COMMAND_END             0x1E
 
 #endif
index a7c19540ce21e6410ed3055cb5a27419a8f5d9db..5e3f12d5359e731290e499c0733e9b6fb496158e 100644 (file)
@@ -116,7 +116,7 @@ struct kvm_irq_level {
         * ACPI gsi notion of irq.
         * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
         * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
-        * For ARM: See Documentation/virtual/kvm/api.txt
+        * For ARM: See Documentation/virt/kvm/api.txt
         */
        union {
                __u32 irq;
@@ -1086,7 +1086,7 @@ struct kvm_xen_hvm_config {
  *
  * KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
  * the irqfd to operate in resampling mode for level triggered interrupt
- * emulation.  See Documentation/virtual/kvm/api.txt.
+ * emulation.  See Documentation/virt/kvm/api.txt.
  */
 #define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
 
index 6f3791c8946f0975e901d380e2b40ac4992a3ac9..00d787f0260ece35edecfb7b29bf162ea712133b 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _NF_SYNPROXY_H
 #define _NF_SYNPROXY_H
 
index 2312f0ec07b2791ffaece0a95eebaefa727f14be..323f0dfc2a4e2403ca50b13fc46b74f4d44a779c 100644 (file)
@@ -1,4 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef _UAPI_XT_CONNLABEL_H
+#define _UAPI_XT_CONNLABEL_H
+
 #include <linux/types.h>
 
 #define XT_CONNLABEL_MAXBIT 127
@@ -11,3 +15,5 @@ struct xt_connlabel_mtinfo {
        __u16 bit;
        __u16 options;
 };
+
+#endif /* _UAPI_XT_CONNLABEL_H */
index 5c8a4d760ee3443c0292112f18852a807b037184..b5123ab8d54a8c7fd4e75d6ee00fad938c1ded81 100644 (file)
@@ -11,4 +11,9 @@ struct xt_nfacct_match_info {
        struct nf_acct  *nfacct;
 };
 
+struct xt_nfacct_match_info_v1 {
+       char            name[NFACCT_NAME_MAX];
+       struct nf_acct  *nfacct __attribute__((aligned(8)));
+};
+
 #endif /* _XT_NFACCT_MATCH_H */
index 75758ec26c8b4d81d2ee21f89c58b648d47e417f..beb9a9d0c00a5a93dc65afc156f41b80a2af4c07 100644 (file)
@@ -2863,7 +2863,7 @@ enum nl80211_attrs {
 #define NL80211_HT_CAPABILITY_LEN              26
 #define NL80211_VHT_CAPABILITY_LEN             12
 #define NL80211_HE_MIN_CAPABILITY_LEN           16
-#define NL80211_HE_MAX_CAPABILITY_LEN           51
+#define NL80211_HE_MAX_CAPABILITY_LEN           54
 #define NL80211_MAX_NR_CIPHER_SUITES           5
 #define NL80211_MAX_NR_AKM_SUITES              2
 
index 8654b2442f6a68bb362fc92f12e381b8e8974b17..592a0c1b77c93eef274bf86bf465649970a3cde6 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * Userspace interface for AMD Secure Encrypted Virtualization (SEV)
  * platform management commands.
index fd6b5f66e2c55432b05ad939477393a29659a5ac..cba368e558634ff7e7ea125487b95ac3afda2d28 100644 (file)
@@ -250,6 +250,7 @@ struct rds_info_rdma_connection {
        __u32           rdma_mr_max;
        __u32           rdma_mr_size;
        __u8            tos;
+       __u8            sl;
        __u32           cache_allocs;
 };
 
@@ -265,6 +266,7 @@ struct rds6_info_rdma_connection {
        __u32           rdma_mr_max;
        __u32           rdma_mr_size;
        __u8            tos;
+       __u8            sl;
        __u32           cache_allocs;
 };
 
index 782069dcf607ea5e6a1271a5a772b6e7f59e8853..4accfa7e266dcf1309e21a62118ae099c91a7119 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
 /* Types and definitions for AF_RXRPC.
  *
  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
index 5642c05e0da04ca37752aaa5e66e207b22f78af7..3cc3af1c2ee1f635fa751efca0377180183b9b93 100644 (file)
 
 #define PORT_PNX8XXX   70
 
-/* Hilscher netx */
-#define PORT_NETX      71
-
 /* SUN4V Hypervisor Console */
 #define PORT_SUNHV     72
 
index 8eb96021709c8c3ed15f53e7295a6c92dfe77010..c3409c8ec0ddd10de38c1a1e7742dff563ec8b71 100644 (file)
@@ -6,17 +6,24 @@
  * Desired design of maximum size and alignment (see RFC2553)
  */
 #define _K_SS_MAXSIZE  128     /* Implementation specific max size */
-#define _K_SS_ALIGNSIZE        (__alignof__ (struct sockaddr *))
-                               /* Implementation specific desired alignment */
 
 typedef unsigned short __kernel_sa_family_t;
 
+/*
+ * The definition uses anonymous union and struct in order to control the
+ * default alignment.
+ */
 struct __kernel_sockaddr_storage {
-       __kernel_sa_family_t    ss_family;              /* address family */
-       /* Following field(s) are implementation specific */
-       char            __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
+       union {
+               struct {
+                       __kernel_sa_family_t    ss_family; /* address family */
+                       /* Following field(s) are implementation specific */
+                       char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
                                /* space to achieve desired size, */
                                /* _SS_MAXSIZE value minus size of ss_family */
-} __attribute__ ((aligned(_K_SS_ALIGNSIZE)));  /* force desired alignment */
+               };
+               void *__align; /* implementation specific desired alignment */
+       };
+};
 
 #endif /* _UAPI_LINUX_SOCKET_H */
index 3c9ee3020cbbeeff50262703f0d7d13e2fa4be58..652f169a019e7d241a8468a1f02bb6c448b4450d 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
 /*
  * g_uvc.h  --  USB Video Class Gadget driver API
  *
index 26f39816af14c149ab1d8be5842112f4bf36c18c..c27289fd619a4114dc39261ddaad8b774c847795 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 OR CDDL-1.0) */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR CDDL-1.0) */
 /*
  * Virtual Device for Guest <-> VMM/Host communication, type definitions
  * which are also used for the vboxguest ioctl interface / by vboxsf
index 612f0c7d355890a63a14127eaea105c1f97bc39e..9cec58a6a5eaa7cfbb5eb28e00ffe19fc63b4032 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 OR CDDL-1.0) */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR CDDL-1.0) */
 /*
  * VBoxGuest - VirtualBox Guest Additions Driver Interface.
  *
index 9d9705ceda768b3e107ecb92a5837204d3d9c4a1..2427bc4d8eba14862e239296c427c3b43a64b652 100644 (file)
@@ -518,7 +518,13 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_RGBX444 v4l2_fourcc('R', 'X', '1', '2') /* 16  rrrrgggg bbbbxxxx */
 #define V4L2_PIX_FMT_ABGR444 v4l2_fourcc('A', 'B', '1', '2') /* 16  aaaabbbb ggggrrrr */
 #define V4L2_PIX_FMT_XBGR444 v4l2_fourcc('X', 'B', '1', '2') /* 16  xxxxbbbb ggggrrrr */
-#define V4L2_PIX_FMT_BGRA444 v4l2_fourcc('B', 'A', '1', '2') /* 16  bbbbgggg rrrraaaa */
+
+/*
+ * Originally this had 'BA12' as fourcc, but this clashed with the older
+ * V4L2_PIX_FMT_SGRBG12 which inexplicably used that same fourcc.
+ * So use 'GA12' instead for V4L2_PIX_FMT_BGRA444.
+ */
+#define V4L2_PIX_FMT_BGRA444 v4l2_fourcc('G', 'A', '1', '2') /* 16  bbbbgggg rrrraaaa */
 #define V4L2_PIX_FMT_BGRX444 v4l2_fourcc('B', 'X', '1', '2') /* 16  bbbbgggg rrrrxxxx */
 #define V4L2_PIX_FMT_RGB555  v4l2_fourcc('R', 'G', 'B', 'O') /* 16  RGB-5-5-5     */
 #define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16  ARGB-1-5-5-5  */
index ba1b460c9944df383b505ed230a8e611483ace75..237e36a280cb636fe053676438ddb80c3383af48 100644 (file)
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause */
 /*
- * Virtio-iommu definition v0.9
+ * Virtio-iommu definition v0.12
  *
- * Copyright (C) 2018 Arm Ltd.
+ * Copyright (C) 2019 Arm Ltd.
  */
 #ifndef _UAPI_LINUX_VIRTIO_IOMMU_H
 #define _UAPI_LINUX_VIRTIO_IOMMU_H
 
 /* Feature bits */
 #define VIRTIO_IOMMU_F_INPUT_RANGE             0
-#define VIRTIO_IOMMU_F_DOMAIN_BITS             1
+#define VIRTIO_IOMMU_F_DOMAIN_RANGE            1
 #define VIRTIO_IOMMU_F_MAP_UNMAP               2
 #define VIRTIO_IOMMU_F_BYPASS                  3
 #define VIRTIO_IOMMU_F_PROBE                   4
+#define VIRTIO_IOMMU_F_MMIO                    5
 
-struct virtio_iommu_range {
-       __u64                                   start;
-       __u64                                   end;
+struct virtio_iommu_range_64 {
+       __le64                                  start;
+       __le64                                  end;
+};
+
+struct virtio_iommu_range_32 {
+       __le32                                  start;
+       __le32                                  end;
 };
 
 struct virtio_iommu_config {
        /* Supported page sizes */
-       __u64                                   page_size_mask;
+       __le64                                  page_size_mask;
        /* Supported IOVA range */
-       struct virtio_iommu_range               input_range;
+       struct virtio_iommu_range_64            input_range;
        /* Max domain ID size */
-       __u8                                    domain_bits;
-       __u8                                    padding[3];
+       struct virtio_iommu_range_32            domain_range;
        /* Probe buffer size */
-       __u32                                   probe_size;
+       __le32                                  probe_size;
 };
 
 /* Request types */
@@ -49,6 +54,7 @@ struct virtio_iommu_config {
 #define VIRTIO_IOMMU_S_RANGE                   0x05
 #define VIRTIO_IOMMU_S_NOENT                   0x06
 #define VIRTIO_IOMMU_S_FAULT                   0x07
+#define VIRTIO_IOMMU_S_NOMEM                   0x08
 
 struct virtio_iommu_req_head {
        __u8                                    type;
@@ -78,12 +84,10 @@ struct virtio_iommu_req_detach {
 
 #define VIRTIO_IOMMU_MAP_F_READ                        (1 << 0)
 #define VIRTIO_IOMMU_MAP_F_WRITE               (1 << 1)
-#define VIRTIO_IOMMU_MAP_F_EXEC                        (1 << 2)
-#define VIRTIO_IOMMU_MAP_F_MMIO                        (1 << 3)
+#define VIRTIO_IOMMU_MAP_F_MMIO                        (1 << 2)
 
 #define VIRTIO_IOMMU_MAP_F_MASK                        (VIRTIO_IOMMU_MAP_F_READ |      \
                                                 VIRTIO_IOMMU_MAP_F_WRITE |     \
-                                                VIRTIO_IOMMU_MAP_F_EXEC |      \
                                                 VIRTIO_IOMMU_MAP_F_MMIO)
 
 struct virtio_iommu_req_map {
index 9a63ed6d062f4870dd70d265e12d4c69be0d1198..b022787ffb94be9bdcaa36a1e4433921fa27b358 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */
 /*
  * Definitions for virtio-pmem devices.
  *
index 022619668e0e9aaf81f0029694c46e2fdbf18e20..3e9da91866ffd38d94c658918193d9c0cd3cae2e 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _UAPI_VMCORE_H
 #define _UAPI_VMCORE_H
 
index c36f2d7675a4907ccab2d1509af0ac8d142e1c56..7085c5dca9fadfc4262a36d22e0b62f9f14ff292 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  *  User API methods for ACPI-WMI mapping driver
  *
index 6d701af9fc426689dbf605fc356677d2192d005c..fb792e882ceffb0e2ad22f5ba04abf40943fa178 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 
 #ifndef __QCOM_FASTRPC_H__
 #define __QCOM_FASTRPC_H__
index 7328293c715cfb0559d841c228083ae4f5bb99ac..7c05a02d2be522cf571c0ce75205acbcb6c32fa4 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
 
 /*
  * This file contains defines, structures, etc. that are used
index 3dd8071ace7b3396d4df2f4d2bbd1d44e8f77511..af735f55b2911208077ad70d2e83e750125001e0 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
+/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) or BSD-3-Clause */
 
 /* Authors: Bernard Metzler <bmt@zurich.ibm.com> */
 /* Copyright (c) 2008-2019, IBM Corporation */
@@ -180,6 +180,7 @@ struct siw_cqe {
  * to control CQ arming.
  */
 struct siw_cq_ctrl {
-       __aligned_u64 notify;
+       __u32 flags;
+       __u32 pad;
 };
 #endif
index 17c7abd0803a83d14c8b20e8a2d48e9e8a0a4782..9988db6ad244fa9bccc40841081d4c81f89915fd 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
  * UFS Transport SGIO v4 BSG Message Support
  *
index f39352cef38223e4b1b5ab70693ca3deb5eee451..9eee32f5e4077da55768f85f0ad90075abfbe906 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 /*
  * skl-tplg-interface.h - Intel DSP FW private data interface
  *
index 1afca973eb0972ee127e75bbac9fbb142ab6faed..e9f697467a8611ad7441d5f1219913bc2de7a97c 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __INCLUDE_UAPI_SOF_FW_H__
 #define __INCLUDE_UAPI_SOF_FW_H__
 
+#include <linux/types.h>
+
 #define SND_SOF_FW_SIG_SIZE    4
 #define SND_SOF_FW_ABI         1
 #define SND_SOF_FW_SIG         "Reef"
@@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type {
 
 struct snd_sof_blk_hdr {
        enum snd_sof_fw_blk_type type;
-       uint32_t size;          /* bytes minus this header */
-       uint32_t offset;        /* offset from base */
+       __u32 size;             /* bytes minus this header */
+       __u32 offset;           /* offset from base */
 } __packed;
 
 /*
@@ -61,8 +63,8 @@ enum snd_sof_fw_mod_type {
 
 struct snd_sof_mod_hdr {
        enum snd_sof_fw_mod_type type;
-       uint32_t size;          /* bytes minus this header */
-       uint32_t num_blocks;    /* number of blocks */
+       __u32 size;             /* bytes minus this header */
+       __u32 num_blocks;       /* number of blocks */
 } __packed;
 
 /*
@@ -70,9 +72,9 @@ struct snd_sof_mod_hdr {
  */
 struct snd_sof_fw_header {
        unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */
-       uint32_t file_size;     /* size of file minus this header */
-       uint32_t num_modules;   /* number of modules */
-       uint32_t abi;           /* version of header format */
+       __u32 file_size;        /* size of file minus this header */
+       __u32 num_modules;      /* number of modules */
+       __u32 abi;              /* version of header format */
 } __packed;
 
 #endif
index 7868990b0d6f34a9bf3613b98281fde8792ec0b3..5f4518e7a972347c121784b8bc7d9194201267fa 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
 #define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
 
+#include <linux/types.h>
+
 /*
  * Header for all non IPC ABI data.
  *
  * Used by any bespoke component data structures or binary blobs.
  */
 struct sof_abi_hdr {
-       uint32_t magic;         /**< 'S', 'O', 'F', '\0' */
-       uint32_t type;          /**< component specific type */
-       uint32_t size;          /**< size in bytes of data excl. this struct */
-       uint32_t abi;           /**< SOF ABI version */
-       uint32_t reserved[4];   /**< reserved for future use */
-       uint32_t data[0];       /**< Component data - opaque to core */
+       __u32 magic;            /**< 'S', 'O', 'F', '\0' */
+       __u32 type;             /**< component specific type */
+       __u32 size;             /**< size in bytes of data excl. this struct */
+       __u32 abi;              /**< SOF ABI version */
+       __u32 reserved[4];      /**< reserved for future use */
+       __u32 data[0];          /**< Component data - opaque to core */
 }  __packed;
 
 #endif
index 4969817124a8d7c6b462aeb18f54105d1d49e2e3..98b30c1613b28031c27a35990510a2bafc0697c4 100644 (file)
@@ -109,6 +109,9 @@ static inline int xen_xlate_unmap_gfn_range(struct vm_area_struct *vma,
 }
 #endif
 
+int xen_remap_vma_range(struct vm_area_struct *vma, unsigned long addr,
+                       unsigned long len);
+
 /*
  * xen_remap_domain_gfn_array() - map an array of foreign frames by gfn
  * @vma:     VMA to map the pages into
index 0fcf8e719b7647fe7e59141c153b2485c95c4399..5766c61aed0e538f2b255480c28e8b41333736af 100644 (file)
@@ -276,29 +276,7 @@ static inline int compat_ipc_parse_version(int *cmd)
        *cmd &= ~IPC_64;
        return version;
 }
-#endif
 
-/* for __ARCH_WANT_SYS_IPC */
-long ksys_semtimedop(int semid, struct sembuf __user *tsops,
-                    unsigned int nsops,
-                    const struct __kernel_timespec __user *timeout);
-long ksys_semget(key_t key, int nsems, int semflg);
-long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);
-long ksys_msgget(key_t key, int msgflg);
-long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
-long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
-                long msgtyp, int msgflg);
-long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz,
-                int msgflg);
-long ksys_shmget(key_t key, size_t size, int shmflg);
-long ksys_shmdt(char __user *shmaddr);
-long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
-
-/* for CONFIG_ARCH_WANT_OLD_COMPAT_IPC */
-long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
-                           unsigned int nsops,
-                           const struct old_timespec32 __user *timeout);
-#ifdef CONFIG_COMPAT
 long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg);
 long compat_ksys_old_msgctl(int msqid, int cmd, void __user *uptr);
 long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
@@ -306,6 +284,7 @@ long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
 long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp,
                       compat_ssize_t msgsz, int msgflg);
 long compat_ksys_old_shmctl(int shmid, int cmd, void __user *uptr);
-#endif /* CONFIG_COMPAT */
+
+#endif
 
 #endif
index fc020c09b7e8f46f8995c9868e932d6052d353fc..deff972174967c55eab3cdaeec5b1e10903e290a 100644 (file)
@@ -35,10 +35,10 @@ config PREEMPT_VOLUNTARY
 
          Select this if you are building a kernel for a desktop system.
 
-config PREEMPT_LL
+config PREEMPT
        bool "Preemptible Kernel (Low-Latency Desktop)"
        depends on !ARCH_NO_PREEMPT
-       select PREEMPT
+       select PREEMPTION
        select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK
        help
          This option reduces the latency of the kernel by making
@@ -58,7 +58,7 @@ config PREEMPT_LL
 config PREEMPT_RT
        bool "Fully Preemptible Kernel (Real-Time)"
        depends on EXPERT && ARCH_SUPPORTS_RT
-       select PREEMPT
+       select PREEMPTION
        help
          This option turns the kernel into a real-time kernel by replacing
          various locking primitives (spinlocks, rwlocks, etc.) with
@@ -77,6 +77,6 @@ endchoice
 config PREEMPT_COUNT
        bool
 
-config PREEMPT
+config PREEMPTION
        bool
        select PREEMPT_COUNT
index a8d923b5481ba91d3cb15209eda7838fe1793ead..ef0d95a190b4179848c52041f2d1cfb6b9fbff77 100644 (file)
@@ -111,7 +111,6 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
 obj-$(CONFIG_TORTURE_TEST) += torture.o
 
 obj-$(CONFIG_HAS_IOMEM) += iomem.o
-obj-$(CONFIG_ZONE_DEVICE) += memremap.o
 obj-$(CONFIG_RSEQ) += rseq.o
 
 obj-$(CONFIG_GCC_PLUGIN_STACKLEAK) += stackleak.o
index 8191a7db27776d6eb7eade68a0458927c2b82c96..66088a9e9b9e220b9b823999d4cc9b022e203c5f 100644 (file)
@@ -890,7 +890,8 @@ int bpf_jit_get_func_addr(const struct bpf_prog *prog,
 
 static int bpf_jit_blind_insn(const struct bpf_insn *from,
                              const struct bpf_insn *aux,
-                             struct bpf_insn *to_buff)
+                             struct bpf_insn *to_buff,
+                             bool emit_zext)
 {
        struct bpf_insn *to = to_buff;
        u32 imm_rnd = get_random_int();
@@ -1005,6 +1006,8 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from,
        case 0: /* Part 2 of BPF_LD | BPF_IMM | BPF_DW. */
                *to++ = BPF_ALU32_IMM(BPF_MOV, BPF_REG_AX, imm_rnd ^ aux[0].imm);
                *to++ = BPF_ALU32_IMM(BPF_XOR, BPF_REG_AX, imm_rnd);
+               if (emit_zext)
+                       *to++ = BPF_ZEXT_REG(BPF_REG_AX);
                *to++ = BPF_ALU64_REG(BPF_OR,  aux[0].dst_reg, BPF_REG_AX);
                break;
 
@@ -1088,7 +1091,8 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
                    insn[1].code == 0)
                        memcpy(aux, insn, sizeof(aux));
 
-               rewritten = bpf_jit_blind_insn(insn, aux, insn_buff);
+               rewritten = bpf_jit_blind_insn(insn, aux, insn_buff,
+                                               clone->aux->verifier_zext);
                if (!rewritten)
                        continue;
 
index 5d141f16f6fa95dd21fbacdc6000521d26a394c0..272071e9112f3bc7ccfb111fc734238f9561ffde 100644 (file)
@@ -1707,20 +1707,26 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
        if (err)
                goto free_used_maps;
 
-       err = bpf_prog_new_fd(prog);
-       if (err < 0) {
-               /* failed to allocate fd.
-                * bpf_prog_put() is needed because the above
-                * bpf_prog_alloc_id() has published the prog
-                * to the userspace and the userspace may
-                * have refcnt-ed it through BPF_PROG_GET_FD_BY_ID.
-                */
-               bpf_prog_put(prog);
-               return err;
-       }
-
+       /* Upon success of bpf_prog_alloc_id(), the BPF prog is
+        * effectively publicly exposed. However, retrieving via
+        * bpf_prog_get_fd_by_id() will take another reference,
+        * therefore it cannot be gone underneath us.
+        *
+        * Only for the time /after/ successful bpf_prog_new_fd()
+        * and before returning to userspace, we might just hold
+        * one reference and any parallel close on that fd could
+        * rip everything out. Hence, below notifications must
+        * happen before bpf_prog_new_fd().
+        *
+        * Also, any failure handling from this point onwards must
+        * be using bpf_prog_put() given the program is exposed.
+        */
        bpf_prog_kallsyms_add(prog);
        perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
+
+       err = bpf_prog_new_fd(prog);
+       if (err < 0)
+               bpf_prog_put(prog);
        return err;
 
 free_used_maps:
index 5900cbb966b17adb04538e887b2f2eff658ba823..c36a719fee6d34a18af09ac4d1e7d0b8c58d377f 100644 (file)
@@ -985,9 +985,6 @@ static void __mark_reg_unbounded(struct bpf_reg_state *reg)
        reg->smax_value = S64_MAX;
        reg->umin_value = 0;
        reg->umax_value = U64_MAX;
-
-       /* constant backtracking is enabled for root only for now */
-       reg->precise = capable(CAP_SYS_ADMIN) ? false : true;
 }
 
 /* Mark a register as having a completely unknown (scalar) value. */
@@ -1014,7 +1011,11 @@ static void mark_reg_unknown(struct bpf_verifier_env *env,
                        __mark_reg_not_init(regs + regno);
                return;
        }
-       __mark_reg_unknown(regs + regno);
+       regs += regno;
+       __mark_reg_unknown(regs);
+       /* constant backtracking is enabled for root without bpf2bpf calls */
+       regs->precise = env->subprog_cnt > 1 || !env->allow_ptr_leaks ?
+                       true : false;
 }
 
 static void __mark_reg_not_init(struct bpf_reg_state *reg)
@@ -1771,16 +1772,21 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
                bitmap_from_u64(mask, stack_mask);
                for_each_set_bit(i, mask, 64) {
                        if (i >= func->allocated_stack / BPF_REG_SIZE) {
-                               /* This can happen if backtracking
-                                * is propagating stack precision where
-                                * caller has larger stack frame
-                                * than callee, but backtrack_insn() should
-                                * have returned -ENOTSUPP.
+                               /* the sequence of instructions:
+                                * 2: (bf) r3 = r10
+                                * 3: (7b) *(u64 *)(r3 -8) = r0
+                                * 4: (79) r4 = *(u64 *)(r10 -8)
+                                * doesn't contain jmps. It's backtracked
+                                * as a single block.
+                                * During backtracking insn 3 is not recognized as
+                                * stack access, so at the end of backtracking
+                                * stack slot fp-8 is still marked in stack_mask.
+                                * However the parent state may not have accessed
+                                * fp-8 and it's "unallocated" stack space.
+                                * In such case fallback to conservative.
                                 */
-                               verbose(env, "BUG spi %d stack_size %d\n",
-                                       i, func->allocated_stack);
-                               WARN_ONCE(1, "verifier backtracking bug");
-                               return -EFAULT;
+                               mark_all_scalars_precise(env, st);
+                               return 0;
                        }
 
                        if (func->stack[i].slot_type[0] != STACK_SPILL) {
@@ -8616,8 +8622,8 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
                }
 
                if (is_narrower_load && size < target_size) {
-                       u8 shift = (off & (size_default - 1)) * 8;
-
+                       u8 shift = bpf_ctx_narrow_load_shift(off, size,
+                                                            size_default);
                        if (ctx_field_size <= 4) {
                                if (shift)
                                        insn_buf[cnt++] = BPF_ALU32_IMM(BPF_RSH,
index 753afbca549fdaeba9c133c192c1927d1d9c6f3c..8be1da1ebd9a4f3d4ee3f6038a85e18e8d5fa685 100644 (file)
@@ -5255,8 +5255,16 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
         * if the parent has to be frozen, the child has too.
         */
        cgrp->freezer.e_freeze = parent->freezer.e_freeze;
-       if (cgrp->freezer.e_freeze)
+       if (cgrp->freezer.e_freeze) {
+               /*
+                * Set the CGRP_FREEZE flag, so when a process will be
+                * attached to the child cgroup, it will become frozen.
+                * At this point the new cgroup is unpopulated, so we can
+                * consider it frozen immediately.
+                */
+               set_bit(CGRP_FREEZE, &cgrp->flags);
                set_bit(CGRP_FROZEN, &cgrp->flags);
+       }
 
        spin_lock_irq(&css_set_lock);
        for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp)) {
index b062425ccf8da3d6a6c79d539297e30ebd70050d..c09ea4c995e104b2ed0dd62b5ab010d4b255dc91 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * kernel/configs.c
  * Echo the kernel .config file used to build the kernel
@@ -6,21 +7,6 @@
  * Copyright (C) 2002 Randy Dunlap <rdunlap@xenotime.net>
  * Copyright (C) 2002 Al Stone <ahs3@fc.hp.com>
  * Copyright (C) 2002 Hewlett-Packard Company
- *
- * 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; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/kernel.h>
index f9a0ce66c9c3e125393f011be7d55a322785ed2e..c0a4c12d38b20ed80254c76acb28c6d060b1df86 100644 (file)
@@ -144,7 +144,10 @@ void __put_cred(struct cred *cred)
        BUG_ON(cred == current->cred);
        BUG_ON(cred == current->real_cred);
 
-       call_rcu(&cred->rcu, put_cred_rcu);
+       if (cred->non_rcu)
+               put_cred_rcu(&cred->rcu);
+       else
+               call_rcu(&cred->rcu, put_cred_rcu);
 }
 EXPORT_SYMBOL(__put_cred);
 
@@ -261,6 +264,7 @@ struct cred *prepare_creds(void)
        old = task->cred;
        memcpy(new, old, sizeof(struct cred));
 
+       new->non_rcu = 0;
        atomic_set(&new->usage, 1);
        set_cred_subscribers(new, 0);
        get_group_info(new->group_info);
@@ -544,7 +548,19 @@ const struct cred *override_creds(const struct cred *new)
 
        validate_creds(old);
        validate_creds(new);
-       get_cred(new);
+
+       /*
+        * NOTE! This uses 'get_new_cred()' rather than 'get_cred()'.
+        *
+        * That means that we do not clear the 'non_rcu' flag, since
+        * we are only installing the cred into the thread-synchronous
+        * '->cred' pointer, not the '->real_cred' pointer that is
+        * visible to other threads under RCU.
+        *
+        * Also note that we did validate_creds() manually, not depending
+        * on the validation in 'get_cred()'.
+        */
+       get_new_cred((struct cred *)new);
        alter_cred_subscribers(new, 1);
        rcu_assign_pointer(current->cred, new);
        alter_cred_subscribers(old, -1);
@@ -681,6 +697,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
        validate_creds(old);
 
        *new = *old;
+       new->non_rcu = 0;
        atomic_set(&new->usage, 1);
        set_cred_subscribers(new, 0);
        get_uid(new->user);
index bfc0c17f2a3d411fcdee446f8aeeb0c1be0f681e..69cfb4345388c3f55a9ebef8df15fe9794bc7269 100644 (file)
@@ -230,9 +230,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
  */
 struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
 {
-       int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
-       size_t count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-       size_t align = get_order(PAGE_ALIGN(size));
+       size_t count = size >> PAGE_SHIFT;
        struct page *page = NULL;
        struct cma *cma = NULL;
 
@@ -243,13 +241,12 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
 
        /* CMA can be used only in the context which permits sleeping */
        if (cma && gfpflags_allow_blocking(gfp)) {
-               align = min_t(size_t, align, CONFIG_CMA_ALIGNMENT);
-               page = cma_alloc(cma, count, align, gfp & __GFP_NOWARN);
+               size_t align = get_order(size);
+               size_t cma_align = min_t(size_t, align, CONFIG_CMA_ALIGNMENT);
+
+               page = cma_alloc(cma, count, cma_align, gfp & __GFP_NOWARN);
        }
 
-       /* Fallback allocation of normal pages */
-       if (!page)
-               page = alloc_pages_node(node, gfp, align);
        return page;
 }
 
@@ -266,7 +263,8 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
  */
 void dma_free_contiguous(struct device *dev, struct page *page, size_t size)
 {
-       if (!cma_release(dev_get_cma_area(dev), page, size >> PAGE_SHIFT))
+       if (!cma_release(dev_get_cma_area(dev), page,
+                        PAGE_ALIGN(size) >> PAGE_SHIFT))
                __free_pages(page, get_order(size));
 }
 
index 59bdceea3737a4a095555723f4a7b79fda15c048..706113c6bebc3d984d0e5abe4acf83519cbec13b 100644 (file)
@@ -47,9 +47,6 @@ u64 dma_direct_get_required_mask(struct device *dev)
 {
        u64 max_dma = phys_to_dma_direct(dev, (max_pfn - 1) << PAGE_SHIFT);
 
-       if (dev->bus_dma_mask && dev->bus_dma_mask < max_dma)
-               max_dma = dev->bus_dma_mask;
-
        return (1ULL << (fls64(max_dma) - 1)) * 2 - 1;
 }
 
@@ -88,6 +85,8 @@ static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
 struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
                dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
 {
+       size_t alloc_size = PAGE_ALIGN(size);
+       int node = dev_to_node(dev);
        struct page *page = NULL;
        u64 phys_mask;
 
@@ -98,8 +97,14 @@ struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
        gfp &= ~__GFP_ZERO;
        gfp |= __dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
                        &phys_mask);
+       page = dma_alloc_contiguous(dev, alloc_size, gfp);
+       if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
+               dma_free_contiguous(dev, page, alloc_size);
+               page = NULL;
+       }
 again:
-       page = dma_alloc_contiguous(dev, size, gfp);
+       if (!page)
+               page = alloc_pages_node(node, gfp, get_order(alloc_size));
        if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
                dma_free_contiguous(dev, page, size);
                page = NULL;
@@ -130,10 +135,12 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
        if (!page)
                return NULL;
 
-       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+       if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+           !force_dma_unencrypted(dev)) {
                /* remove any dirty cache lines on the kernel alias */
                if (!PageHighMem(page))
                        arch_dma_prep_coherent(page, size);
+               *dma_handle = phys_to_dma(dev, page_to_phys(page));
                /* return the page pointer as the opaque cookie */
                return page;
        }
@@ -178,7 +185,8 @@ void dma_direct_free_pages(struct device *dev, size_t size, void *cpu_addr,
 {
        unsigned int page_order = get_order(size);
 
-       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+       if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+           !force_dma_unencrypted(dev)) {
                /* cpu_addr is a struct page cookie, not a kernel address */
                __dma_direct_free_pages(dev, size, cpu_addr);
                return;
index 1f628e7ac7097ab40e577904a91f26fce28610b8..b0038ca3aa92b2e9d4a7976a08237deb2c2c7531 100644 (file)
@@ -116,11 +116,16 @@ int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
        int ret;
 
        if (!dev_is_dma_coherent(dev)) {
+               unsigned long pfn;
+
                if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
                        return -ENXIO;
 
-               page = pfn_to_page(arch_dma_coherent_to_pfn(dev, cpu_addr,
-                               dma_addr));
+               /* If the PFN is not valid, we do not have a struct page */
+               pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
+               if (!pfn_valid(pfn))
+                       return -ENXIO;
+               page = pfn_to_page(pfn);
        } else {
                page = virt_to_page(cpu_addr);
        }
@@ -145,6 +150,23 @@ int dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt,
 }
 EXPORT_SYMBOL(dma_get_sgtable_attrs);
 
+#ifdef CONFIG_MMU
+/*
+ * Return the page attributes used for mapping dma_alloc_* memory, either in
+ * kernel space if remapping is needed, or to userspace through dma_mmap_*.
+ */
+pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs)
+{
+       if (dev_is_dma_coherent(dev) ||
+           (IS_ENABLED(CONFIG_DMA_NONCOHERENT_CACHE_SYNC) &&
+             (attrs & DMA_ATTR_NON_CONSISTENT)))
+               return prot;
+       if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_MMAP_PGPROT))
+               return arch_dma_mmap_pgprot(dev, prot, attrs);
+       return pgprot_noncached(prot);
+}
+#endif /* CONFIG_MMU */
+
 /*
  * Create userspace mapping for the DMA-coherent memory.
  */
@@ -159,7 +181,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
        unsigned long pfn;
        int ret = -ENXIO;
 
-       vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs);
+       vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);
 
        if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
                return ret;
@@ -170,7 +192,11 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
        if (!dev_is_dma_coherent(dev)) {
                if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
                        return -ENXIO;
+
+               /* If the PFN is not valid, we do not have a struct page */
                pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
+               if (!pfn_valid(pfn))
+                       return -ENXIO;
        } else {
                pfn = page_to_pfn(virt_to_page(cpu_addr));
        }
index a594aec07882d9a0ad4d482d00afb81e4daa3189..ffe78f0b2fe47c442330ee8de67cb11e230b0ae0 100644 (file)
@@ -218,7 +218,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 
        /* create a coherent mapping */
        ret = dma_common_contiguous_remap(page, size, VM_USERMAP,
-                       arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs),
+                       dma_pgprot(dev, PAGE_KERNEL, attrs),
                        __builtin_return_address(0));
        if (!ret) {
                __dma_direct_free_pages(dev, size, page);
index 026a14541a38223669a021585f0539e9d45f7628..0463c1151baebb612b617cbf3b189fdde1990d28 100644 (file)
@@ -11274,7 +11274,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
                goto err_unlock;
        }
 
-       perf_install_in_context(ctx, event, cpu);
+       perf_install_in_context(ctx, event, event->cpu);
        perf_unpin_context(ctx);
        mutex_unlock(&ctx->mutex);
 
index c5cd852fe86bb4e6eda1466330d7d6ea5f5a5fac..3cc8416ec844a46cb967becb21de903bc019824f 100644 (file)
@@ -413,7 +413,7 @@ static int hw_breakpoint_parse(struct perf_event *bp,
 
 int register_perf_hw_breakpoint(struct perf_event *bp)
 {
-       struct arch_hw_breakpoint hw;
+       struct arch_hw_breakpoint hw = { };
        int err;
 
        err = reserve_bp_slot(bp);
@@ -461,7 +461,7 @@ int
 modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *attr,
                                bool check)
 {
-       struct arch_hw_breakpoint hw;
+       struct arch_hw_breakpoint hw = { };
        int err;
 
        err = hw_breakpoint_parse(bp, attr, &hw);
index a75b6a7f458a7287439e40f0ac102fbb8b61e4a4..5b4a5dcce8f8328dd173ead148f4dc6a5fa0d8c4 100644 (file)
@@ -720,6 +720,7 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
        if (group_dead)
                kill_orphaned_pgrp(tsk->group_leader, NULL);
 
+       tsk->exit_state = EXIT_ZOMBIE;
        if (unlikely(tsk->ptrace)) {
                int sig = thread_group_leader(tsk) &&
                                thread_group_empty(tsk) &&
@@ -733,9 +734,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
                autoreap = true;
        }
 
-       tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE;
-       if (tsk->exit_state == EXIT_DEAD)
+       if (autoreap) {
+               tsk->exit_state = EXIT_DEAD;
                list_add(&tsk->ptrace_entry, &dead);
+       }
 
        /* mt-exec, de_thread() is waiting for group leader */
        if (unlikely(tsk->signal->notify_count < 0))
index d8ae0f1b4148023c8c0d242b799039deb362ca09..541fd805fb8882f93ac104f9020ee90adc78dd6b 100644 (file)
@@ -726,7 +726,7 @@ void __put_task_struct(struct task_struct *tsk)
        WARN_ON(tsk == current);
 
        cgroup_free(tsk);
-       task_numa_free(tsk);
+       task_numa_free(tsk, true);
        security_task_free(tsk);
        exit_creds(tsk);
        delayacct_tsk_free(tsk);
@@ -2338,6 +2338,8 @@ struct mm_struct *copy_init_mm(void)
  *
  * It copies the process, and if successful kick-starts
  * it and waits for it to finish using the VM if required.
+ *
+ * args->exit_signal is expected to be checked for sanity by the caller.
  */
 long _do_fork(struct kernel_clone_args *args)
 {
@@ -2562,6 +2564,14 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
        if (copy_from_user(&args, uargs, size))
                return -EFAULT;
 
+       /*
+        * Verify that higher 32bits of exit_signal are unset and that
+        * it is a valid signal
+        */
+       if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+                    !valid_signal(args.exit_signal)))
+               return -EINVAL;
+
        *kargs = (struct kernel_clone_args){
                .flags          = args.flags,
                .pidfd          = u64_to_user_ptr(args.pidfd),
index 4352b08ae48dec41f3ec678cd6938fc2e8bb2b3a..6fef48033f9686997bc455d79e2a76899746fc93 100644 (file)
@@ -251,11 +251,9 @@ irq_create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd)
         * Determine the number of vectors which need interrupt affinities
         * assigned. If the pre/post request exhausts the available vectors
         * then nothing to do here except for invoking the calc_sets()
-        * callback so the device driver can adjust to the situation. If there
-        * is only a single vector, then managing the queue is pointless as
-        * well.
+        * callback so the device driver can adjust to the situation.
         */
-       if (nvecs > 1 && nvecs > affd->pre_vectors + affd->post_vectors)
+       if (nvecs > affd->pre_vectors + affd->post_vectors)
                affvecs = nvecs - affd->pre_vectors - affd->post_vectors;
        else
                affvecs = 0;
index 9484e88dabc28d8e532a9465f45180c340aed4cd..9be995fc3c5a1414593056b09757db62efb15557 100644 (file)
@@ -295,6 +295,18 @@ static void irq_sysfs_add(int irq, struct irq_desc *desc)
        }
 }
 
+static void irq_sysfs_del(struct irq_desc *desc)
+{
+       /*
+        * If irq_sysfs_init() has not yet been invoked (early boot), then
+        * irq_kobj_base is NULL and the descriptor was never added.
+        * kobject_del() complains about a object with no parent, so make
+        * it conditional.
+        */
+       if (irq_kobj_base)
+               kobject_del(&desc->kobj);
+}
+
 static int __init irq_sysfs_init(void)
 {
        struct irq_desc *desc;
@@ -325,6 +337,7 @@ static struct kobj_type irq_kobj_type = {
 };
 
 static void irq_sysfs_add(int irq, struct irq_desc *desc) {}
+static void irq_sysfs_del(struct irq_desc *desc) {}
 
 #endif /* CONFIG_SYSFS */
 
@@ -438,7 +451,7 @@ static void free_desc(unsigned int irq)
         * The sysfs entry must be serialized against a concurrent
         * irq_sysfs_init() as well.
         */
-       kobject_del(&desc->kobj);
+       irq_sysfs_del(desc);
        delete_irq_desc(irq);
 
        /*
index 95414ad3506a919e21561d057e54ba27b8eb53c2..98c04ca5fa43d6a4515fff52a2d956c250777083 100644 (file)
@@ -36,6 +36,8 @@ static void resend_irqs(unsigned long arg)
                irq = find_first_bit(irqs_resend, nr_irqs);
                clear_bit(irq, irqs_resend);
                desc = irq_to_desc(irq);
+               if (!desc)
+                       continue;
                local_irq_disable();
                desc->handle_irq(desc);
                local_irq_enable();
index 95a260f9214b97e274ce4fdfe3ca1446b441ebbc..136ce049c4ad2f34f2b811c0e04c668ed511dba1 100644 (file)
@@ -263,8 +263,10 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
 {
        char namebuf[KSYM_NAME_LEN];
 
-       if (is_ksym_addr(addr))
-               return !!get_symbol_pos(addr, symbolsize, offset);
+       if (is_ksym_addr(addr)) {
+               get_symbol_pos(addr, symbolsize, offset);
+               return 1;
+       }
        return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) ||
               !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
 }
index 9873fc627d61f14295545817547aa4b96f7a00eb..d9770a5393c89925d2fa3f391dfb341a34a70409 100644 (file)
@@ -470,6 +470,7 @@ static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer);
  */
 static void do_optimize_kprobes(void)
 {
+       lockdep_assert_held(&text_mutex);
        /*
         * The optimization/unoptimization refers online_cpus via
         * stop_machine() and cpu-hotplug modifies online_cpus.
@@ -487,9 +488,7 @@ static void do_optimize_kprobes(void)
            list_empty(&optimizing_list))
                return;
 
-       mutex_lock(&text_mutex);
        arch_optimize_kprobes(&optimizing_list);
-       mutex_unlock(&text_mutex);
 }
 
 /*
@@ -500,6 +499,7 @@ static void do_unoptimize_kprobes(void)
 {
        struct optimized_kprobe *op, *tmp;
 
+       lockdep_assert_held(&text_mutex);
        /* See comment in do_optimize_kprobes() */
        lockdep_assert_cpus_held();
 
@@ -507,7 +507,6 @@ static void do_unoptimize_kprobes(void)
        if (list_empty(&unoptimizing_list))
                return;
 
-       mutex_lock(&text_mutex);
        arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list);
        /* Loop free_list for disarming */
        list_for_each_entry_safe(op, tmp, &freeing_list, list) {
@@ -524,7 +523,6 @@ static void do_unoptimize_kprobes(void)
                } else
                        list_del_init(&op->list);
        }
-       mutex_unlock(&text_mutex);
 }
 
 /* Reclaim all kprobes on the free_list */
@@ -556,6 +554,7 @@ static void kprobe_optimizer(struct work_struct *work)
 {
        mutex_lock(&kprobe_mutex);
        cpus_read_lock();
+       mutex_lock(&text_mutex);
        /* Lock modules while optimizing kprobes */
        mutex_lock(&module_mutex);
 
@@ -583,6 +582,7 @@ static void kprobe_optimizer(struct work_struct *work)
        do_free_cleaned_kprobes();
 
        mutex_unlock(&module_mutex);
+       mutex_unlock(&text_mutex);
        cpus_read_unlock();
        mutex_unlock(&kprobe_mutex);
 
index 341f52117f8864b1f1206a45364101fc23bd2e22..4861cf8e274b1c75ec73260e13131463b35dad49 100644 (file)
@@ -448,7 +448,7 @@ static void print_lockdep_off(const char *bug_msg)
 
 unsigned long nr_stack_trace_entries;
 
-#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
+#ifdef CONFIG_PROVE_LOCKING
 /*
  * Stack-trace: tightly packed array of stack backtrace
  * addresses. Protected by the graph_lock.
@@ -491,7 +491,7 @@ unsigned int max_lockdep_depth;
 DEFINE_PER_CPU(struct lockdep_stats, lockdep_stats);
 #endif
 
-#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
+#ifdef CONFIG_PROVE_LOCKING
 /*
  * Locking printouts:
  */
@@ -2969,7 +2969,7 @@ static void check_chain_key(struct task_struct *curr)
 #endif
 }
 
-#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING)
+#ifdef CONFIG_PROVE_LOCKING
 static int mark_lock(struct task_struct *curr, struct held_lock *this,
                     enum lock_usage_bit new_bit);
 
@@ -3608,7 +3608,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
        return ret;
 }
 
-#else /* defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING) */
+#else /* CONFIG_PROVE_LOCKING */
 
 static inline int
 mark_usage(struct task_struct *curr, struct held_lock *hlock, int check)
@@ -3627,7 +3627,7 @@ static inline int separate_irq_context(struct task_struct *curr,
        return 0;
 }
 
-#endif /* defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_PROVE_LOCKING) */
+#endif /* CONFIG_PROVE_LOCKING */
 
 /*
  * Initialize a lock instance's lock-class mapping info:
@@ -4321,8 +4321,7 @@ static void __lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie cookie
  */
 static void check_flags(unsigned long flags)
 {
-#if defined(CONFIG_PROVE_LOCKING) && defined(CONFIG_DEBUG_LOCKDEP) && \
-    defined(CONFIG_TRACE_IRQFLAGS)
+#if defined(CONFIG_PROVE_LOCKING) && defined(CONFIG_DEBUG_LOCKDEP)
        if (!debug_locks)
                return;
 
index 65b6a1600c8fd719ced51056093721f7c93b94c3..bda006f8a88be11c83bdb6fce4b63b9bf8d6e608 100644 (file)
@@ -200,7 +200,6 @@ static void lockdep_stats_debug_show(struct seq_file *m)
 
 static int lockdep_stats_show(struct seq_file *m, void *v)
 {
-       struct lock_class *class;
        unsigned long nr_unused = 0, nr_uncategorized = 0,
                      nr_irq_safe = 0, nr_irq_unsafe = 0,
                      nr_softirq_safe = 0, nr_softirq_unsafe = 0,
@@ -211,6 +210,8 @@ static int lockdep_stats_show(struct seq_file *m, void *v)
                      sum_forward_deps = 0;
 
 #ifdef CONFIG_PROVE_LOCKING
+       struct lock_class *class;
+
        list_for_each_entry(class, &all_lock_classes, lock_entry) {
 
                if (class->usage_mask == 0)
index edd1c082dbf5d5b2eb6b19a260051153c94af055..5e069734363c479d294180864c1b2bd9be9bddb8 100644 (file)
@@ -908,6 +908,10 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
 
        might_sleep();
 
+#ifdef CONFIG_DEBUG_MUTEXES
+       DEBUG_LOCKS_WARN_ON(lock->magic != lock);
+#endif
+
        ww = container_of(lock, struct ww_mutex, base);
        if (use_ww_ctx && ww_ctx) {
                if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
@@ -1379,8 +1383,13 @@ __ww_mutex_lock_interruptible_slowpath(struct ww_mutex *lock,
  */
 int __sched mutex_trylock(struct mutex *lock)
 {
-       bool locked = __mutex_trylock(lock);
+       bool locked;
+
+#ifdef CONFIG_DEBUG_MUTEXES
+       DEBUG_LOCKS_WARN_ON(lock->magic != lock);
+#endif
 
+       locked = __mutex_trylock(lock);
        if (locked)
                mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
 
index 37524a47f002719dc6459a4b2dc6b76a608a8102..bd0f0d05724ca943649788f5a72bd1c36f0bb567 100644 (file)
@@ -666,7 +666,11 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem,
        preempt_disable();
        rcu_read_lock();
        owner = rwsem_owner_flags(sem, &flags);
-       if ((flags & nonspinnable) || (owner && !owner_on_cpu(owner)))
+       /*
+        * Don't check the read-owner as the entry may be stale.
+        */
+       if ((flags & nonspinnable) ||
+           (owner && !(flags & RWSEM_READER_OWNED) && !owner_on_cpu(owner)))
                ret = false;
        rcu_read_unlock();
        preempt_enable();
@@ -1000,6 +1004,7 @@ rwsem_down_read_slowpath(struct rw_semaphore *sem, int state)
        atomic_long_add(-RWSEM_READER_BIAS, &sem->count);
        adjustment = 0;
        if (rwsem_optimistic_spin(sem, false)) {
+               /* rwsem_optimistic_spin() implies ACQUIRE on success */
                /*
                 * Wake up other readers in the wait list if the front
                 * waiter is a reader.
@@ -1014,6 +1019,7 @@ rwsem_down_read_slowpath(struct rw_semaphore *sem, int state)
                }
                return sem;
        } else if (rwsem_reader_phase_trylock(sem, waiter.last_rowner)) {
+               /* rwsem_reader_phase_trylock() implies ACQUIRE on success */
                return sem;
        }
 
@@ -1032,6 +1038,8 @@ queue:
                 */
                if (adjustment && !(atomic_long_read(&sem->count) &
                     (RWSEM_WRITER_MASK | RWSEM_FLAG_HANDOFF))) {
+                       /* Provide lock ACQUIRE */
+                       smp_acquire__after_ctrl_dep();
                        raw_spin_unlock_irq(&sem->wait_lock);
                        rwsem_set_reader_owned(sem);
                        lockevent_inc(rwsem_rlock_fast);
@@ -1065,15 +1073,18 @@ queue:
        wake_up_q(&wake_q);
 
        /* wait to be given the lock */
-       while (true) {
+       for (;;) {
                set_current_state(state);
-               if (!waiter.task)
+               if (!smp_load_acquire(&waiter.task)) {
+                       /* Matches rwsem_mark_wake()'s smp_store_release(). */
                        break;
+               }
                if (signal_pending_state(state, current)) {
                        raw_spin_lock_irq(&sem->wait_lock);
                        if (waiter.task)
                                goto out_nolock;
                        raw_spin_unlock_irq(&sem->wait_lock);
+                       /* Ordered by sem->wait_lock against rwsem_mark_wake(). */
                        break;
                }
                schedule();
@@ -1083,6 +1094,7 @@ queue:
        __set_current_state(TASK_RUNNING);
        lockevent_inc(rwsem_rlock);
        return sem;
+
 out_nolock:
        list_del(&waiter.list);
        if (list_empty(&sem->wait_list)) {
@@ -1123,8 +1135,10 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state)
 
        /* do optimistic spinning and steal lock if possible */
        if (rwsem_can_spin_on_owner(sem, RWSEM_WR_NONSPINNABLE) &&
-           rwsem_optimistic_spin(sem, true))
+           rwsem_optimistic_spin(sem, true)) {
+               /* rwsem_optimistic_spin() implies ACQUIRE on success */
                return sem;
+       }
 
        /*
         * Disable reader optimistic spinning for this rwsem after
@@ -1184,9 +1198,11 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state)
 wait:
        /* wait until we successfully acquire the lock */
        set_current_state(state);
-       while (true) {
-               if (rwsem_try_write_lock(sem, wstate))
+       for (;;) {
+               if (rwsem_try_write_lock(sem, wstate)) {
+                       /* rwsem_try_write_lock() implies ACQUIRE on success */
                        break;
+               }
 
                raw_spin_unlock_irq(&sem->wait_lock);
 
diff --git a/kernel/memremap.c b/kernel/memremap.c
deleted file mode 100644 (file)
index 6ee03a8..0000000
+++ /dev/null
@@ -1,405 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2015 Intel Corporation. All rights reserved. */
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/kasan.h>
-#include <linux/memory_hotplug.h>
-#include <linux/mm.h>
-#include <linux/pfn_t.h>
-#include <linux/swap.h>
-#include <linux/swapops.h>
-#include <linux/types.h>
-#include <linux/wait_bit.h>
-#include <linux/xarray.h>
-
-static DEFINE_XARRAY(pgmap_array);
-#define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1)
-#define SECTION_SIZE (1UL << PA_SECTION_SHIFT)
-
-#ifdef CONFIG_DEV_PAGEMAP_OPS
-DEFINE_STATIC_KEY_FALSE(devmap_managed_key);
-EXPORT_SYMBOL(devmap_managed_key);
-static atomic_t devmap_managed_enable;
-
-static void devmap_managed_enable_put(void *data)
-{
-       if (atomic_dec_and_test(&devmap_managed_enable))
-               static_branch_disable(&devmap_managed_key);
-}
-
-static int devmap_managed_enable_get(struct device *dev, struct dev_pagemap *pgmap)
-{
-       if (!pgmap->ops || !pgmap->ops->page_free) {
-               WARN(1, "Missing page_free method\n");
-               return -EINVAL;
-       }
-
-       if (atomic_inc_return(&devmap_managed_enable) == 1)
-               static_branch_enable(&devmap_managed_key);
-       return devm_add_action_or_reset(dev, devmap_managed_enable_put, NULL);
-}
-#else
-static int devmap_managed_enable_get(struct device *dev, struct dev_pagemap *pgmap)
-{
-       return -EINVAL;
-}
-#endif /* CONFIG_DEV_PAGEMAP_OPS */
-
-static void pgmap_array_delete(struct resource *res)
-{
-       xa_store_range(&pgmap_array, PHYS_PFN(res->start), PHYS_PFN(res->end),
-                       NULL, GFP_KERNEL);
-       synchronize_rcu();
-}
-
-static unsigned long pfn_first(struct dev_pagemap *pgmap)
-{
-       return PHYS_PFN(pgmap->res.start) +
-               vmem_altmap_offset(pgmap_altmap(pgmap));
-}
-
-static unsigned long pfn_end(struct dev_pagemap *pgmap)
-{
-       const struct resource *res = &pgmap->res;
-
-       return (res->start + resource_size(res)) >> PAGE_SHIFT;
-}
-
-static unsigned long pfn_next(unsigned long pfn)
-{
-       if (pfn % 1024 == 0)
-               cond_resched();
-       return pfn + 1;
-}
-
-#define for_each_device_pfn(pfn, map) \
-       for (pfn = pfn_first(map); pfn < pfn_end(map); pfn = pfn_next(pfn))
-
-static void dev_pagemap_kill(struct dev_pagemap *pgmap)
-{
-       if (pgmap->ops && pgmap->ops->kill)
-               pgmap->ops->kill(pgmap);
-       else
-               percpu_ref_kill(pgmap->ref);
-}
-
-static void dev_pagemap_cleanup(struct dev_pagemap *pgmap)
-{
-       if (pgmap->ops && pgmap->ops->cleanup) {
-               pgmap->ops->cleanup(pgmap);
-       } else {
-               wait_for_completion(&pgmap->done);
-               percpu_ref_exit(pgmap->ref);
-       }
-}
-
-static void devm_memremap_pages_release(void *data)
-{
-       struct dev_pagemap *pgmap = data;
-       struct device *dev = pgmap->dev;
-       struct resource *res = &pgmap->res;
-       unsigned long pfn;
-       int nid;
-
-       dev_pagemap_kill(pgmap);
-       for_each_device_pfn(pfn, pgmap)
-               put_page(pfn_to_page(pfn));
-       dev_pagemap_cleanup(pgmap);
-
-       /* pages are dead and unused, undo the arch mapping */
-       nid = page_to_nid(pfn_to_page(PHYS_PFN(res->start)));
-
-       mem_hotplug_begin();
-       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
-               pfn = PHYS_PFN(res->start);
-               __remove_pages(page_zone(pfn_to_page(pfn)), pfn,
-                                PHYS_PFN(resource_size(res)), NULL);
-       } else {
-               arch_remove_memory(nid, res->start, resource_size(res),
-                               pgmap_altmap(pgmap));
-               kasan_remove_zero_shadow(__va(res->start), resource_size(res));
-       }
-       mem_hotplug_done();
-
-       untrack_pfn(NULL, PHYS_PFN(res->start), resource_size(res));
-       pgmap_array_delete(res);
-       dev_WARN_ONCE(dev, pgmap->altmap.alloc,
-                     "%s: failed to free all reserved pages\n", __func__);
-}
-
-static void dev_pagemap_percpu_release(struct percpu_ref *ref)
-{
-       struct dev_pagemap *pgmap =
-               container_of(ref, struct dev_pagemap, internal_ref);
-
-       complete(&pgmap->done);
-}
-
-/**
- * devm_memremap_pages - remap and provide memmap backing for the given resource
- * @dev: hosting device for @res
- * @pgmap: pointer to a struct dev_pagemap
- *
- * Notes:
- * 1/ At a minimum the res and type members of @pgmap must be initialized
- *    by the caller before passing it to this function
- *
- * 2/ The altmap field may optionally be initialized, in which case
- *    PGMAP_ALTMAP_VALID must be set in pgmap->flags.
- *
- * 3/ The ref field may optionally be provided, in which pgmap->ref must be
- *    'live' on entry and will be killed and reaped at
- *    devm_memremap_pages_release() time, or if this routine fails.
- *
- * 4/ res is expected to be a host memory range that could feasibly be
- *    treated as a "System RAM" range, i.e. not a device mmio range, but
- *    this is not enforced.
- */
-void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
-{
-       struct resource *res = &pgmap->res;
-       struct dev_pagemap *conflict_pgmap;
-       struct mhp_restrictions restrictions = {
-               /*
-                * We do not want any optional features only our own memmap
-                */
-               .altmap = pgmap_altmap(pgmap),
-       };
-       pgprot_t pgprot = PAGE_KERNEL;
-       int error, nid, is_ram;
-       bool need_devmap_managed = true;
-
-       switch (pgmap->type) {
-       case MEMORY_DEVICE_PRIVATE:
-               if (!IS_ENABLED(CONFIG_DEVICE_PRIVATE)) {
-                       WARN(1, "Device private memory not supported\n");
-                       return ERR_PTR(-EINVAL);
-               }
-               if (!pgmap->ops || !pgmap->ops->migrate_to_ram) {
-                       WARN(1, "Missing migrate_to_ram method\n");
-                       return ERR_PTR(-EINVAL);
-               }
-               break;
-       case MEMORY_DEVICE_FS_DAX:
-               if (!IS_ENABLED(CONFIG_ZONE_DEVICE) ||
-                   IS_ENABLED(CONFIG_FS_DAX_LIMITED)) {
-                       WARN(1, "File system DAX not supported\n");
-                       return ERR_PTR(-EINVAL);
-               }
-               break;
-       case MEMORY_DEVICE_DEVDAX:
-       case MEMORY_DEVICE_PCI_P2PDMA:
-               need_devmap_managed = false;
-               break;
-       default:
-               WARN(1, "Invalid pgmap type %d\n", pgmap->type);
-               break;
-       }
-
-       if (!pgmap->ref) {
-               if (pgmap->ops && (pgmap->ops->kill || pgmap->ops->cleanup))
-                       return ERR_PTR(-EINVAL);
-
-               init_completion(&pgmap->done);
-               error = percpu_ref_init(&pgmap->internal_ref,
-                               dev_pagemap_percpu_release, 0, GFP_KERNEL);
-               if (error)
-                       return ERR_PTR(error);
-               pgmap->ref = &pgmap->internal_ref;
-       } else {
-               if (!pgmap->ops || !pgmap->ops->kill || !pgmap->ops->cleanup) {
-                       WARN(1, "Missing reference count teardown definition\n");
-                       return ERR_PTR(-EINVAL);
-               }
-       }
-
-       if (need_devmap_managed) {
-               error = devmap_managed_enable_get(dev, pgmap);
-               if (error)
-                       return ERR_PTR(error);
-       }
-
-       conflict_pgmap = get_dev_pagemap(PHYS_PFN(res->start), NULL);
-       if (conflict_pgmap) {
-               dev_WARN(dev, "Conflicting mapping in same section\n");
-               put_dev_pagemap(conflict_pgmap);
-               error = -ENOMEM;
-               goto err_array;
-       }
-
-       conflict_pgmap = get_dev_pagemap(PHYS_PFN(res->end), NULL);
-       if (conflict_pgmap) {
-               dev_WARN(dev, "Conflicting mapping in same section\n");
-               put_dev_pagemap(conflict_pgmap);
-               error = -ENOMEM;
-               goto err_array;
-       }
-
-       is_ram = region_intersects(res->start, resource_size(res),
-               IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
-
-       if (is_ram != REGION_DISJOINT) {
-               WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
-                               is_ram == REGION_MIXED ? "mixed" : "ram", res);
-               error = -ENXIO;
-               goto err_array;
-       }
-
-       pgmap->dev = dev;
-
-       error = xa_err(xa_store_range(&pgmap_array, PHYS_PFN(res->start),
-                               PHYS_PFN(res->end), pgmap, GFP_KERNEL));
-       if (error)
-               goto err_array;
-
-       nid = dev_to_node(dev);
-       if (nid < 0)
-               nid = numa_mem_id();
-
-       error = track_pfn_remap(NULL, &pgprot, PHYS_PFN(res->start), 0,
-                       resource_size(res));
-       if (error)
-               goto err_pfn_remap;
-
-       mem_hotplug_begin();
-
-       /*
-        * For device private memory we call add_pages() as we only need to
-        * allocate and initialize struct page for the device memory. More-
-        * over the device memory is un-accessible thus we do not want to
-        * create a linear mapping for the memory like arch_add_memory()
-        * would do.
-        *
-        * For all other device memory types, which are accessible by
-        * the CPU, we do want the linear mapping and thus use
-        * arch_add_memory().
-        */
-       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
-               error = add_pages(nid, PHYS_PFN(res->start),
-                               PHYS_PFN(resource_size(res)), &restrictions);
-       } else {
-               error = kasan_add_zero_shadow(__va(res->start), resource_size(res));
-               if (error) {
-                       mem_hotplug_done();
-                       goto err_kasan;
-               }
-
-               error = arch_add_memory(nid, res->start, resource_size(res),
-                                       &restrictions);
-       }
-
-       if (!error) {
-               struct zone *zone;
-
-               zone = &NODE_DATA(nid)->node_zones[ZONE_DEVICE];
-               move_pfn_range_to_zone(zone, PHYS_PFN(res->start),
-                               PHYS_PFN(resource_size(res)), restrictions.altmap);
-       }
-
-       mem_hotplug_done();
-       if (error)
-               goto err_add_memory;
-
-       /*
-        * Initialization of the pages has been deferred until now in order
-        * to allow us to do the work while not holding the hotplug lock.
-        */
-       memmap_init_zone_device(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
-                               PHYS_PFN(res->start),
-                               PHYS_PFN(resource_size(res)), pgmap);
-       percpu_ref_get_many(pgmap->ref, pfn_end(pgmap) - pfn_first(pgmap));
-
-       error = devm_add_action_or_reset(dev, devm_memremap_pages_release,
-                       pgmap);
-       if (error)
-               return ERR_PTR(error);
-
-       return __va(res->start);
-
- err_add_memory:
-       kasan_remove_zero_shadow(__va(res->start), resource_size(res));
- err_kasan:
-       untrack_pfn(NULL, PHYS_PFN(res->start), resource_size(res));
- err_pfn_remap:
-       pgmap_array_delete(res);
- err_array:
-       dev_pagemap_kill(pgmap);
-       dev_pagemap_cleanup(pgmap);
-       return ERR_PTR(error);
-}
-EXPORT_SYMBOL_GPL(devm_memremap_pages);
-
-void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap)
-{
-       devm_release_action(dev, devm_memremap_pages_release, pgmap);
-}
-EXPORT_SYMBOL_GPL(devm_memunmap_pages);
-
-unsigned long vmem_altmap_offset(struct vmem_altmap *altmap)
-{
-       /* number of pfns from base where pfn_to_page() is valid */
-       if (altmap)
-               return altmap->reserve + altmap->free;
-       return 0;
-}
-
-void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns)
-{
-       altmap->alloc -= nr_pfns;
-}
-
-/**
- * get_dev_pagemap() - take a new live reference on the dev_pagemap for @pfn
- * @pfn: page frame number to lookup page_map
- * @pgmap: optional known pgmap that already has a reference
- *
- * If @pgmap is non-NULL and covers @pfn it will be returned as-is.  If @pgmap
- * is non-NULL but does not cover @pfn the reference to it will be released.
- */
-struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
-               struct dev_pagemap *pgmap)
-{
-       resource_size_t phys = PFN_PHYS(pfn);
-
-       /*
-        * In the cached case we're already holding a live reference.
-        */
-       if (pgmap) {
-               if (phys >= pgmap->res.start && phys <= pgmap->res.end)
-                       return pgmap;
-               put_dev_pagemap(pgmap);
-       }
-
-       /* fall back to slow path lookup */
-       rcu_read_lock();
-       pgmap = xa_load(&pgmap_array, PHYS_PFN(phys));
-       if (pgmap && !percpu_ref_tryget_live(pgmap->ref))
-               pgmap = NULL;
-       rcu_read_unlock();
-
-       return pgmap;
-}
-EXPORT_SYMBOL_GPL(get_dev_pagemap);
-
-#ifdef CONFIG_DEV_PAGEMAP_OPS
-void __put_devmap_managed_page(struct page *page)
-{
-       int count = page_ref_dec_return(page);
-
-       /*
-        * If refcount is 1 then page is freed and refcount is stable as nobody
-        * holds a reference on the page.
-        */
-       if (count == 1) {
-               /* Clear Active bit in case of parallel mark_page_accessed */
-               __ClearPageActive(page);
-               __ClearPageWaiters(page);
-
-               mem_cgroup_uncharge(page);
-
-               page->pgmap->ops->page_free(page);
-       } else if (!count)
-               __put_page(page);
-}
-EXPORT_SYMBOL(__put_devmap_managed_page);
-#endif /* CONFIG_DEV_PAGEMAP_OPS */
index 5933395af9a0c18c7ccf1f97543d15050e1550a0..9ee93421269c061393f03721bcbf1a94239f1877 100644 (file)
@@ -65,9 +65,9 @@
 /*
  * Modules' sections will be aligned on page boundaries
  * to ensure complete separation of code and data, but
- * only when CONFIG_STRICT_MODULE_RWX=y
+ * only when CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
  */
-#ifdef CONFIG_STRICT_MODULE_RWX
+#ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX
 # define debug_align(X) ALIGN(X, PAGE_SIZE)
 #else
 # define debug_align(X) (X)
index 2b037f1954732ab5a3b5bca3ecc7bd4a638774bc..df9f1fe5689b04006907283f798b91959c0b9d51 100644 (file)
@@ -3904,7 +3904,7 @@ void __noreturn do_task_dead(void)
 
 static inline void sched_submit_work(struct task_struct *tsk)
 {
-       if (!tsk->state || tsk_is_pi_blocked(tsk))
+       if (!tsk->state)
                return;
 
        /*
@@ -3920,6 +3920,9 @@ static inline void sched_submit_work(struct task_struct *tsk)
                preempt_enable_no_resched();
        }
 
+       if (tsk_is_pi_blocked(tsk))
+               return;
+
        /*
         * If we are going to sleep and we have plugged IO queued,
         * make sure to submit it to avoid deadlocks.
@@ -5102,37 +5105,40 @@ out_unlock:
        return retval;
 }
 
-static int sched_read_attr(struct sched_attr __user *uattr,
-                          struct sched_attr *attr,
-                          unsigned int usize)
+/*
+ * Copy the kernel size attribute structure (which might be larger
+ * than what user-space knows about) to user-space.
+ *
+ * Note that all cases are valid: user-space buffer can be larger or
+ * smaller than the kernel-space buffer. The usual case is that both
+ * have the same size.
+ */
+static int
+sched_attr_copy_to_user(struct sched_attr __user *uattr,
+                       struct sched_attr *kattr,
+                       unsigned int usize)
 {
-       int ret;
+       unsigned int ksize = sizeof(*kattr);
 
        if (!access_ok(uattr, usize))
                return -EFAULT;
 
        /*
-        * If we're handed a smaller struct than we know of,
-        * ensure all the unknown bits are 0 - i.e. old
-        * user-space does not get uncomplete information.
+        * sched_getattr() ABI forwards and backwards compatibility:
+        *
+        * If usize == ksize then we just copy everything to user-space and all is good.
+        *
+        * If usize < ksize then we only copy as much as user-space has space for,
+        * this keeps ABI compatibility as well. We skip the rest.
+        *
+        * If usize > ksize then user-space is using a newer version of the ABI,
+        * which part the kernel doesn't know about. Just ignore it - tooling can
+        * detect the kernel's knowledge of attributes from the attr->size value
+        * which is set to ksize in this case.
         */
-       if (usize < sizeof(*attr)) {
-               unsigned char *addr;
-               unsigned char *end;
-
-               addr = (void *)attr + usize;
-               end  = (void *)attr + sizeof(*attr);
+       kattr->size = min(usize, ksize);
 
-               for (; addr < end; addr++) {
-                       if (*addr)
-                               return -EFBIG;
-               }
-
-               attr->size = usize;
-       }
-
-       ret = copy_to_user(uattr, attr, attr->size);
-       if (ret)
+       if (copy_to_user(uattr, kattr, kattr->size))
                return -EFAULT;
 
        return 0;
@@ -5142,20 +5148,18 @@ static int sched_read_attr(struct sched_attr __user *uattr,
  * sys_sched_getattr - similar to sched_getparam, but with sched_attr
  * @pid: the pid in question.
  * @uattr: structure containing the extended parameters.
- * @size: sizeof(attr) for fwd/bwd comp.
+ * @usize: sizeof(attr) that user-space knows about, for forwards and backwards compatibility.
  * @flags: for future extension.
  */
 SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
-               unsigned int, size, unsigned int, flags)
+               unsigned int, usize, unsigned int, flags)
 {
-       struct sched_attr attr = {
-               .size = sizeof(struct sched_attr),
-       };
+       struct sched_attr kattr = { };
        struct task_struct *p;
        int retval;
 
-       if (!uattr || pid < 0 || size > PAGE_SIZE ||
-           size < SCHED_ATTR_SIZE_VER0 || flags)
+       if (!uattr || pid < 0 || usize > PAGE_SIZE ||
+           usize < SCHED_ATTR_SIZE_VER0 || flags)
                return -EINVAL;
 
        rcu_read_lock();
@@ -5168,25 +5172,24 @@ SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
        if (retval)
                goto out_unlock;
 
-       attr.sched_policy = p->policy;
+       kattr.sched_policy = p->policy;
        if (p->sched_reset_on_fork)
-               attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
+               kattr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
        if (task_has_dl_policy(p))
-               __getparam_dl(p, &attr);
+               __getparam_dl(p, &kattr);
        else if (task_has_rt_policy(p))
-               attr.sched_priority = p->rt_priority;
+               kattr.sched_priority = p->rt_priority;
        else
-               attr.sched_nice = task_nice(p);
+               kattr.sched_nice = task_nice(p);
 
 #ifdef CONFIG_UCLAMP_TASK
-       attr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value;
-       attr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value;
+       kattr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value;
+       kattr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value;
 #endif
 
        rcu_read_unlock();
 
-       retval = sched_read_attr(uattr, &attr, size);
-       return retval;
+       return sched_attr_copy_to_user(uattr, &kattr, usize);
 
 out_unlock:
        rcu_read_unlock();
index 636ca6f88c8ee275efd664c553609c5121a5cb3f..867b4bb6d4beb541d1d9eb087711d1e52a446416 100644 (file)
@@ -40,6 +40,7 @@ struct sugov_policy {
        struct task_struct      *thread;
        bool                    work_in_progress;
 
+       bool                    limits_changed;
        bool                    need_freq_update;
 };
 
@@ -89,8 +90,11 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
            !cpufreq_this_cpu_can_update(sg_policy->policy))
                return false;
 
-       if (unlikely(sg_policy->need_freq_update))
+       if (unlikely(sg_policy->limits_changed)) {
+               sg_policy->limits_changed = false;
+               sg_policy->need_freq_update = true;
                return true;
+       }
 
        delta_ns = time - sg_policy->last_freq_update_time;
 
@@ -437,7 +441,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
 static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy)
 {
        if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl)
-               sg_policy->need_freq_update = true;
+               sg_policy->limits_changed = true;
 }
 
 static void sugov_update_single(struct update_util_data *hook, u64 time,
@@ -457,7 +461,8 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
        if (!sugov_should_update_freq(sg_policy, time))
                return;
 
-       busy = sugov_cpu_is_busy(sg_cpu);
+       /* Limits may have changed, don't skip frequency update */
+       busy = !sg_policy->need_freq_update && sugov_cpu_is_busy(sg_cpu);
 
        util = sugov_get_util(sg_cpu);
        max = sg_cpu->max;
@@ -831,6 +836,7 @@ static int sugov_start(struct cpufreq_policy *policy)
        sg_policy->last_freq_update_time        = 0;
        sg_policy->next_freq                    = 0;
        sg_policy->work_in_progress             = false;
+       sg_policy->limits_changed               = false;
        sg_policy->need_freq_update             = false;
        sg_policy->cached_raw_freq              = 0;
 
@@ -879,7 +885,7 @@ static void sugov_limits(struct cpufreq_policy *policy)
                mutex_unlock(&sg_policy->work_lock);
        }
 
-       sg_policy->need_freq_update = true;
+       sg_policy->limits_changed = true;
 }
 
 struct cpufreq_governor schedutil_gov = {
index ef5b9f6b1d421bbd3e88e5300fa8f0ceeb448cbd..46122edd8552c9abd7acb3cf665332d91746ed7d 100644 (file)
@@ -2088,17 +2088,13 @@ retry:
        }
 
        deactivate_task(rq, next_task, 0);
-       sub_running_bw(&next_task->dl, &rq->dl);
-       sub_rq_bw(&next_task->dl, &rq->dl);
        set_task_cpu(next_task, later_rq->cpu);
-       add_rq_bw(&next_task->dl, &later_rq->dl);
 
        /*
         * Update the later_rq clock here, because the clock is used
         * by the cpufreq_update_util() inside __add_running_bw().
         */
        update_rq_clock(later_rq);
-       add_running_bw(&next_task->dl, &later_rq->dl);
        activate_task(later_rq, next_task, ENQUEUE_NOCLOCK);
        ret = 1;
 
@@ -2186,11 +2182,7 @@ static void pull_dl_task(struct rq *this_rq)
                        resched = true;
 
                        deactivate_task(src_rq, p, 0);
-                       sub_running_bw(&p->dl, &src_rq->dl);
-                       sub_rq_bw(&p->dl, &src_rq->dl);
                        set_task_cpu(p, this_cpu);
-                       add_rq_bw(&p->dl, &this_rq->dl);
-                       add_running_bw(&p->dl, &this_rq->dl);
                        activate_task(this_rq, p, 0);
                        dmin = p->dl.deadline;
 
index 036be95a87e905a726ed9fa61369a8054b20733c..500f5db0de0ba86a331586d4189e3b299cb6148e 100644 (file)
@@ -1086,6 +1086,21 @@ struct numa_group {
        unsigned long faults[0];
 };
 
+/*
+ * For functions that can be called in multiple contexts that permit reading
+ * ->numa_group (see struct task_struct for locking rules).
+ */
+static struct numa_group *deref_task_numa_group(struct task_struct *p)
+{
+       return rcu_dereference_check(p->numa_group, p == current ||
+               (lockdep_is_held(&task_rq(p)->lock) && !READ_ONCE(p->on_cpu)));
+}
+
+static struct numa_group *deref_curr_numa_group(struct task_struct *p)
+{
+       return rcu_dereference_protected(p->numa_group, p == current);
+}
+
 static inline unsigned long group_faults_priv(struct numa_group *ng);
 static inline unsigned long group_faults_shared(struct numa_group *ng);
 
@@ -1129,10 +1144,12 @@ static unsigned int task_scan_start(struct task_struct *p)
 {
        unsigned long smin = task_scan_min(p);
        unsigned long period = smin;
+       struct numa_group *ng;
 
        /* Scale the maximum scan period with the amount of shared memory. */
-       if (p->numa_group) {
-               struct numa_group *ng = p->numa_group;
+       rcu_read_lock();
+       ng = rcu_dereference(p->numa_group);
+       if (ng) {
                unsigned long shared = group_faults_shared(ng);
                unsigned long private = group_faults_priv(ng);
 
@@ -1140,6 +1157,7 @@ static unsigned int task_scan_start(struct task_struct *p)
                period *= shared + 1;
                period /= private + shared + 1;
        }
+       rcu_read_unlock();
 
        return max(smin, period);
 }
@@ -1148,13 +1166,14 @@ static unsigned int task_scan_max(struct task_struct *p)
 {
        unsigned long smin = task_scan_min(p);
        unsigned long smax;
+       struct numa_group *ng;
 
        /* Watch for min being lower than max due to floor calculations */
        smax = sysctl_numa_balancing_scan_period_max / task_nr_scan_windows(p);
 
        /* Scale the maximum scan period with the amount of shared memory. */
-       if (p->numa_group) {
-               struct numa_group *ng = p->numa_group;
+       ng = deref_curr_numa_group(p);
+       if (ng) {
                unsigned long shared = group_faults_shared(ng);
                unsigned long private = group_faults_priv(ng);
                unsigned long period = smax;
@@ -1186,7 +1205,7 @@ void init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
        p->numa_scan_period             = sysctl_numa_balancing_scan_delay;
        p->numa_work.next               = &p->numa_work;
        p->numa_faults                  = NULL;
-       p->numa_group                   = NULL;
+       RCU_INIT_POINTER(p->numa_group, NULL);
        p->last_task_numa_placement     = 0;
        p->last_sum_exec_runtime        = 0;
 
@@ -1233,7 +1252,16 @@ static void account_numa_dequeue(struct rq *rq, struct task_struct *p)
 
 pid_t task_numa_group_id(struct task_struct *p)
 {
-       return p->numa_group ? p->numa_group->gid : 0;
+       struct numa_group *ng;
+       pid_t gid = 0;
+
+       rcu_read_lock();
+       ng = rcu_dereference(p->numa_group);
+       if (ng)
+               gid = ng->gid;
+       rcu_read_unlock();
+
+       return gid;
 }
 
 /*
@@ -1258,11 +1286,13 @@ static inline unsigned long task_faults(struct task_struct *p, int nid)
 
 static inline unsigned long group_faults(struct task_struct *p, int nid)
 {
-       if (!p->numa_group)
+       struct numa_group *ng = deref_task_numa_group(p);
+
+       if (!ng)
                return 0;
 
-       return p->numa_group->faults[task_faults_idx(NUMA_MEM, nid, 0)] +
-               p->numa_group->faults[task_faults_idx(NUMA_MEM, nid, 1)];
+       return ng->faults[task_faults_idx(NUMA_MEM, nid, 0)] +
+               ng->faults[task_faults_idx(NUMA_MEM, nid, 1)];
 }
 
 static inline unsigned long group_faults_cpu(struct numa_group *group, int nid)
@@ -1400,12 +1430,13 @@ static inline unsigned long task_weight(struct task_struct *p, int nid,
 static inline unsigned long group_weight(struct task_struct *p, int nid,
                                         int dist)
 {
+       struct numa_group *ng = deref_task_numa_group(p);
        unsigned long faults, total_faults;
 
-       if (!p->numa_group)
+       if (!ng)
                return 0;
 
-       total_faults = p->numa_group->total_faults;
+       total_faults = ng->total_faults;
 
        if (!total_faults)
                return 0;
@@ -1419,7 +1450,7 @@ static inline unsigned long group_weight(struct task_struct *p, int nid,
 bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
                                int src_nid, int dst_cpu)
 {
-       struct numa_group *ng = p->numa_group;
+       struct numa_group *ng = deref_curr_numa_group(p);
        int dst_nid = cpu_to_node(dst_cpu);
        int last_cpupid, this_cpupid;
 
@@ -1600,13 +1631,14 @@ static bool load_too_imbalanced(long src_load, long dst_load,
 static void task_numa_compare(struct task_numa_env *env,
                              long taskimp, long groupimp, bool maymove)
 {
+       struct numa_group *cur_ng, *p_ng = deref_curr_numa_group(env->p);
        struct rq *dst_rq = cpu_rq(env->dst_cpu);
+       long imp = p_ng ? groupimp : taskimp;
        struct task_struct *cur;
        long src_load, dst_load;
-       long load;
-       long imp = env->p->numa_group ? groupimp : taskimp;
-       long moveimp = imp;
        int dist = env->dist;
+       long moveimp = imp;
+       long load;
 
        if (READ_ONCE(dst_rq->numa_migrate_on))
                return;
@@ -1645,21 +1677,22 @@ static void task_numa_compare(struct task_numa_env *env,
         * If dst and source tasks are in the same NUMA group, or not
         * in any group then look only at task weights.
         */
-       if (cur->numa_group == env->p->numa_group) {
+       cur_ng = rcu_dereference(cur->numa_group);
+       if (cur_ng == p_ng) {
                imp = taskimp + task_weight(cur, env->src_nid, dist) -
                      task_weight(cur, env->dst_nid, dist);
                /*
                 * Add some hysteresis to prevent swapping the
                 * tasks within a group over tiny differences.
                 */
-               if (cur->numa_group)
+               if (cur_ng)
                        imp -= imp / 16;
        } else {
                /*
                 * Compare the group weights. If a task is all by itself
                 * (not part of a group), use the task weight instead.
                 */
-               if (cur->numa_group && env->p->numa_group)
+               if (cur_ng && p_ng)
                        imp += group_weight(cur, env->src_nid, dist) -
                               group_weight(cur, env->dst_nid, dist);
                else
@@ -1757,11 +1790,12 @@ static int task_numa_migrate(struct task_struct *p)
                .best_imp = 0,
                .best_cpu = -1,
        };
+       unsigned long taskweight, groupweight;
        struct sched_domain *sd;
+       long taskimp, groupimp;
+       struct numa_group *ng;
        struct rq *best_rq;
-       unsigned long taskweight, groupweight;
        int nid, ret, dist;
-       long taskimp, groupimp;
 
        /*
         * Pick the lowest SD_NUMA domain, as that would have the smallest
@@ -1807,7 +1841,8 @@ static int task_numa_migrate(struct task_struct *p)
         *   multiple NUMA nodes; in order to better consolidate the group,
         *   we need to check other locations.
         */
-       if (env.best_cpu == -1 || (p->numa_group && p->numa_group->active_nodes > 1)) {
+       ng = deref_curr_numa_group(p);
+       if (env.best_cpu == -1 || (ng && ng->active_nodes > 1)) {
                for_each_online_node(nid) {
                        if (nid == env.src_nid || nid == p->numa_preferred_nid)
                                continue;
@@ -1840,7 +1875,7 @@ static int task_numa_migrate(struct task_struct *p)
         * A task that migrated to a second choice node will be better off
         * trying for a better one later. Do not set the preferred node here.
         */
-       if (p->numa_group) {
+       if (ng) {
                if (env.best_cpu == -1)
                        nid = env.src_nid;
                else
@@ -2135,6 +2170,7 @@ static void task_numa_placement(struct task_struct *p)
        unsigned long total_faults;
        u64 runtime, period;
        spinlock_t *group_lock = NULL;
+       struct numa_group *ng;
 
        /*
         * The p->mm->numa_scan_seq field gets updated without
@@ -2152,8 +2188,9 @@ static void task_numa_placement(struct task_struct *p)
        runtime = numa_get_avg_runtime(p, &period);
 
        /* If the task is part of a group prevent parallel updates to group stats */
-       if (p->numa_group) {
-               group_lock = &p->numa_group->lock;
+       ng = deref_curr_numa_group(p);
+       if (ng) {
+               group_lock = &ng->lock;
                spin_lock_irq(group_lock);
        }
 
@@ -2194,7 +2231,7 @@ static void task_numa_placement(struct task_struct *p)
                        p->numa_faults[cpu_idx] += f_diff;
                        faults += p->numa_faults[mem_idx];
                        p->total_numa_faults += diff;
-                       if (p->numa_group) {
+                       if (ng) {
                                /*
                                 * safe because we can only change our own group
                                 *
@@ -2202,14 +2239,14 @@ static void task_numa_placement(struct task_struct *p)
                                 * nid and priv in a specific region because it
                                 * is at the beginning of the numa_faults array.
                                 */
-                               p->numa_group->faults[mem_idx] += diff;
-                               p->numa_group->faults_cpu[mem_idx] += f_diff;
-                               p->numa_group->total_faults += diff;
-                               group_faults += p->numa_group->faults[mem_idx];
+                               ng->faults[mem_idx] += diff;
+                               ng->faults_cpu[mem_idx] += f_diff;
+                               ng->total_faults += diff;
+                               group_faults += ng->faults[mem_idx];
                        }
                }
 
-               if (!p->numa_group) {
+               if (!ng) {
                        if (faults > max_faults) {
                                max_faults = faults;
                                max_nid = nid;
@@ -2220,8 +2257,8 @@ static void task_numa_placement(struct task_struct *p)
                }
        }
 
-       if (p->numa_group) {
-               numa_group_count_active_nodes(p->numa_group);
+       if (ng) {
+               numa_group_count_active_nodes(ng);
                spin_unlock_irq(group_lock);
                max_nid = preferred_group_nid(p, max_nid);
        }
@@ -2255,7 +2292,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
        int cpu = cpupid_to_cpu(cpupid);
        int i;
 
-       if (unlikely(!p->numa_group)) {
+       if (unlikely(!deref_curr_numa_group(p))) {
                unsigned int size = sizeof(struct numa_group) +
                                    4*nr_node_ids*sizeof(unsigned long);
 
@@ -2291,7 +2328,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
        if (!grp)
                goto no_join;
 
-       my_grp = p->numa_group;
+       my_grp = deref_curr_numa_group(p);
        if (grp == my_grp)
                goto no_join;
 
@@ -2353,13 +2390,24 @@ no_join:
        return;
 }
 
-void task_numa_free(struct task_struct *p)
+/*
+ * Get rid of NUMA staticstics associated with a task (either current or dead).
+ * If @final is set, the task is dead and has reached refcount zero, so we can
+ * safely free all relevant data structures. Otherwise, there might be
+ * concurrent reads from places like load balancing and procfs, and we should
+ * reset the data back to default state without freeing ->numa_faults.
+ */
+void task_numa_free(struct task_struct *p, bool final)
 {
-       struct numa_group *grp = p->numa_group;
-       void *numa_faults = p->numa_faults;
+       /* safe: p either is current or is being freed by current */
+       struct numa_group *grp = rcu_dereference_raw(p->numa_group);
+       unsigned long *numa_faults = p->numa_faults;
        unsigned long flags;
        int i;
 
+       if (!numa_faults)
+               return;
+
        if (grp) {
                spin_lock_irqsave(&grp->lock, flags);
                for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
@@ -2372,8 +2420,14 @@ void task_numa_free(struct task_struct *p)
                put_numa_group(grp);
        }
 
-       p->numa_faults = NULL;
-       kfree(numa_faults);
+       if (final) {
+               p->numa_faults = NULL;
+               kfree(numa_faults);
+       } else {
+               p->total_numa_faults = 0;
+               for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
+                       numa_faults[i] = 0;
+       }
 }
 
 /*
@@ -2426,7 +2480,7 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
         * actively using should be counted as local. This allows the
         * scan rate to slow down when a workload has settled down.
         */
-       ng = p->numa_group;
+       ng = deref_curr_numa_group(p);
        if (!priv && !local && ng && ng->active_nodes > 1 &&
                                numa_is_active_node(cpu_node, ng) &&
                                numa_is_active_node(mem_node, ng))
@@ -4416,6 +4470,8 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
        if (likely(cfs_rq->runtime_remaining > 0))
                return;
 
+       if (cfs_rq->throttled)
+               return;
        /*
         * if we're unable to extend our runtime we resched so that the active
         * hierarchy can be throttled
@@ -4619,6 +4675,9 @@ static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b,
                if (!cfs_rq_throttled(cfs_rq))
                        goto next;
 
+               /* By the above check, this should never be true */
+               SCHED_WARN_ON(cfs_rq->runtime_remaining > 0);
+
                runtime = -cfs_rq->runtime_remaining + 1;
                if (runtime > remaining)
                        runtime = remaining;
@@ -10444,18 +10503,22 @@ void show_numa_stats(struct task_struct *p, struct seq_file *m)
 {
        int node;
        unsigned long tsf = 0, tpf = 0, gsf = 0, gpf = 0;
+       struct numa_group *ng;
 
+       rcu_read_lock();
+       ng = rcu_dereference(p->numa_group);
        for_each_online_node(node) {
                if (p->numa_faults) {
                        tsf = p->numa_faults[task_faults_idx(NUMA_MEM, node, 0)];
                        tpf = p->numa_faults[task_faults_idx(NUMA_MEM, node, 1)];
                }
-               if (p->numa_group) {
-                       gsf = p->numa_group->faults[task_faults_idx(NUMA_MEM, node, 0)],
-                       gpf = p->numa_group->faults[task_faults_idx(NUMA_MEM, node, 1)];
+               if (ng) {
+                       gsf = ng->faults[task_faults_idx(NUMA_MEM, node, 0)],
+                       gpf = ng->faults[task_faults_idx(NUMA_MEM, node, 1)];
                }
                print_numa_stats(m, node, tsf, tpf, gsf, gpf);
        }
+       rcu_read_unlock();
 }
 #endif /* CONFIG_NUMA_BALANCING */
 #endif /* CONFIG_SCHED_DEBUG */
index 7acc632c3b82bebceeff2cfdc06eb652096f912b..6e52b67b420e7a3312f463f8d3bb6baad6576041 100644 (file)
@@ -1051,7 +1051,7 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
 
        if (!rcu_access_pointer(group->poll_kworker)) {
                struct sched_param param = {
-                       .sched_priority = MAX_RT_PRIO - 1,
+                       .sched_priority = 1,
                };
                struct kthread_worker *kworker;
 
@@ -1061,7 +1061,7 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
                        mutex_unlock(&group->trigger_lock);
                        return ERR_CAST(kworker);
                }
-               sched_setscheduler(kworker->task, SCHED_FIFO, &param);
+               sched_setscheduler_nocheck(kworker->task, SCHED_FIFO, &param);
                kthread_init_delayed_work(&group->poll_work,
                                psi_poll_work);
                rcu_assign_pointer(group->poll_kworker, kworker);
@@ -1131,7 +1131,15 @@ static void psi_trigger_destroy(struct kref *ref)
         * deadlock while waiting for psi_poll_work to acquire trigger_lock
         */
        if (kworker_to_destroy) {
+               /*
+                * After the RCU grace period has expired, the worker
+                * can no longer be found through group->poll_kworker.
+                * But it might have been already scheduled before
+                * that - deschedule it cleanly before destroying it.
+                */
                kthread_cancel_delayed_work_sync(&group->poll_work);
+               atomic_set(&group->poll_scheduled, 0);
+
                kthread_destroy_worker(kworker_to_destroy);
        }
        kfree(t);
index 91b789dd6e722ef96f8cf4440eb8f5bbc857ac60..534fec266a334b299846034e878c271619fe5c71 100644 (file)
@@ -90,6 +90,11 @@ static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
            handler == SIG_DFL && !(force && sig_kernel_only(sig)))
                return true;
 
+       /* Only allow kernel generated signals to this kthread */
+       if (unlikely((t->flags & PF_KTHREAD) &&
+                    (handler == SIG_KTHREAD_KERNEL) && !force))
+               return true;
+
        return sig_handler_ignored(handler, sig);
 }
 
@@ -349,7 +354,7 @@ void task_clear_jobctl_pending(struct task_struct *task, unsigned long mask)
  * @task has %JOBCTL_STOP_PENDING set and is participating in a group stop.
  * Group stop states are cleared and the group stop count is consumed if
  * %JOBCTL_STOP_CONSUME was set.  If the consumption completes the group
- * stop, the appropriate %SIGNAL_* flags are set.
+ * stop, the appropriate `SIGNAL_*` flags are set.
  *
  * CONTEXT:
  * Must be called with @task->sighand->siglock held.
@@ -1885,6 +1890,7 @@ static void do_notify_pidfd(struct task_struct *task)
 {
        struct pid *pid;
 
+       WARN_ON(task->exit_state == 0);
        pid = task_pid(task);
        wake_up_all(&pid->wait_pidfd);
 }
index d911c8470149e87330838153abfd511f868fe383..ca69290bee2a3131358993e9a3bbc32c6a9a9231 100644 (file)
@@ -146,6 +146,11 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec64 wtm)
 static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta)
 {
        tk->offs_boot = ktime_add(tk->offs_boot, delta);
+       /*
+        * Timespec representation for VDSO update to avoid 64bit division
+        * on every update.
+        */
+       tk->monotonic_to_boot = ktime_to_timespec64(tk->offs_boot);
 }
 
 /*
index 8cf3596a4ce677ca787e214d6f33b32a6d6b4088..4bc37ac3bb0526994e2dcacd20369e6f2e98f8d3 100644 (file)
@@ -17,7 +17,7 @@ static inline void update_vdso_data(struct vdso_data *vdata,
                                    struct timekeeper *tk)
 {
        struct vdso_timestamp *vdso_ts;
-       u64 nsec;
+       u64 nsec, sec;
 
        vdata[CS_HRES_COARSE].cycle_last        = tk->tkr_mono.cycle_last;
        vdata[CS_HRES_COARSE].mask              = tk->tkr_mono.mask;
@@ -45,23 +45,27 @@ static inline void update_vdso_data(struct vdso_data *vdata,
        }
        vdso_ts->nsec   = nsec;
 
-       /* CLOCK_MONOTONIC_RAW */
-       vdso_ts         = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
-       vdso_ts->sec    = tk->raw_sec;
-       vdso_ts->nsec   = tk->tkr_raw.xtime_nsec;
+       /* Copy MONOTONIC time for BOOTTIME */
+       sec     = vdso_ts->sec;
+       /* Add the boot offset */
+       sec     += tk->monotonic_to_boot.tv_sec;
+       nsec    += (u64)tk->monotonic_to_boot.tv_nsec << tk->tkr_mono.shift;
 
        /* CLOCK_BOOTTIME */
        vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
-       vdso_ts->sec    = tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
-       nsec = tk->tkr_mono.xtime_nsec;
-       nsec += ((u64)(tk->wall_to_monotonic.tv_nsec +
-                      ktime_to_ns(tk->offs_boot)) << tk->tkr_mono.shift);
+       vdso_ts->sec    = sec;
+
        while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
                nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
                vdso_ts->sec++;
        }
        vdso_ts->nsec   = nsec;
 
+       /* CLOCK_MONOTONIC_RAW */
+       vdso_ts         = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
+       vdso_ts->sec    = tk->raw_sec;
+       vdso_ts->nsec   = tk->tkr_raw.xtime_nsec;
+
        /* CLOCK_TAI */
        vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI];
        vdso_ts->sec    = tk->xtime_sec + (s64)tk->tai_offset;
index eca34503f178ece3f25a469ed3d73f186fd98c9e..f9821a3374e9dd4b81ed0f7cfe8c436d7a58b4c5 100644 (file)
@@ -3095,6 +3095,14 @@ t_probe_next(struct seq_file *m, loff_t *pos)
                hnd = &iter->probe_entry->hlist;
 
        hash = iter->probe->ops.func_hash->filter_hash;
+
+       /*
+        * A probe being registered may temporarily have an empty hash
+        * and it's at the end of the func_probes list.
+        */
+       if (!hash || hash == EMPTY_HASH)
+               return NULL;
+
        size = 1 << hash->size_bits;
 
  retry:
@@ -4320,12 +4328,21 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr,
 
        mutex_unlock(&ftrace_lock);
 
+       /*
+        * Note, there's a small window here that the func_hash->filter_hash
+        * may be NULL or empty. Need to be carefule when reading the loop.
+        */
        mutex_lock(&probe->ops.func_hash->regex_lock);
 
        orig_hash = &probe->ops.func_hash->filter_hash;
        old_hash = *orig_hash;
        hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, old_hash);
 
+       if (!hash) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
        ret = ftrace_match_records(hash, glob, strlen(glob));
 
        /* Nothing found? */
index 525a97fbbc603fa476a27b23d49dff7b7932a112..563e80f9006a438442dcfb1736e846aca7959b63 100644 (file)
@@ -1567,9 +1567,9 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu,
 
 /**
  * update_max_tr_single - only copy one trace over, and reset the rest
- * @tr - tracer
- * @tsk - task with the latency
- * @cpu - the cpu of the buffer to copy.
+ * @tr: tracer
+ * @tsk: task with the latency
+ * @cpu: the cpu of the buffer to copy.
  *
  * Flip the trace of a single CPU buffer between the @tr and the max_tr.
  */
@@ -1767,7 +1767,7 @@ static void __init apply_trace_boot_options(void);
 
 /**
  * register_tracer - register a tracer with the ftrace system.
- * @type - the plugin for the tracer
+ * @type: the plugin for the tracer
  *
  * Register a new plugin tracer.
  */
@@ -2230,9 +2230,9 @@ static bool tracing_record_taskinfo_skip(int flags)
 /**
  * tracing_record_taskinfo - record the task info of a task
  *
- * @task  - task to record
- * @flags - TRACE_RECORD_CMDLINE for recording comm
- *        - TRACE_RECORD_TGID for recording tgid
+ * @task task to record
+ * @flags: TRACE_RECORD_CMDLINE for recording comm
+ *         TRACE_RECORD_TGID for recording tgid
  */
 void tracing_record_taskinfo(struct task_struct *task, int flags)
 {
@@ -2258,10 +2258,10 @@ void tracing_record_taskinfo(struct task_struct *task, int flags)
 /**
  * tracing_record_taskinfo_sched_switch - record task info for sched_switch
  *
- * @prev - previous task during sched_switch
- * @next - next task during sched_switch
- * @flags - TRACE_RECORD_CMDLINE for recording comm
- *          TRACE_RECORD_TGID for recording tgid
+ * @prev: previous task during sched_switch
+ * @next: next task during sched_switch
+ * @flags: TRACE_RECORD_CMDLINE for recording comm
+ *         TRACE_RECORD_TGID for recording tgid
  */
 void tracing_record_taskinfo_sched_switch(struct task_struct *prev,
                                          struct task_struct *next, int flags)
@@ -3072,7 +3072,9 @@ static void trace_printk_start_stop_comm(int enabled)
 
 /**
  * trace_vbprintk - write binary msg to tracing buffer
- *
+ * @ip:    The address of the caller
+ * @fmt:   The string format to write to the buffer
+ * @args:  Arguments for @fmt
  */
 int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
 {
index c7506bc81b757f776ff690be99749ea1b8338e5f..648930823b571083c1a95000937962e565162eb2 100644 (file)
@@ -787,7 +787,7 @@ static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
        return ret;
 }
 
-static int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
+int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
 {
        char *event = NULL, *sub = NULL, *match;
        int ret;
index 69ebf3c2f1b5dd2e369232068f9074e0c48b4b48..78af97163147bf4d4fd3a7f5de85e2034fbd4c17 100644 (file)
@@ -137,6 +137,13 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
        if (trace_recursion_test(TRACE_GRAPH_NOTRACE_BIT))
                return 0;
 
+       /*
+        * Do not trace a function if it's filtered by set_graph_notrace.
+        * Make the index of ret stack negative to indicate that it should
+        * ignore further functions.  But it needs its own ret stack entry
+        * to recover the original index in order to continue tracing after
+        * returning from the function.
+        */
        if (ftrace_graph_notrace_addr(trace->func)) {
                trace_recursion_set(TRACE_GRAPH_NOTRACE_BIT);
                /*
@@ -155,16 +162,6 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
        if (ftrace_graph_ignore_irqs())
                return 0;
 
-       /*
-        * Do not trace a function if it's filtered by set_graph_notrace.
-        * Make the index of ret stack negative to indicate that it should
-        * ignore further functions.  But it needs its own ret stack entry
-        * to recover the original index in order to continue tracing after
-        * returning from the function.
-        */
-       if (ftrace_graph_notrace_addr(trace->func))
-               return 1;
-
        /*
         * Stop here if tracing_threshold is set. We only write function return
         * events to the ring buffer.
index dbef0d1350754c5404995811f31358bc39087400..fb6bfbc5bf862005e30f12b777c561e0bf09666a 100644 (file)
@@ -895,7 +895,8 @@ void trace_probe_cleanup(struct trace_probe *tp)
        for (i = 0; i < tp->nr_args; i++)
                traceprobe_free_probe_arg(&tp->args[i]);
 
-       kfree(call->class->system);
+       if (call->class)
+               kfree(call->class->system);
        kfree(call->name);
        kfree(call->print_fmt);
 }
index f33d66fc0e86d5741e42b352bcb9e3a94d944412..4e6b1c3e4c9814405922d47ee2d9ffe1eb3c5d3d 100644 (file)
@@ -631,6 +631,9 @@ config SBITMAP
 config PARMAN
        tristate "parman" if COMPILE_TEST
 
+config OBJAGG
+       tristate "objagg" if COMPILE_TEST
+
 config STRING_SELFTEST
        tristate "Test string functions"
 
@@ -653,6 +656,3 @@ config GENERIC_LIB_CMPDI2
 
 config GENERIC_LIB_UCMPDI2
        bool
-
-config OBJAGG
-       tristate "objagg" if COMPILE_TEST
index 4fafba1a923b67a2650a0265025e247829d3f9c6..7fa97a8b571778a1619940ab10a9a4bc9e96f823 100644 (file)
@@ -106,7 +106,6 @@ endchoice
 
 config KASAN_STACK_ENABLE
        bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && !COMPILE_TEST
-       default !(CLANG_VERSION < 90000)
        depends on KASAN
        help
          The LLVM stack address sanitizer has a know problem that
@@ -115,11 +114,11 @@ config KASAN_STACK_ENABLE
          Disabling asan-stack makes it safe to run kernels build
          with clang-8 with KASAN enabled, though it loses some of
          the functionality.
-         This feature is always disabled when compile-testing with clang-8
-         or earlier to avoid cluttering the output in stack overflow
-         warnings, but clang-8 users can still enable it for builds without
-         CONFIG_COMPILE_TEST.  On gcc and later clang versions it is
-         assumed to always be safe to use and enabled by default.
+         This feature is always disabled when compile-testing with clang
+         to avoid cluttering the output in stack overflow warnings,
+         but clang users can still enable it for builds without
+         CONFIG_COMPILE_TEST.  On gcc it is assumed to always be safe
+         to use and enabled by default.
 
 config KASAN_STACK
        int
index 095601ce371dabd7a7e5b3501c61ac4b6516d91b..29c02a924973afefc9a95cac47a6dfbcced66993 100644 (file)
@@ -279,7 +279,8 @@ obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
 obj-$(CONFIG_UBSAN) += ubsan.o
 
 UBSAN_SANITIZE_ubsan.o := n
-CFLAGS_ubsan.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector)
+KASAN_SANITIZE_ubsan.o := n
+CFLAGS_ubsan.o := $(call cc-option, -fno-stack-protector) $(DISABLE_STACKLEAK_PLUGIN)
 
 obj-$(CONFIG_SBITMAP) += sbitmap.o
 
index 439d641ec79648439999bcb9a93a11cece9c4566..38045d6d05381ebb89d73369b0c60766505ef9be 100644 (file)
@@ -74,8 +74,8 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
                                        delta_us);
        curr_stats->cpms = DIV_ROUND_UP(ncomps * USEC_PER_MSEC, delta_us);
        if (curr_stats->epms != 0)
-               curr_stats->cpe_ratio =
-                               (curr_stats->cpms * 100) / curr_stats->epms;
+               curr_stats->cpe_ratio = DIV_ROUND_DOWN_ULL(
+                       curr_stats->cpms * 100, curr_stats->epms);
        else
                curr_stats->cpe_ratio = 0;
 
index 5bcc902c53888d8feb90957d0e90e5ad91e562fc..a4db51c2126633c35c3f0ee789022a3562596b80 100644 (file)
@@ -5,6 +5,62 @@
 
 #include <linux/dim.h>
 
+/*
+ * Net DIM profiles:
+ *        There are different set of profiles for each CQ period mode.
+ *        There are different set of profiles for RX/TX CQs.
+ *        Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES
+ */
+#define NET_DIM_PARAMS_NUM_PROFILES 5
+#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
+#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128
+#define NET_DIM_DEF_PROFILE_CQE 1
+#define NET_DIM_DEF_PROFILE_EQE 1
+
+#define NET_DIM_RX_EQE_PROFILES { \
+       {1,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {8,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {64,  NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+}
+
+#define NET_DIM_RX_CQE_PROFILES { \
+       {2,  256},             \
+       {8,  128},             \
+       {16, 64},              \
+       {32, 64},              \
+       {64, 64}               \
+}
+
+#define NET_DIM_TX_EQE_PROFILES { \
+       {1,   NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
+       {8,   NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
+       {32,  NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
+       {64,  NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
+       {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}   \
+}
+
+#define NET_DIM_TX_CQE_PROFILES { \
+       {5,  128},  \
+       {8,  64},  \
+       {16, 32},  \
+       {32, 32},  \
+       {64, 32}   \
+}
+
+static const struct dim_cq_moder
+rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
+       NET_DIM_RX_EQE_PROFILES,
+       NET_DIM_RX_CQE_PROFILES,
+};
+
+static const struct dim_cq_moder
+tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
+       NET_DIM_TX_EQE_PROFILES,
+       NET_DIM_TX_CQE_PROFILES,
+};
+
 struct dim_cq_moder
 net_dim_get_rx_moderation(u8 cq_period_mode, int ix)
 {
index 117ad0e7fbf4913e8cd9d3f38d3a81bfe2420a65..70dab9ac78273f4cc50da6805dd9dfcf24ead42c 100644 (file)
@@ -68,7 +68,8 @@ int __kfifo_init(struct __kfifo *fifo, void *buffer,
 {
        size /= esize;
 
-       size = roundup_pow_of_two(size);
+       if (!is_power_of_2(size))
+               size = rounddown_pow_of_two(size);
 
        fifo->in = 0;
        fifo->out = 0;
index feea48fd1a0dd6ae7913b6fad19cc52e20664785..905027574e5d8041d1394dc4e5582061ed084e2f 100644 (file)
@@ -35,7 +35,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
        struct logic_pio_hwaddr *range;
        resource_size_t start;
        resource_size_t end;
-       resource_size_t mmio_sz = 0;
+       resource_size_t mmio_end = 0;
        resource_size_t iio_sz = MMIO_UPPER_LIMIT;
        int ret = 0;
 
@@ -46,7 +46,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
        end = new_range->hw_start + new_range->size;
 
        mutex_lock(&io_range_mutex);
-       list_for_each_entry_rcu(range, &io_range_list, list) {
+       list_for_each_entry(range, &io_range_list, list) {
                if (range->fwnode == new_range->fwnode) {
                        /* range already there */
                        goto end_register;
@@ -56,7 +56,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
                        /* for MMIO ranges we need to check for overlap */
                        if (start >= range->hw_start + range->size ||
                            end < range->hw_start) {
-                               mmio_sz += range->size;
+                               mmio_end = range->io_start + range->size;
                        } else {
                                ret = -EFAULT;
                                goto end_register;
@@ -69,16 +69,16 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
 
        /* range not registered yet, check for available space */
        if (new_range->flags == LOGIC_PIO_CPU_MMIO) {
-               if (mmio_sz + new_range->size - 1 > MMIO_UPPER_LIMIT) {
+               if (mmio_end + new_range->size - 1 > MMIO_UPPER_LIMIT) {
                        /* if it's too big check if 64K space can be reserved */
-                       if (mmio_sz + SZ_64K - 1 > MMIO_UPPER_LIMIT) {
+                       if (mmio_end + SZ_64K - 1 > MMIO_UPPER_LIMIT) {
                                ret = -E2BIG;
                                goto end_register;
                        }
                        new_range->size = SZ_64K;
                        pr_warn("Requested IO range too big, new size set to 64K\n");
                }
-               new_range->io_start = mmio_sz;
+               new_range->io_start = mmio_end;
        } else if (new_range->flags == LOGIC_PIO_INDIRECT) {
                if (iio_sz + new_range->size - 1 > IO_SPACE_LIMIT) {
                        ret = -E2BIG;
@@ -98,6 +98,20 @@ end_register:
        return ret;
 }
 
+/**
+ * logic_pio_unregister_range - unregister a logical PIO range for a host
+ * @range: pointer to the IO range which has been already registered.
+ *
+ * Unregister a previously-registered IO range node.
+ */
+void logic_pio_unregister_range(struct logic_pio_hwaddr *range)
+{
+       mutex_lock(&io_range_mutex);
+       list_del_rcu(&range->list);
+       mutex_unlock(&io_range_mutex);
+       synchronize_rcu();
+}
+
 /**
  * find_io_range_by_fwnode - find logical PIO range for given FW node
  * @fwnode: FW node handle associated with logical PIO range
@@ -108,26 +122,38 @@ end_register:
  */
 struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
 {
-       struct logic_pio_hwaddr *range;
+       struct logic_pio_hwaddr *range, *found_range = NULL;
 
+       rcu_read_lock();
        list_for_each_entry_rcu(range, &io_range_list, list) {
-               if (range->fwnode == fwnode)
-                       return range;
+               if (range->fwnode == fwnode) {
+                       found_range = range;
+                       break;
+               }
        }
-       return NULL;
+       rcu_read_unlock();
+
+       return found_range;
 }
 
 /* Return a registered range given an input PIO token */
 static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
 {
-       struct logic_pio_hwaddr *range;
+       struct logic_pio_hwaddr *range, *found_range = NULL;
 
+       rcu_read_lock();
        list_for_each_entry_rcu(range, &io_range_list, list) {
-               if (in_range(pio, range->io_start, range->size))
-                       return range;
+               if (in_range(pio, range->io_start, range->size)) {
+                       found_range = range;
+                       break;
+               }
        }
-       pr_err("PIO entry token %lx invalid\n", pio);
-       return NULL;
+       rcu_read_unlock();
+
+       if (!found_range)
+               pr_err("PIO entry token 0x%lx invalid\n", pio);
+
+       return found_range;
 }
 
 /**
@@ -180,14 +206,23 @@ unsigned long logic_pio_trans_cpuaddr(resource_size_t addr)
 {
        struct logic_pio_hwaddr *range;
 
+       rcu_read_lock();
        list_for_each_entry_rcu(range, &io_range_list, list) {
                if (range->flags != LOGIC_PIO_CPU_MMIO)
                        continue;
-               if (in_range(addr, range->hw_start, range->size))
-                       return addr - range->hw_start + range->io_start;
+               if (in_range(addr, range->hw_start, range->size)) {
+                       unsigned long cpuaddr;
+
+                       cpuaddr = addr - range->hw_start + range->io_start;
+
+                       rcu_read_unlock();
+                       return cpuaddr;
+               }
        }
-       pr_err("addr %llx not registered in io_range_list\n",
-              (unsigned long long) addr);
+       rcu_read_unlock();
+
+       pr_err("addr %pa not registered in io_range_list\n", &addr);
+
        return ~0UL;
 }
 
index 42695bc8d4515ff1da2c4926a72174516fb09e48..0083b5cc646c94a0c01ea3bd1de1652b8a57946b 100644 (file)
@@ -66,7 +66,7 @@ CFLAGS_vpermxor1.o += $(altivec_flags)
 CFLAGS_vpermxor2.o += $(altivec_flags)
 CFLAGS_vpermxor4.o += $(altivec_flags)
 CFLAGS_vpermxor8.o += $(altivec_flags)
-targets += vpermxor1.o vpermxor2.o vpermxor4.o vpermxor8.o
+targets += vpermxor1.c vpermxor2.c vpermxor4.c vpermxor8.c
 $(obj)/vpermxor%.c: $(src)/vpermxor.uc $(src)/unroll.awk FORCE
        $(call if_changed,unroll)
 
index 83ea6c4e623cf5a422dc40969a3f1ff1254e90d8..6ca97a63b3d6bea266032932704846b719c23b50 100644 (file)
@@ -886,8 +886,11 @@ static int __init test_firmware_init(void)
                return -ENOMEM;
 
        rc = __test_firmware_config_init();
-       if (rc)
+       if (rc) {
+               kfree(test_fw_config);
+               pr_err("could not init firmware test config: %d\n", rc);
                return rc;
+       }
 
        rc = misc_register(&test_fw_misc_device);
        if (rc) {
index 62d19f270cad4c75b9582abb5397e987c0aaca1c..9729f271d15041ac1930eb85922b81ba094a574f 100644 (file)
@@ -222,7 +222,7 @@ static int __init do_kmem_cache_size(size_t size, bool want_ctor,
                 * Copy the buffer to check that it's not wiped on
                 * free().
                 */
-               buf_copy = kmalloc(size, GFP_KERNEL);
+               buf_copy = kmalloc(size, GFP_ATOMIC);
                if (buf_copy)
                        memcpy(buf_copy, buf, size);
 
index 2d1c1f241fd9ec8828f5377616c445c663fe74db..e630e7ff57f1f9102e28820ef98f9c49e23da2ed 100644 (file)
@@ -51,7 +51,7 @@ static int do_hres(const struct vdso_data *vd, clockid_t clk,
                ns = vdso_ts->nsec;
                last = vd->cycle_last;
                if (unlikely((s64)cycles < 0))
-                       return clock_gettime_fallback(clk, ts);
+                       return -1;
 
                ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
                ns >>= vd->shift;
@@ -82,14 +82,14 @@ static void do_coarse(const struct vdso_data *vd, clockid_t clk,
 }
 
 static __maybe_unused int
-__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+__cvdso_clock_gettime_common(clockid_t clock, struct __kernel_timespec *ts)
 {
        const struct vdso_data *vd = __arch_get_vdso_data();
        u32 msk;
 
        /* Check for negative values or invalid clocks */
        if (unlikely((u32) clock >= MAX_CLOCKS))
-               goto fallback;
+               return -1;
 
        /*
         * Convert the clockid to a bitmask and use it to check which
@@ -104,9 +104,17 @@ __cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
        } else if (msk & VDSO_RAW) {
                return do_hres(&vd[CS_RAW], clock, ts);
        }
+       return -1;
+}
+
+static __maybe_unused int
+__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+{
+       int ret = __cvdso_clock_gettime_common(clock, ts);
 
-fallback:
-       return clock_gettime_fallback(clock, ts);
+       if (unlikely(ret))
+               return clock_gettime_fallback(clock, ts);
+       return 0;
 }
 
 static __maybe_unused int
@@ -115,20 +123,21 @@ __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
        struct __kernel_timespec ts;
        int ret;
 
-       if (res == NULL)
-               goto fallback;
+       ret = __cvdso_clock_gettime_common(clock, &ts);
 
-       ret = __cvdso_clock_gettime(clock, &ts);
+#ifdef VDSO_HAS_32BIT_FALLBACK
+       if (unlikely(ret))
+               return clock_gettime32_fallback(clock, res);
+#else
+       if (unlikely(ret))
+               ret = clock_gettime_fallback(clock, &ts);
+#endif
 
-       if (ret == 0) {
+       if (likely(!ret)) {
                res->tv_sec = ts.tv_sec;
                res->tv_nsec = ts.tv_nsec;
        }
-
        return ret;
-
-fallback:
-       return clock_gettime_fallback(clock, (struct __kernel_timespec *)res);
 }
 
 static __maybe_unused int
@@ -169,17 +178,18 @@ static __maybe_unused time_t __cvdso_time(time_t *time)
 
 #ifdef VDSO_HAS_CLOCK_GETRES
 static __maybe_unused
-int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res)
 {
        const struct vdso_data *vd = __arch_get_vdso_data();
-       u64 ns;
+       u64 hrtimer_res;
        u32 msk;
-       u64 hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
+       u64 ns;
 
        /* Check for negative values or invalid clocks */
        if (unlikely((u32) clock >= MAX_CLOCKS))
-               goto fallback;
+               return -1;
 
+       hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
        /*
         * Convert the clockid to a bitmask and use it to check which
         * clocks are handled in the VDSO directly.
@@ -201,18 +211,22 @@ int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
                 */
                ns = hrtimer_res;
        } else {
-               goto fallback;
+               return -1;
        }
 
-       if (res) {
-               res->tv_sec = 0;
-               res->tv_nsec = ns;
-       }
+       res->tv_sec = 0;
+       res->tv_nsec = ns;
 
        return 0;
+}
+
+int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+{
+       int ret = __cvdso_clock_getres_common(clock, res);
 
-fallback:
-       return clock_getres_fallback(clock, res);
+       if (unlikely(ret))
+               return clock_getres_fallback(clock, res);
+       return 0;
 }
 
 static __maybe_unused int
@@ -221,19 +235,20 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
        struct __kernel_timespec ts;
        int ret;
 
-       if (res == NULL)
-               goto fallback;
+       ret = __cvdso_clock_getres_common(clock, &ts);
 
-       ret = __cvdso_clock_getres(clock, &ts);
+#ifdef VDSO_HAS_32BIT_FALLBACK
+       if (unlikely(ret))
+               return clock_getres32_fallback(clock, res);
+#else
+       if (unlikely(ret))
+               ret = clock_getres_fallback(clock, &ts);
+#endif
 
-       if (ret == 0) {
+       if (likely(!ret)) {
                res->tv_sec = ts.tv_sec;
                res->tv_nsec = ts.tv_nsec;
        }
-
        return ret;
-
-fallback:
-       return clock_getres_fallback(clock, (struct __kernel_timespec *)res);
 }
 #endif /* VDSO_HAS_CLOCK_GETRES */
index 338e528ad4366f982298e9a8e59eba5e308fab32..d0b295c3b764bb753e4081b5847d6cef577f114d 100644 (file)
@@ -102,5 +102,6 @@ obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o
 obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o
 obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o
 obj-$(CONFIG_PERCPU_STATS) += percpu-stats.o
+obj-$(CONFIG_ZONE_DEVICE) += memremap.o
 obj-$(CONFIG_HMM_MIRROR) += hmm.o
 obj-$(CONFIG_MEMFD_CREATE) += memfd.o
index 83a7b614061f4027d030162d4237c4fdd5b0302e..26de020aae7b407c7ff5b1ae01eea92ad18d4e9e 100644 (file)
@@ -21,7 +21,6 @@ static void balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info,
         * memory corruption is possible and we should stop execution.
         */
        BUG_ON(!trylock_page(page));
-       list_del(&page->lru);
        balloon_page_insert(b_dev_info, page);
        unlock_page(page);
        __count_vm_event(BALLOON_INFLATE);
@@ -33,8 +32,8 @@ static void balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info,
  * @b_dev_info: balloon device descriptor where we will insert a new page to
  * @pages: pages to enqueue - allocated using balloon_page_alloc.
  *
- * Driver must call it to properly enqueue a balloon pages before definitively
- * removing it from the guest system.
+ * Driver must call this function to properly enqueue balloon pages before
+ * definitively removing them from the guest system.
  *
  * Return: number of pages that were enqueued.
  */
@@ -47,6 +46,7 @@ size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
 
        spin_lock_irqsave(&b_dev_info->pages_lock, flags);
        list_for_each_entry_safe(page, tmp, pages, lru) {
+               list_del(&page->lru);
                balloon_page_enqueue_one(b_dev_info, page);
                n_pages++;
        }
@@ -63,12 +63,13 @@ EXPORT_SYMBOL_GPL(balloon_page_list_enqueue);
  * @n_req_pages: number of requested pages.
  *
  * Driver must call this function to properly de-allocate a previous enlisted
- * balloon pages before definetively releasing it back to the guest system.
+ * balloon pages before definitively releasing it back to the guest system.
  * This function tries to remove @n_req_pages from the ballooned pages and
  * return them to the caller in the @pages list.
  *
- * Note that this function may fail to dequeue some pages temporarily empty due
- * to compaction isolated pages.
+ * Note that this function may fail to dequeue some pages even if the balloon
+ * isn't empty - since the page list can be temporarily empty due to compaction
+ * of isolated pages.
  *
  * Return: number of pages that were added to the @pages list.
  */
@@ -112,31 +113,35 @@ EXPORT_SYMBOL_GPL(balloon_page_list_dequeue);
 
 /*
  * balloon_page_alloc - allocates a new page for insertion into the balloon
- *                       page list.
+ *                     page list.
+ *
+ * Driver must call this function to properly allocate a new balloon page.
+ * Driver must call balloon_page_enqueue before definitively removing the page
+ * from the guest system.
  *
- * Driver must call it to properly allocate a new enlisted balloon page.
- * Driver must call balloon_page_enqueue before definitively removing it from
- * the guest system.  This function returns the page address for the recently
- * allocated page or NULL in the case we fail to allocate a new page this turn.
+ * Return: struct page for the allocated page or NULL on allocation failure.
  */
 struct page *balloon_page_alloc(void)
 {
        struct page *page = alloc_page(balloon_mapping_gfp_mask() |
-                                      __GFP_NOMEMALLOC | __GFP_NORETRY);
+                                      __GFP_NOMEMALLOC | __GFP_NORETRY |
+                                      __GFP_NOWARN);
        return page;
 }
 EXPORT_SYMBOL_GPL(balloon_page_alloc);
 
 /*
- * balloon_page_enqueue - allocates a new page and inserts it into the balloon
- *                       page list.
- * @b_dev_info: balloon device descriptor where we will insert a new page to
+ * balloon_page_enqueue - inserts a new page into the balloon page list.
+ *
+ * @b_dev_info: balloon device descriptor where we will insert a new page
  * @page: new page to enqueue - allocated using balloon_page_alloc.
  *
- * Driver must call it to properly enqueue a new allocated balloon page
- * before definitively removing it from the guest system.
- * This function returns the page address for the recently enqueued page or
- * NULL in the case we fail to allocate a new page this turn.
+ * Drivers must call this function to properly enqueue a new allocated balloon
+ * page before definitively removing the page from the guest system.
+ *
+ * Drivers must not call balloon_page_enqueue on pages that have been pushed to
+ * a list with balloon_page_push before removing them with balloon_page_pop. To
+ * enqueue a list of pages, use balloon_page_list_enqueue instead.
  */
 void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
                          struct page *page)
@@ -151,14 +156,23 @@ EXPORT_SYMBOL_GPL(balloon_page_enqueue);
 
 /*
  * balloon_page_dequeue - removes a page from balloon's page list and returns
- *                       the its address to allow the driver release the page.
+ *                       its address to allow the driver to release the page.
  * @b_dev_info: balloon device decriptor where we will grab a page from.
  *
- * Driver must call it to properly de-allocate a previous enlisted balloon page
- * before definetively releasing it back to the guest system.
- * This function returns the page address for the recently dequeued page or
- * NULL in the case we find balloon's page list temporarily empty due to
- * compaction isolated pages.
+ * Driver must call this function to properly dequeue a previously enqueued page
+ * before definitively releasing it back to the guest system.
+ *
+ * Caller must perform its own accounting to ensure that this
+ * function is called only if some pages are actually enqueued.
+ *
+ * Note that this function may fail to dequeue some pages even if there are
+ * some enqueued pages - since the page list can be temporarily empty due to
+ * the compaction of isolated pages.
+ *
+ * TODO: remove the caller accounting requirements, and allow caller to wait
+ * until all pages can be dequeued.
+ *
+ * Return: struct page for the dequeued page, or NULL if no page was dequeued.
  */
 struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
 {
@@ -171,9 +185,9 @@ struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
        if (n_pages != 1) {
                /*
                 * If we are unable to dequeue a balloon page because the page
-                * list is empty and there is no isolated pages, then something
+                * list is empty and there are no isolated pages, then something
                 * went out of track and some balloon pages are lost.
-                * BUG() here, otherwise the balloon driver may get stuck into
+                * BUG() here, otherwise the balloon driver may get stuck in
                 * an infinite loop while attempting to release all its pages.
                 */
                spin_lock_irqsave(&b_dev_info->pages_lock, flags);
@@ -224,8 +238,8 @@ int balloon_page_migrate(struct address_space *mapping,
 
        /*
         * We can not easily support the no copy case here so ignore it as it
-        * is unlikely to be use with ballon pages. See include/linux/hmm.h for
-        * user of the MIGRATE_SYNC_NO_COPY mode.
+        * is unlikely to be used with balloon pages. See include/linux/hmm.h
+        * for a user of the MIGRATE_SYNC_NO_COPY mode.
         */
        if (mode == MIGRATE_SYNC_NO_COPY)
                return -EINVAL;
index 9e1b9acb116b9b3efaabd8ee02538c20456b4714..952dc2fb24e50a26bee9621965ec6070b5d13346 100644 (file)
@@ -842,13 +842,15 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
 
                /*
                 * Periodically drop the lock (if held) regardless of its
-                * contention, to give chance to IRQs. Abort async compaction
-                * if contended.
+                * contention, to give chance to IRQs. Abort completely if
+                * a fatal signal is pending.
                 */
                if (!(low_pfn % SWAP_CLUSTER_MAX)
                    && compact_unlock_should_abort(&pgdat->lru_lock,
-                                           flags, &locked, cc))
-                       break;
+                                           flags, &locked, cc)) {
+                       low_pfn = 0;
+                       goto fatal_pending;
+               }
 
                if (!pfn_valid_within(low_pfn))
                        goto isolate_fail;
@@ -1060,6 +1062,7 @@ isolate_abort:
        trace_mm_compaction_isolate_migratepages(start_pfn, low_pfn,
                                                nr_scanned, nr_isolated);
 
+fatal_pending:
        cc->total_migrate_scanned += nr_scanned;
        if (nr_isolated)
                count_compact_events(COMPACTISOLATED, nr_isolated);
index e1eedef129cf5c3425cb5d709b42910cb5409e43..16b6731a34db79b46516ac74da8ec5c59a03e99c 100644 (file)
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -946,7 +946,7 @@ EXPORT_SYMBOL(hmm_range_unregister);
  * @range: range
  * Return: -EINVAL if invalid argument, -ENOMEM out of memory, -EPERM invalid
  *          permission (for instance asking for write and range is read only),
- *          -EAGAIN if you need to retry, -EFAULT invalid (ie either no valid
+ *          -EBUSY if you need to retry, -EFAULT invalid (ie either no valid
  *          vma or it is illegal to access that range), number of valid pages
  *          in range->pfns[] (from range start address).
  *
@@ -967,7 +967,7 @@ long hmm_range_snapshot(struct hmm_range *range)
        do {
                /* If range is no longer valid force retry. */
                if (!range->valid)
-                       return -EAGAIN;
+                       return -EBUSY;
 
                vma = find_vma(hmm->mm, start);
                if (vma == NULL || (vma->vm_flags & device_vma))
@@ -1062,10 +1062,8 @@ long hmm_range_fault(struct hmm_range *range, bool block)
 
        do {
                /* If range is no longer valid force retry. */
-               if (!range->valid) {
-                       up_read(&hmm->mm->mmap_sem);
-                       return -EAGAIN;
-               }
+               if (!range->valid)
+                       return -EBUSY;
 
                vma = find_vma(hmm->mm, start);
                if (vma == NULL || (vma->vm_flags & device_vma))
index 1334ede667a82aa1d5701526836c7f54487e9996..de1f15969e2782edd648a43fc5e7c6d7edacb38b 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/shmem_fs.h>
 #include <linux/oom.h>
 #include <linux/numa.h>
+#include <linux/page_owner.h>
 
 #include <asm/tlb.h>
 #include <asm/pgalloc.h>
@@ -644,30 +645,40 @@ release:
  *         available
  * never: never stall for any thp allocation
  */
-static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma)
+static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma, unsigned long addr)
 {
        const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
+       gfp_t this_node = 0;
+
+#ifdef CONFIG_NUMA
+       struct mempolicy *pol;
+       /*
+        * __GFP_THISNODE is used only when __GFP_DIRECT_RECLAIM is not
+        * specified, to express a general desire to stay on the current
+        * node for optimistic allocation attempts. If the defrag mode
+        * and/or madvise hint requires the direct reclaim then we prefer
+        * to fallback to other node rather than node reclaim because that
+        * can lead to excessive reclaim even though there is free memory
+        * on other nodes. We expect that NUMA preferences are specified
+        * by memory policies.
+        */
+       pol = get_vma_policy(vma, addr);
+       if (pol->mode != MPOL_BIND)
+               this_node = __GFP_THISNODE;
+       mpol_cond_put(pol);
+#endif
 
-       /* Always do synchronous compaction */
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
                return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
-
-       /* Kick kcompactd and fail quickly */
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
-
-       /* Synchronous compaction if madvised, otherwise kick kcompactd */
+               return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM | this_node;
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT |
-                       (vma_madvised ? __GFP_DIRECT_RECLAIM :
-                                       __GFP_KSWAPD_RECLAIM);
-
-       /* Only do synchronous compaction if madvised */
+               return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+                                                            __GFP_KSWAPD_RECLAIM | this_node);
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT |
-                      (vma_madvised ? __GFP_DIRECT_RECLAIM : 0);
-
-       return GFP_TRANSHUGE_LIGHT;
+               return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+                                                            this_node);
+       return GFP_TRANSHUGE_LIGHT | this_node;
 }
 
 /* Caller must hold page table lock. */
@@ -739,8 +750,8 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
                        pte_free(vma->vm_mm, pgtable);
                return ret;
        }
-       gfp = alloc_hugepage_direct_gfpmask(vma);
-       page = alloc_hugepage_vma(gfp, vma, haddr, HPAGE_PMD_ORDER);
+       gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
+       page = alloc_pages_vma(gfp, HPAGE_PMD_ORDER, vma, haddr, numa_node_id());
        if (unlikely(!page)) {
                count_vm_event(THP_FAULT_FALLBACK);
                return VM_FAULT_FALLBACK;
@@ -1347,8 +1358,9 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
 alloc:
        if (__transparent_hugepage_enabled(vma) &&
            !transparent_hugepage_debug_cow()) {
-               huge_gfp = alloc_hugepage_direct_gfpmask(vma);
-               new_page = alloc_hugepage_vma(huge_gfp, vma, haddr, HPAGE_PMD_ORDER);
+               huge_gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
+               new_page = alloc_pages_vma(huge_gfp, HPAGE_PMD_ORDER, vma,
+                               haddr, numa_node_id());
        } else
                new_page = NULL;
 
@@ -2505,6 +2517,9 @@ static void __split_huge_page(struct page *page, struct list_head *list,
        }
 
        ClearPageCompound(head);
+
+       split_page_owner(head, HPAGE_PMD_ORDER);
+
        /* See comment in __split_huge_page_tail() */
        if (PageAnon(head)) {
                /* Additional pin to swap cache */
index ede7e7f5d1ab2fec113507b5dabe78a7cdad8256..6d7296dd11b83503a511986814ba5d1f2a84b26b 100644 (file)
@@ -3856,6 +3856,25 @@ retry:
 
                page = alloc_huge_page(vma, haddr, 0);
                if (IS_ERR(page)) {
+                       /*
+                        * Returning error will result in faulting task being
+                        * sent SIGBUS.  The hugetlb fault mutex prevents two
+                        * tasks from racing to fault in the same page which
+                        * could result in false unable to allocate errors.
+                        * Page migration does not take the fault mutex, but
+                        * does a clear then write of pte's under page table
+                        * lock.  Page fault code could race with migration,
+                        * notice the clear pte and try to allocate a page
+                        * here.  Before returning error, get ptl and make
+                        * sure there really is no pte entry.
+                        */
+                       ptl = huge_pte_lock(h, mm, ptep);
+                       if (!huge_pte_none(huge_ptep_get(ptep))) {
+                               ret = 0;
+                               spin_unlock(ptl);
+                               goto out;
+                       }
+                       spin_unlock(ptl);
                        ret = vmf_error(PTR_ERR(page));
                        goto out;
                }
index 2277b82902d83a75fabfb9c2c2269315a6022b71..95d16a42db6bc731e11c9e86bb639bb277cc345d 100644 (file)
@@ -407,8 +407,14 @@ static inline bool shadow_invalid(u8 tag, s8 shadow_byte)
        if (IS_ENABLED(CONFIG_KASAN_GENERIC))
                return shadow_byte < 0 ||
                        shadow_byte >= KASAN_SHADOW_SCALE_SIZE;
-       else
-               return tag != (u8)shadow_byte;
+
+       /* else CONFIG_KASAN_SW_TAGS: */
+       if ((u8)shadow_byte == KASAN_TAG_INVALID)
+               return true;
+       if ((tag != KASAN_TAG_KERNEL) && (tag != (u8)shadow_byte))
+               return true;
+
+       return false;
 }
 
 static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
index dbbd518fb6b3e91dc298956f7abe842361369952..f6e602918dac84a96fe16a8e2c202505256bcb8d 100644 (file)
 /* GFP bitmask for kmemleak internal allocations */
 #define gfp_kmemleak_mask(gfp) (((gfp) & (GFP_KERNEL | GFP_ATOMIC)) | \
                                 __GFP_NORETRY | __GFP_NOMEMALLOC | \
-                                __GFP_NOWARN | __GFP_NOFAIL)
+                                __GFP_NOWARN)
 
 /* scanning area inside a memory block */
 struct kmemleak_scan_area {
@@ -1966,6 +1966,7 @@ static void kmemleak_disable(void)
 
        /* stop any memory operation tracing */
        kmemleak_enabled = 0;
+       kmemleak_early_log = 0;
 
        /* check whether it is too early for a kernel thread */
        if (kmemleak_initialized)
@@ -2009,7 +2010,6 @@ void __init kmemleak_init(void)
 
 #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
        if (!kmemleak_skip_disable) {
-               kmemleak_early_log = 0;
                kmemleak_disable();
                return;
        }
index cdbb7a84cb6e186242afeebb32f4c5c7fb2d0639..9ec5e12486a7805c8250f9a814be5036785c66b1 100644 (file)
@@ -752,15 +752,13 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
        /* Update memcg */
        __mod_memcg_state(memcg, idx, val);
 
+       /* Update lruvec */
+       __this_cpu_add(pn->lruvec_stat_local->count[idx], val);
+
        x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]);
        if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) {
                struct mem_cgroup_per_node *pi;
 
-               /*
-                * Batch local counters to keep them in sync with
-                * the hierarchical ones.
-                */
-               __this_cpu_add(pn->lruvec_stat_local->count[idx], x);
                for (pi = pn; pi; pi = parent_nodeinfo(pi, pgdat->node_id))
                        atomic_long_add(x, &pi->lruvec_stat[idx]);
                x = 0;
@@ -768,6 +766,26 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
        __this_cpu_write(pn->lruvec_stat_cpu->count[idx], x);
 }
 
+void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val)
+{
+       struct page *page = virt_to_head_page(p);
+       pg_data_t *pgdat = page_pgdat(page);
+       struct mem_cgroup *memcg;
+       struct lruvec *lruvec;
+
+       rcu_read_lock();
+       memcg = memcg_from_slab_page(page);
+
+       /* Untracked pages have no memcg, no lruvec. Update only the node */
+       if (!memcg || memcg == root_mem_cgroup) {
+               __mod_node_page_state(pgdat, idx, val);
+       } else {
+               lruvec = mem_cgroup_lruvec(pgdat, memcg);
+               __mod_lruvec_state(lruvec, idx, val);
+       }
+       rcu_read_unlock();
+}
+
 /**
  * __count_memcg_events - account VM events in a cgroup
  * @memcg: the memory cgroup
@@ -1130,26 +1148,45 @@ void mem_cgroup_iter_break(struct mem_cgroup *root,
                css_put(&prev->css);
 }
 
-static void invalidate_reclaim_iterators(struct mem_cgroup *dead_memcg)
+static void __invalidate_reclaim_iterators(struct mem_cgroup *from,
+                                       struct mem_cgroup *dead_memcg)
 {
-       struct mem_cgroup *memcg = dead_memcg;
        struct mem_cgroup_reclaim_iter *iter;
        struct mem_cgroup_per_node *mz;
        int nid;
        int i;
 
-       for (; memcg; memcg = parent_mem_cgroup(memcg)) {
-               for_each_node(nid) {
-                       mz = mem_cgroup_nodeinfo(memcg, nid);
-                       for (i = 0; i <= DEF_PRIORITY; i++) {
-                               iter = &mz->iter[i];
-                               cmpxchg(&iter->position,
-                                       dead_memcg, NULL);
-                       }
+       for_each_node(nid) {
+               mz = mem_cgroup_nodeinfo(from, nid);
+               for (i = 0; i <= DEF_PRIORITY; i++) {
+                       iter = &mz->iter[i];
+                       cmpxchg(&iter->position,
+                               dead_memcg, NULL);
                }
        }
 }
 
+static void invalidate_reclaim_iterators(struct mem_cgroup *dead_memcg)
+{
+       struct mem_cgroup *memcg = dead_memcg;
+       struct mem_cgroup *last;
+
+       do {
+               __invalidate_reclaim_iterators(memcg, dead_memcg);
+               last = memcg;
+       } while ((memcg = parent_mem_cgroup(memcg)));
+
+       /*
+        * When cgruop1 non-hierarchy mode is used,
+        * parent_mem_cgroup() does not walk all the way up to the
+        * cgroup root (root_mem_cgroup). So we have to handle
+        * dead_memcg from cgroup root separately.
+        */
+       if (last != root_mem_cgroup)
+               __invalidate_reclaim_iterators(root_mem_cgroup,
+                                               dead_memcg);
+}
+
 /**
  * mem_cgroup_scan_tasks - iterate over tasks of a memory cgroup hierarchy
  * @memcg: hierarchy root
@@ -3221,6 +3258,72 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
        }
 }
 
+static void memcg_flush_percpu_vmstats(struct mem_cgroup *memcg, bool slab_only)
+{
+       unsigned long stat[MEMCG_NR_STAT];
+       struct mem_cgroup *mi;
+       int node, cpu, i;
+       int min_idx, max_idx;
+
+       if (slab_only) {
+               min_idx = NR_SLAB_RECLAIMABLE;
+               max_idx = NR_SLAB_UNRECLAIMABLE;
+       } else {
+               min_idx = 0;
+               max_idx = MEMCG_NR_STAT;
+       }
+
+       for (i = min_idx; i < max_idx; i++)
+               stat[i] = 0;
+
+       for_each_online_cpu(cpu)
+               for (i = min_idx; i < max_idx; i++)
+                       stat[i] += per_cpu(memcg->vmstats_percpu->stat[i], cpu);
+
+       for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+               for (i = min_idx; i < max_idx; i++)
+                       atomic_long_add(stat[i], &mi->vmstats[i]);
+
+       if (!slab_only)
+               max_idx = NR_VM_NODE_STAT_ITEMS;
+
+       for_each_node(node) {
+               struct mem_cgroup_per_node *pn = memcg->nodeinfo[node];
+               struct mem_cgroup_per_node *pi;
+
+               for (i = min_idx; i < max_idx; i++)
+                       stat[i] = 0;
+
+               for_each_online_cpu(cpu)
+                       for (i = min_idx; i < max_idx; i++)
+                               stat[i] += per_cpu(
+                                       pn->lruvec_stat_cpu->count[i], cpu);
+
+               for (pi = pn; pi; pi = parent_nodeinfo(pi, node))
+                       for (i = min_idx; i < max_idx; i++)
+                               atomic_long_add(stat[i], &pi->lruvec_stat[i]);
+       }
+}
+
+static void memcg_flush_percpu_vmevents(struct mem_cgroup *memcg)
+{
+       unsigned long events[NR_VM_EVENT_ITEMS];
+       struct mem_cgroup *mi;
+       int cpu, i;
+
+       for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+               events[i] = 0;
+
+       for_each_online_cpu(cpu)
+               for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+                       events[i] += per_cpu(memcg->vmstats_percpu->events[i],
+                                            cpu);
+
+       for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
+               for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+                       atomic_long_add(events[i], &mi->vmevents[i]);
+}
+
 #ifdef CONFIG_MEMCG_KMEM
 static int memcg_online_kmem(struct mem_cgroup *memcg)
 {
@@ -3270,7 +3373,14 @@ static void memcg_offline_kmem(struct mem_cgroup *memcg)
        if (!parent)
                parent = root_mem_cgroup;
 
+       /*
+        * Deactivate and reparent kmem_caches. Then flush percpu
+        * slab statistics to have precise values at the parent and
+        * all ancestor levels. It's required to keep slab stats
+        * accurate after the reparenting of kmem_caches.
+        */
        memcg_deactivate_kmem_caches(memcg, parent);
+       memcg_flush_percpu_vmstats(memcg, true);
 
        kmemcg_id = memcg->kmemcg_id;
        BUG_ON(kmemcg_id < 0);
@@ -4643,6 +4753,12 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
 {
        int node;
 
+       /*
+        * Flush percpu vmstats and vmevents to guarantee the value correctness
+        * on parent's and all ancestor levels.
+        */
+       memcg_flush_percpu_vmstats(memcg, false);
+       memcg_flush_percpu_vmevents(memcg);
        for_each_node(node)
                free_mem_cgroup_per_node_info(memcg, node);
        free_percpu(memcg->vmstats_percpu);
index 2a9bbddb0e55427125e90dde4795b6460cdbdae1..c73f0991316511fb5471d3382f2d719c6cbfd759 100644 (file)
@@ -132,7 +132,6 @@ static void release_memory_resource(struct resource *res)
                return;
        release_resource(res);
        kfree(res);
-       return;
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
@@ -979,7 +978,6 @@ static void rollback_node_hotadd(int nid)
        arch_refresh_nodedata(nid, NULL);
        free_percpu(pgdat->per_cpu_nodestats);
        arch_free_nodedata(pgdat);
-       return;
 }
 
 
index f48693f75b37a0ece6ba8bf9c7ebb9a25ce3a7fd..65e0874fce1736a65f8ced74f2a94d3e23d718c9 100644 (file)
@@ -403,7 +403,7 @@ static const struct mempolicy_operations mpol_ops[MPOL_MAX] = {
        },
 };
 
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
                                unsigned long flags);
 
 struct queue_pages {
@@ -429,11 +429,14 @@ static inline bool queue_pages_required(struct page *page,
 }
 
 /*
- * queue_pages_pmd() has three possible return values:
- * 1 - pages are placed on the right node or queued successfully.
- * 0 - THP was split.
- * -EIO - is migration entry or MPOL_MF_STRICT was specified and an existing
- *        page was already on a node that does not follow the policy.
+ * queue_pages_pmd() has four possible return values:
+ * 0 - pages are placed on the right node or queued successfully.
+ * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ *     specified.
+ * 2 - THP was split.
+ * -EIO - is migration entry or only MPOL_MF_STRICT was specified and an
+ *        existing page was already on a node that does not follow the
+ *        policy.
  */
 static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
                                unsigned long end, struct mm_walk *walk)
@@ -451,23 +454,20 @@ static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
        if (is_huge_zero_page(page)) {
                spin_unlock(ptl);
                __split_huge_pmd(walk->vma, pmd, addr, false, NULL);
+               ret = 2;
                goto out;
        }
-       if (!queue_pages_required(page, qp)) {
-               ret = 1;
+       if (!queue_pages_required(page, qp))
                goto unlock;
-       }
 
-       ret = 1;
        flags = qp->flags;
        /* go to thp migration */
        if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-               if (!vma_migratable(walk->vma)) {
-                       ret = -EIO;
+               if (!vma_migratable(walk->vma) ||
+                   migrate_page_add(page, qp->pagelist, flags)) {
+                       ret = 1;
                        goto unlock;
                }
-
-               migrate_page_add(page, qp->pagelist, flags);
        } else
                ret = -EIO;
 unlock:
@@ -479,6 +479,13 @@ out:
 /*
  * Scan through pages checking if pages follow certain conditions,
  * and move them to the pagelist if they do.
+ *
+ * queue_pages_pte_range() has three possible return values:
+ * 0 - pages are placed on the right node or queued successfully.
+ * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ *     specified.
+ * -EIO - only MPOL_MF_STRICT was specified and an existing page was already
+ *        on a node that does not follow the policy.
  */
 static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
                        unsigned long end, struct mm_walk *walk)
@@ -488,17 +495,17 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
        struct queue_pages *qp = walk->private;
        unsigned long flags = qp->flags;
        int ret;
+       bool has_unmovable = false;
        pte_t *pte;
        spinlock_t *ptl;
 
        ptl = pmd_trans_huge_lock(pmd, vma);
        if (ptl) {
                ret = queue_pages_pmd(pmd, ptl, addr, end, walk);
-               if (ret > 0)
-                       return 0;
-               else if (ret < 0)
+               if (ret != 2)
                        return ret;
        }
+       /* THP was split, fall through to pte walk */
 
        if (pmd_trans_unstable(pmd))
                return 0;
@@ -519,14 +526,28 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
                if (!queue_pages_required(page, qp))
                        continue;
                if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-                       if (!vma_migratable(vma))
+                       /* MPOL_MF_STRICT must be specified if we get here */
+                       if (!vma_migratable(vma)) {
+                               has_unmovable = true;
                                break;
-                       migrate_page_add(page, qp->pagelist, flags);
+                       }
+
+                       /*
+                        * Do not abort immediately since there may be
+                        * temporary off LRU pages in the range.  Still
+                        * need migrate other LRU pages.
+                        */
+                       if (migrate_page_add(page, qp->pagelist, flags))
+                               has_unmovable = true;
                } else
                        break;
        }
        pte_unmap_unlock(pte - 1, ptl);
        cond_resched();
+
+       if (has_unmovable)
+               return 1;
+
        return addr != end ? -EIO : 0;
 }
 
@@ -639,7 +660,13 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end,
  *
  * If pages found in a given range are on a set of nodes (determined by
  * @nodes and @flags,) it's isolated and queued to the pagelist which is
- * passed via @private.)
+ * passed via @private.
+ *
+ * queue_pages_range() has three possible return values:
+ * 1 - there is unmovable page, but MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ *     specified.
+ * 0 - queue pages successfully or no misplaced page.
+ * -EIO - there is misplaced page and only MPOL_MF_STRICT was specified.
  */
 static int
 queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
@@ -940,7 +967,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
 /*
  * page migration, thp tail pages can be passed.
  */
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
                                unsigned long flags)
 {
        struct page *head = compound_head(page);
@@ -953,8 +980,19 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
                        mod_node_page_state(page_pgdat(head),
                                NR_ISOLATED_ANON + page_is_file_cache(head),
                                hpage_nr_pages(head));
+               } else if (flags & MPOL_MF_STRICT) {
+                       /*
+                        * Non-movable page may reach here.  And, there may be
+                        * temporary off LRU pages or non-LRU movable pages.
+                        * Treat them as unmovable pages since they can't be
+                        * isolated, so they can't be moved at the moment.  It
+                        * should return -EIO for this case too.
+                        */
+                       return -EIO;
                }
        }
+
+       return 0;
 }
 
 /* page allocation callback for NUMA node migration */
@@ -1142,8 +1180,8 @@ static struct page *new_page(struct page *page, unsigned long start)
        } else if (PageTransHuge(page)) {
                struct page *thp;
 
-               thp = alloc_hugepage_vma(GFP_TRANSHUGE, vma, address,
-                                        HPAGE_PMD_ORDER);
+               thp = alloc_pages_vma(GFP_TRANSHUGE, HPAGE_PMD_ORDER, vma,
+                               address, numa_node_id());
                if (!thp)
                        return NULL;
                prep_transhuge_page(thp);
@@ -1157,9 +1195,10 @@ static struct page *new_page(struct page *page, unsigned long start)
 }
 #else
 
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
                                unsigned long flags)
 {
+       return -EIO;
 }
 
 int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
@@ -1182,6 +1221,7 @@ static long do_mbind(unsigned long start, unsigned long len,
        struct mempolicy *new;
        unsigned long end;
        int err;
+       int ret;
        LIST_HEAD(pagelist);
 
        if (flags & ~(unsigned long)MPOL_MF_VALID)
@@ -1243,10 +1283,15 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (err)
                goto mpol_out;
 
-       err = queue_pages_range(mm, start, end, nmask,
+       ret = queue_pages_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
-       if (!err)
-               err = mbind_range(mm, start, end, new);
+
+       if (ret < 0) {
+               err = -EIO;
+               goto up_out;
+       }
+
+       err = mbind_range(mm, start, end, new);
 
        if (!err) {
                int nr_failed = 0;
@@ -1259,13 +1304,14 @@ static long do_mbind(unsigned long start, unsigned long len,
                                putback_movable_pages(&pagelist);
                }
 
-               if (nr_failed && (flags & MPOL_MF_STRICT))
+               if ((ret > 0) || (nr_failed && (flags & MPOL_MF_STRICT)))
                        err = -EIO;
        } else
                putback_movable_pages(&pagelist);
 
+up_out:
        up_write(&mm->mmap_sem);
- mpol_out:
+mpol_out:
        mpol_put(new);
        return err;
 }
@@ -1688,7 +1734,7 @@ struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
  * freeing by another task.  It is the caller's responsibility to free the
  * extra reference for shared policies.
  */
-static struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
+struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
                                                unsigned long addr)
 {
        struct mempolicy *pol = __get_vma_policy(vma, addr);
@@ -2037,7 +2083,6 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
  *     @vma:  Pointer to VMA or NULL if not available.
  *     @addr: Virtual Address of the allocation. Must be inside the VMA.
  *     @node: Which node to prefer for allocation (modulo policy).
- *     @hugepage: for hugepages try only the preferred node if possible
  *
  *     This function allocates a page from the kernel page pool and applies
  *     a NUMA policy associated with the VMA or the current process.
@@ -2048,7 +2093,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
  */
 struct page *
 alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
-               unsigned long addr, int node, bool hugepage)
+               unsigned long addr, int node)
 {
        struct mempolicy *pol;
        struct page *page;
@@ -2066,31 +2111,6 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
                goto out;
        }
 
-       if (unlikely(IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hugepage)) {
-               int hpage_node = node;
-
-               /*
-                * For hugepage allocation and non-interleave policy which
-                * allows the current node (or other explicitly preferred
-                * node) we only try to allocate from the current/preferred
-                * node and don't fall back to other nodes, as the cost of
-                * remote accesses would likely offset THP benefits.
-                *
-                * If the policy is interleave, or does not allow the current
-                * node in its nodemask, we allocate the standard way.
-                */
-               if (pol->mode == MPOL_PREFERRED && !(pol->flags & MPOL_F_LOCAL))
-                       hpage_node = pol->v.preferred_node;
-
-               nmask = policy_nodemask(gfp, pol);
-               if (!nmask || node_isset(hpage_node, *nmask)) {
-                       mpol_cond_put(pol);
-                       page = __alloc_pages_node(hpage_node,
-                                               gfp | __GFP_THISNODE, order);
-                       goto out;
-               }
-       }
-
        nmask = policy_nodemask(gfp, pol);
        preferred_nid = policy_node(gfp, pol, node);
        page = __alloc_pages_nodemask(gfp, order, preferred_nid, nmask);
diff --git a/mm/memremap.c b/mm/memremap.c
new file mode 100644 (file)
index 0000000..ed70c4e
--- /dev/null
@@ -0,0 +1,435 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2015 Intel Corporation. All rights reserved. */
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kasan.h>
+#include <linux/memory_hotplug.h>
+#include <linux/mm.h>
+#include <linux/pfn_t.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
+#include <linux/types.h>
+#include <linux/wait_bit.h>
+#include <linux/xarray.h>
+
+static DEFINE_XARRAY(pgmap_array);
+#define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1)
+#define SECTION_SIZE (1UL << PA_SECTION_SHIFT)
+
+#ifdef CONFIG_DEV_PAGEMAP_OPS
+DEFINE_STATIC_KEY_FALSE(devmap_managed_key);
+EXPORT_SYMBOL(devmap_managed_key);
+static atomic_t devmap_managed_enable;
+
+static void devmap_managed_enable_put(void *data)
+{
+       if (atomic_dec_and_test(&devmap_managed_enable))
+               static_branch_disable(&devmap_managed_key);
+}
+
+static int devmap_managed_enable_get(struct device *dev, struct dev_pagemap *pgmap)
+{
+       if (!pgmap->ops || !pgmap->ops->page_free) {
+               WARN(1, "Missing page_free method\n");
+               return -EINVAL;
+       }
+
+       if (atomic_inc_return(&devmap_managed_enable) == 1)
+               static_branch_enable(&devmap_managed_key);
+       return devm_add_action_or_reset(dev, devmap_managed_enable_put, NULL);
+}
+#else
+static int devmap_managed_enable_get(struct device *dev, struct dev_pagemap *pgmap)
+{
+       return -EINVAL;
+}
+#endif /* CONFIG_DEV_PAGEMAP_OPS */
+
+static void pgmap_array_delete(struct resource *res)
+{
+       xa_store_range(&pgmap_array, PHYS_PFN(res->start), PHYS_PFN(res->end),
+                       NULL, GFP_KERNEL);
+       synchronize_rcu();
+}
+
+static unsigned long pfn_first(struct dev_pagemap *pgmap)
+{
+       return PHYS_PFN(pgmap->res.start) +
+               vmem_altmap_offset(pgmap_altmap(pgmap));
+}
+
+static unsigned long pfn_end(struct dev_pagemap *pgmap)
+{
+       const struct resource *res = &pgmap->res;
+
+       return (res->start + resource_size(res)) >> PAGE_SHIFT;
+}
+
+static unsigned long pfn_next(unsigned long pfn)
+{
+       if (pfn % 1024 == 0)
+               cond_resched();
+       return pfn + 1;
+}
+
+#define for_each_device_pfn(pfn, map) \
+       for (pfn = pfn_first(map); pfn < pfn_end(map); pfn = pfn_next(pfn))
+
+static void dev_pagemap_kill(struct dev_pagemap *pgmap)
+{
+       if (pgmap->ops && pgmap->ops->kill)
+               pgmap->ops->kill(pgmap);
+       else
+               percpu_ref_kill(pgmap->ref);
+}
+
+static void dev_pagemap_cleanup(struct dev_pagemap *pgmap)
+{
+       if (pgmap->ops && pgmap->ops->cleanup) {
+               pgmap->ops->cleanup(pgmap);
+       } else {
+               wait_for_completion(&pgmap->done);
+               percpu_ref_exit(pgmap->ref);
+       }
+       /*
+        * Undo the pgmap ref assignment for the internal case as the
+        * caller may re-enable the same pgmap.
+        */
+       if (pgmap->ref == &pgmap->internal_ref)
+               pgmap->ref = NULL;
+}
+
+static void devm_memremap_pages_release(void *data)
+{
+       struct dev_pagemap *pgmap = data;
+       struct device *dev = pgmap->dev;
+       struct resource *res = &pgmap->res;
+       unsigned long pfn;
+       int nid;
+
+       dev_pagemap_kill(pgmap);
+       for_each_device_pfn(pfn, pgmap)
+               put_page(pfn_to_page(pfn));
+       dev_pagemap_cleanup(pgmap);
+
+       /* pages are dead and unused, undo the arch mapping */
+       nid = page_to_nid(pfn_to_page(PHYS_PFN(res->start)));
+
+       mem_hotplug_begin();
+       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
+               pfn = PHYS_PFN(res->start);
+               __remove_pages(page_zone(pfn_to_page(pfn)), pfn,
+                                PHYS_PFN(resource_size(res)), NULL);
+       } else {
+               arch_remove_memory(nid, res->start, resource_size(res),
+                               pgmap_altmap(pgmap));
+               kasan_remove_zero_shadow(__va(res->start), resource_size(res));
+       }
+       mem_hotplug_done();
+
+       untrack_pfn(NULL, PHYS_PFN(res->start), resource_size(res));
+       pgmap_array_delete(res);
+       dev_WARN_ONCE(dev, pgmap->altmap.alloc,
+                     "%s: failed to free all reserved pages\n", __func__);
+}
+
+static void dev_pagemap_percpu_release(struct percpu_ref *ref)
+{
+       struct dev_pagemap *pgmap =
+               container_of(ref, struct dev_pagemap, internal_ref);
+
+       complete(&pgmap->done);
+}
+
+/**
+ * devm_memremap_pages - remap and provide memmap backing for the given resource
+ * @dev: hosting device for @res
+ * @pgmap: pointer to a struct dev_pagemap
+ *
+ * Notes:
+ * 1/ At a minimum the res and type members of @pgmap must be initialized
+ *    by the caller before passing it to this function
+ *
+ * 2/ The altmap field may optionally be initialized, in which case
+ *    PGMAP_ALTMAP_VALID must be set in pgmap->flags.
+ *
+ * 3/ The ref field may optionally be provided, in which pgmap->ref must be
+ *    'live' on entry and will be killed and reaped at
+ *    devm_memremap_pages_release() time, or if this routine fails.
+ *
+ * 4/ res is expected to be a host memory range that could feasibly be
+ *    treated as a "System RAM" range, i.e. not a device mmio range, but
+ *    this is not enforced.
+ */
+void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
+{
+       struct resource *res = &pgmap->res;
+       struct dev_pagemap *conflict_pgmap;
+       struct mhp_restrictions restrictions = {
+               /*
+                * We do not want any optional features only our own memmap
+                */
+               .altmap = pgmap_altmap(pgmap),
+       };
+       pgprot_t pgprot = PAGE_KERNEL;
+       int error, nid, is_ram;
+       bool need_devmap_managed = true;
+
+       switch (pgmap->type) {
+       case MEMORY_DEVICE_PRIVATE:
+               if (!IS_ENABLED(CONFIG_DEVICE_PRIVATE)) {
+                       WARN(1, "Device private memory not supported\n");
+                       return ERR_PTR(-EINVAL);
+               }
+               if (!pgmap->ops || !pgmap->ops->migrate_to_ram) {
+                       WARN(1, "Missing migrate_to_ram method\n");
+                       return ERR_PTR(-EINVAL);
+               }
+               break;
+       case MEMORY_DEVICE_FS_DAX:
+               if (!IS_ENABLED(CONFIG_ZONE_DEVICE) ||
+                   IS_ENABLED(CONFIG_FS_DAX_LIMITED)) {
+                       WARN(1, "File system DAX not supported\n");
+                       return ERR_PTR(-EINVAL);
+               }
+               break;
+       case MEMORY_DEVICE_DEVDAX:
+       case MEMORY_DEVICE_PCI_P2PDMA:
+               need_devmap_managed = false;
+               break;
+       default:
+               WARN(1, "Invalid pgmap type %d\n", pgmap->type);
+               break;
+       }
+
+       if (!pgmap->ref) {
+               if (pgmap->ops && (pgmap->ops->kill || pgmap->ops->cleanup))
+                       return ERR_PTR(-EINVAL);
+
+               init_completion(&pgmap->done);
+               error = percpu_ref_init(&pgmap->internal_ref,
+                               dev_pagemap_percpu_release, 0, GFP_KERNEL);
+               if (error)
+                       return ERR_PTR(error);
+               pgmap->ref = &pgmap->internal_ref;
+       } else {
+               if (!pgmap->ops || !pgmap->ops->kill || !pgmap->ops->cleanup) {
+                       WARN(1, "Missing reference count teardown definition\n");
+                       return ERR_PTR(-EINVAL);
+               }
+       }
+
+       if (need_devmap_managed) {
+               error = devmap_managed_enable_get(dev, pgmap);
+               if (error)
+                       return ERR_PTR(error);
+       }
+
+       conflict_pgmap = get_dev_pagemap(PHYS_PFN(res->start), NULL);
+       if (conflict_pgmap) {
+               dev_WARN(dev, "Conflicting mapping in same section\n");
+               put_dev_pagemap(conflict_pgmap);
+               error = -ENOMEM;
+               goto err_array;
+       }
+
+       conflict_pgmap = get_dev_pagemap(PHYS_PFN(res->end), NULL);
+       if (conflict_pgmap) {
+               dev_WARN(dev, "Conflicting mapping in same section\n");
+               put_dev_pagemap(conflict_pgmap);
+               error = -ENOMEM;
+               goto err_array;
+       }
+
+       is_ram = region_intersects(res->start, resource_size(res),
+               IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
+
+       if (is_ram != REGION_DISJOINT) {
+               WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
+                               is_ram == REGION_MIXED ? "mixed" : "ram", res);
+               error = -ENXIO;
+               goto err_array;
+       }
+
+       pgmap->dev = dev;
+
+       error = xa_err(xa_store_range(&pgmap_array, PHYS_PFN(res->start),
+                               PHYS_PFN(res->end), pgmap, GFP_KERNEL));
+       if (error)
+               goto err_array;
+
+       nid = dev_to_node(dev);
+       if (nid < 0)
+               nid = numa_mem_id();
+
+       error = track_pfn_remap(NULL, &pgprot, PHYS_PFN(res->start), 0,
+                       resource_size(res));
+       if (error)
+               goto err_pfn_remap;
+
+       mem_hotplug_begin();
+
+       /*
+        * For device private memory we call add_pages() as we only need to
+        * allocate and initialize struct page for the device memory. More-
+        * over the device memory is un-accessible thus we do not want to
+        * create a linear mapping for the memory like arch_add_memory()
+        * would do.
+        *
+        * For all other device memory types, which are accessible by
+        * the CPU, we do want the linear mapping and thus use
+        * arch_add_memory().
+        */
+       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
+               error = add_pages(nid, PHYS_PFN(res->start),
+                               PHYS_PFN(resource_size(res)), &restrictions);
+       } else {
+               error = kasan_add_zero_shadow(__va(res->start), resource_size(res));
+               if (error) {
+                       mem_hotplug_done();
+                       goto err_kasan;
+               }
+
+               error = arch_add_memory(nid, res->start, resource_size(res),
+                                       &restrictions);
+       }
+
+       if (!error) {
+               struct zone *zone;
+
+               zone = &NODE_DATA(nid)->node_zones[ZONE_DEVICE];
+               move_pfn_range_to_zone(zone, PHYS_PFN(res->start),
+                               PHYS_PFN(resource_size(res)), restrictions.altmap);
+       }
+
+       mem_hotplug_done();
+       if (error)
+               goto err_add_memory;
+
+       /*
+        * Initialization of the pages has been deferred until now in order
+        * to allow us to do the work while not holding the hotplug lock.
+        */
+       memmap_init_zone_device(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
+                               PHYS_PFN(res->start),
+                               PHYS_PFN(resource_size(res)), pgmap);
+       percpu_ref_get_many(pgmap->ref, pfn_end(pgmap) - pfn_first(pgmap));
+
+       error = devm_add_action_or_reset(dev, devm_memremap_pages_release,
+                       pgmap);
+       if (error)
+               return ERR_PTR(error);
+
+       return __va(res->start);
+
+ err_add_memory:
+       kasan_remove_zero_shadow(__va(res->start), resource_size(res));
+ err_kasan:
+       untrack_pfn(NULL, PHYS_PFN(res->start), resource_size(res));
+ err_pfn_remap:
+       pgmap_array_delete(res);
+ err_array:
+       dev_pagemap_kill(pgmap);
+       dev_pagemap_cleanup(pgmap);
+       return ERR_PTR(error);
+}
+EXPORT_SYMBOL_GPL(devm_memremap_pages);
+
+void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap)
+{
+       devm_release_action(dev, devm_memremap_pages_release, pgmap);
+}
+EXPORT_SYMBOL_GPL(devm_memunmap_pages);
+
+unsigned long vmem_altmap_offset(struct vmem_altmap *altmap)
+{
+       /* number of pfns from base where pfn_to_page() is valid */
+       if (altmap)
+               return altmap->reserve + altmap->free;
+       return 0;
+}
+
+void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns)
+{
+       altmap->alloc -= nr_pfns;
+}
+
+/**
+ * get_dev_pagemap() - take a new live reference on the dev_pagemap for @pfn
+ * @pfn: page frame number to lookup page_map
+ * @pgmap: optional known pgmap that already has a reference
+ *
+ * If @pgmap is non-NULL and covers @pfn it will be returned as-is.  If @pgmap
+ * is non-NULL but does not cover @pfn the reference to it will be released.
+ */
+struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
+               struct dev_pagemap *pgmap)
+{
+       resource_size_t phys = PFN_PHYS(pfn);
+
+       /*
+        * In the cached case we're already holding a live reference.
+        */
+       if (pgmap) {
+               if (phys >= pgmap->res.start && phys <= pgmap->res.end)
+                       return pgmap;
+               put_dev_pagemap(pgmap);
+       }
+
+       /* fall back to slow path lookup */
+       rcu_read_lock();
+       pgmap = xa_load(&pgmap_array, PHYS_PFN(phys));
+       if (pgmap && !percpu_ref_tryget_live(pgmap->ref))
+               pgmap = NULL;
+       rcu_read_unlock();
+
+       return pgmap;
+}
+EXPORT_SYMBOL_GPL(get_dev_pagemap);
+
+#ifdef CONFIG_DEV_PAGEMAP_OPS
+void __put_devmap_managed_page(struct page *page)
+{
+       int count = page_ref_dec_return(page);
+
+       /*
+        * If refcount is 1 then page is freed and refcount is stable as nobody
+        * holds a reference on the page.
+        */
+       if (count == 1) {
+               /* Clear Active bit in case of parallel mark_page_accessed */
+               __ClearPageActive(page);
+               __ClearPageWaiters(page);
+
+               mem_cgroup_uncharge(page);
+
+               /*
+                * When a device_private page is freed, the page->mapping field
+                * may still contain a (stale) mapping value. For example, the
+                * lower bits of page->mapping may still identify the page as
+                * an anonymous page. Ultimately, this entire field is just
+                * stale and wrong, and it will cause errors if not cleared.
+                * One example is:
+                *
+                *  migrate_vma_pages()
+                *    migrate_vma_insert_page()
+                *      page_add_new_anon_rmap()
+                *        __page_set_anon_rmap()
+                *          ...checks page->mapping, via PageAnon(page) call,
+                *            and incorrectly concludes that the page is an
+                *            anonymous page. Therefore, it incorrectly,
+                *            silently fails to set up the new anon rmap.
+                *
+                * For other types of ZONE_DEVICE pages, migration is either
+                * handled differently or not done at all, so there is no need
+                * to clear page->mapping.
+                */
+               if (is_device_private_page(page))
+                       page->mapping = NULL;
+
+               page->pgmap->ops->page_free(page);
+       } else if (!count)
+               __put_page(page);
+}
+EXPORT_SYMBOL(__put_devmap_managed_page);
+#endif /* CONFIG_DEV_PAGEMAP_OPS */
index 8992741f10aad4bb1e56c4635ef84aac57176550..a42858d8e00b7bae8d43e9746fb786a16a64e809 100644 (file)
@@ -767,12 +767,12 @@ recheck_buffers:
                        }
                        bh = bh->b_this_page;
                } while (bh != head);
-               spin_unlock(&mapping->private_lock);
                if (busy) {
                        if (invalidated) {
                                rc = -EAGAIN;
                                goto unlock_buffers;
                        }
+                       spin_unlock(&mapping->private_lock);
                        invalidate_bh_lrus();
                        invalidated = true;
                        goto recheck_buffers;
@@ -805,6 +805,8 @@ recheck_buffers:
 
        rc = MIGRATEPAGE_SUCCESS;
 unlock_buffers:
+       if (check_refs)
+               spin_unlock(&mapping->private_lock);
        bh = head;
        do {
                unlock_buffer(bh);
@@ -2338,16 +2340,13 @@ next:
 static void migrate_vma_collect(struct migrate_vma *migrate)
 {
        struct mmu_notifier_range range;
-       struct mm_walk mm_walk;
-
-       mm_walk.pmd_entry = migrate_vma_collect_pmd;
-       mm_walk.pte_entry = NULL;
-       mm_walk.pte_hole = migrate_vma_collect_hole;
-       mm_walk.hugetlb_entry = NULL;
-       mm_walk.test_walk = NULL;
-       mm_walk.vma = migrate->vma;
-       mm_walk.mm = migrate->vma->vm_mm;
-       mm_walk.private = migrate;
+       struct mm_walk mm_walk = {
+               .pmd_entry = migrate_vma_collect_pmd,
+               .pte_hole = migrate_vma_collect_hole,
+               .vma = migrate->vma,
+               .mm = migrate->vma->vm_mm,
+               .private = migrate,
+       };
 
        mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm_walk.mm,
                                migrate->start,
index 272c6de1bf4ead31c22aca202940da00bc8eaf8b..9c9194959271cfc0d9214bf60bb09b96c5b1a96a 100644 (file)
@@ -2238,27 +2238,12 @@ static int move_freepages(struct zone *zone,
        unsigned int order;
        int pages_moved = 0;
 
-#ifndef CONFIG_HOLES_IN_ZONE
-       /*
-        * page_zone is not safe to call in this context when
-        * CONFIG_HOLES_IN_ZONE is set. This bug check is probably redundant
-        * anyway as we check zone boundaries in move_freepages_block().
-        * Remove at a later date when no bug reports exist related to
-        * grouping pages by mobility
-        */
-       VM_BUG_ON(pfn_valid(page_to_pfn(start_page)) &&
-                 pfn_valid(page_to_pfn(end_page)) &&
-                 page_zone(start_page) != page_zone(end_page));
-#endif
        for (page = start_page; page <= end_page;) {
                if (!pfn_valid_within(page_to_pfn(page))) {
                        page++;
                        continue;
                }
 
-               /* Make sure we are not inadvertently changing nodes */
-               VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
-
                if (!PageBuddy(page)) {
                        /*
                         * We assume that pages that could be isolated for
@@ -2273,6 +2258,10 @@ static int move_freepages(struct zone *zone,
                        continue;
                }
 
+               /* Make sure we are not inadvertently changing nodes */
+               VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
+               VM_BUG_ON_PAGE(page_zone(page) != zone, page);
+
                order = page_order(page);
                move_to_free_area(page, &zone->free_area[order], migratetype);
                page += 1 << order;
index e5dfe2ae6b0d5dfc4a0b38c58c8e2c762b0b7696..003377e2423232614525ae2e6cbdda9695aca75b 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1475,7 +1475,15 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                        /*
                         * No need to invalidate here it will synchronize on
                         * against the special swap migration pte.
+                        *
+                        * The assignment to subpage above was computed from a
+                        * swap PTE which results in an invalid pointer.
+                        * Since only PAGE_SIZE pages can currently be
+                        * migrated, just set it to page. This will need to be
+                        * changed when hugepage migrations to device private
+                        * memory are supported.
                         */
+                       subpage = page;
                        goto discard;
                }
 
index 626d8c74b973f173d3062ee118580b649d35073a..2bed4761f2795695b2e970c304f8985aeacef9f6 100644 (file)
@@ -1466,7 +1466,7 @@ static struct page *shmem_alloc_hugepage(gfp_t gfp,
 
        shmem_pseudo_vma_init(&pvma, info, hindex);
        page = alloc_pages_vma(gfp | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN,
-                       HPAGE_PMD_ORDER, &pvma, 0, numa_node_id(), true);
+                       HPAGE_PMD_ORDER, &pvma, 0, numa_node_id());
        shmem_pseudo_vma_destroy(&pvma);
        if (page)
                prep_transhuge_page(page);
index e6c030e473649b7a0ee94cea464d46f6c352ea9d..8834563cdb4bd4bedc4c59fad15de6afa6850717 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1432,7 +1432,9 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
        void *old_tail = *tail ? *tail : *head;
        int rsize;
 
-       if (slab_want_init_on_free(s))
+       if (slab_want_init_on_free(s)) {
+               void *p = NULL;
+
                do {
                        object = next;
                        next = get_freepointer(s, object);
@@ -1445,8 +1447,10 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
                                                           : 0;
                        memset((char *)object + s->inuse, 0,
                               s->size - s->inuse - rsize);
-                       set_freepointer(s, object, next);
+                       set_freepointer(s, object, p);
+                       p = object;
                } while (object != old_tail);
+       }
 
 /*
  * Compiler cannot detect this function can be removed if slab_free_hook()
index 2a09796edef8d53d257dedada5b1a40bc21b4c16..98e924864554c5dbbd4804f51af20639eb413694 100644 (file)
@@ -147,7 +147,7 @@ static inline void check_bogus_address(const unsigned long ptr, unsigned long n,
                                       bool to_user)
 {
        /* Reject if object wraps past end of memory. */
-       if (ptr + n < ptr)
+       if (ptr + (n - 1) < ptr)
                usercopy_abort("wrapped address", NULL, to_user, 0, ptr + n);
 
        /* Reject if NULL or ZERO-allocation. */
index 4fa8d84599b0bad60d03c87243c9cf97ec9bb52e..7ba11e12a11f33b38a007a038bbfc7dee2fe48b3 100644 (file)
@@ -1258,6 +1258,12 @@ static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end)
        if (unlikely(valist == NULL))
                return false;
 
+       /*
+        * First make sure the mappings are removed from all page-tables
+        * before they are freed.
+        */
+       vmalloc_sync_all();
+
        /*
         * TODO: to calculate a flush range without looping.
         * The list can be up to lazy_max_pages() elements.
@@ -3038,6 +3044,9 @@ EXPORT_SYMBOL(remap_vmalloc_range);
 /*
  * Implement a stub for vmalloc_sync_all() if the architecture chose not to
  * have one.
+ *
+ * The purpose of this function is to make sure the vmalloc area
+ * mappings are identical in all page-tables in the system.
  */
 void __weak vmalloc_sync_all(void)
 {
@@ -3269,10 +3278,20 @@ retry:
                if (va == NULL)
                        goto overflow;
 
+               /*
+                * If required width exeeds current VA block, move
+                * base downwards and then recheck.
+                */
+               if (base + end > va->va_end) {
+                       base = pvm_determine_end_from_reverse(&va, align) - end;
+                       term_area = area;
+                       continue;
+               }
+
                /*
                 * If this VA does not fit, move base downwards and recheck.
                 */
-               if (base + start < va->va_start || base + end > va->va_end) {
+               if (base + start < va->va_start) {
                        va = node_to_va(rb_prev(&va->rb_node));
                        base = pvm_determine_end_from_reverse(&va, align) - end;
                        term_area = area;
index 44df66a98f2adbbd2c18c38dec8eed9e45b4a6ce..a6c5d0b28321c383037aab176bfbfca35755a320 100644 (file)
@@ -88,9 +88,6 @@ struct scan_control {
        /* Can pages be swapped as part of reclaim? */
        unsigned int may_swap:1;
 
-       /* e.g. boosted watermark reclaim leaves slabs alone */
-       unsigned int may_shrinkslab:1;
-
        /*
         * Cgroups are not reclaimed below their configured memory.low,
         * unless we threaten to OOM. If any cgroups are skipped due to
@@ -699,7 +696,14 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid,
        unsigned long ret, freed = 0;
        struct shrinker *shrinker;
 
-       if (!mem_cgroup_is_root(memcg))
+       /*
+        * The root memcg might be allocated even though memcg is disabled
+        * via "cgroup_disable=memory" boot parameter.  This could make
+        * mem_cgroup_is_root() return false, then just run memcg slab
+        * shrink, but skip global shrink.  This may result in premature
+        * oom.
+        */
+       if (!mem_cgroup_disabled() && !mem_cgroup_is_root(memcg))
                return shrink_slab_memcg(gfp_mask, nid, memcg, priority);
 
        if (!down_read_trylock(&shrinker_rwsem))
@@ -2707,10 +2711,8 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc)
                        shrink_node_memcg(pgdat, memcg, sc, &lru_pages);
                        node_lru_pages += lru_pages;
 
-                       if (sc->may_shrinkslab) {
-                               shrink_slab(sc->gfp_mask, pgdat->node_id,
-                                   memcg, sc->priority);
-                       }
+                       shrink_slab(sc->gfp_mask, pgdat->node_id, memcg,
+                                       sc->priority);
 
                        /* Record the group's reclaim efficiency */
                        vmpressure(sc->gfp_mask, memcg, false,
@@ -3187,7 +3189,6 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
                .may_writepage = !laptop_mode,
                .may_unmap = 1,
                .may_swap = 1,
-               .may_shrinkslab = 1,
        };
 
        /*
@@ -3219,6 +3220,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 
 #ifdef CONFIG_MEMCG
 
+/* Only used by soft limit reclaim. Do not reuse for anything else. */
 unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
                                                gfp_t gfp_mask, bool noswap,
                                                pg_data_t *pgdat,
@@ -3231,11 +3233,11 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
                .may_unmap = 1,
                .reclaim_idx = MAX_NR_ZONES - 1,
                .may_swap = !noswap,
-               .may_shrinkslab = 1,
        };
        unsigned long lru_pages;
 
-       set_task_reclaim_state(current, &sc.reclaim_state);
+       WARN_ON_ONCE(!current->reclaim_state);
+
        sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
                        (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
 
@@ -3253,7 +3255,6 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
 
        trace_mm_vmscan_memcg_softlimit_reclaim_end(sc.nr_reclaimed);
 
-       set_task_reclaim_state(current, NULL);
        *nr_scanned = sc.nr_scanned;
 
        return sc.nr_reclaimed;
@@ -3279,7 +3280,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
                .may_writepage = !laptop_mode,
                .may_unmap = 1,
                .may_swap = may_swap,
-               .may_shrinkslab = 1,
        };
 
        set_task_reclaim_state(current, &sc.reclaim_state);
@@ -3591,7 +3591,6 @@ restart:
                 */
                sc.may_writepage = !laptop_mode && !nr_boost_reclaim;
                sc.may_swap = !nr_boost_reclaim;
-               sc.may_shrinkslab = !nr_boost_reclaim;
 
                /*
                 * Do some background aging of the anon list, to give
index e0b4edcb88c8c63dd307b0648ad34e3a27ce0ee8..c963831d354f8058447888c049c41178fe9a4d55 100644 (file)
@@ -380,14 +380,12 @@ void workingset_update_node(struct xa_node *node)
        if (node->count && node->count == node->nr_values) {
                if (list_empty(&node->private_list)) {
                        list_lru_add(&shadow_nodes, &node->private_list);
-                       __inc_lruvec_page_state(virt_to_page(node),
-                                               WORKINGSET_NODES);
+                       __inc_lruvec_slab_state(node, WORKINGSET_NODES);
                }
        } else {
                if (!list_empty(&node->private_list)) {
                        list_lru_del(&shadow_nodes, &node->private_list);
-                       __dec_lruvec_page_state(virt_to_page(node),
-                                               WORKINGSET_NODES);
+                       __dec_lruvec_slab_state(node, WORKINGSET_NODES);
                }
        }
 }
@@ -480,7 +478,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
        }
 
        list_lru_isolate(lru, item);
-       __dec_lruvec_page_state(virt_to_page(node), WORKINGSET_NODES);
+       __dec_lruvec_slab_state(node, WORKINGSET_NODES);
 
        spin_unlock(lru_lock);
 
@@ -503,7 +501,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
         * shadow entries we were tracking ...
         */
        xas_store(&xas, NULL);
-       __inc_lruvec_page_state(virt_to_page(node), WORKINGSET_NODERECLAIM);
+       __inc_lruvec_slab_state(node, WORKINGSET_NODERECLAIM);
 
 out_invalid:
        xa_unlock_irq(&mapping->i_pages);
index 1a029a7432ee56635f9dcde8f4c5ad2b1e2984ed..75b7962439ff8b21b9cacb6a542d21ad8313af3b 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/wait.h>
 #include <linux/zpool.h>
 #include <linux/magic.h>
 
@@ -145,6 +146,8 @@ struct z3fold_header {
  * @release_wq:        workqueue for safe page release
  * @work:      work_struct for safe page release
  * @inode:     inode for z3fold pseudo filesystem
+ * @destroying: bool to stop migration once we start destruction
+ * @isolated: int to count the number of pages currently in isolation
  *
  * This structure is allocated at pool creation time and maintains metadata
  * pertaining to a particular z3fold pool.
@@ -163,8 +166,11 @@ struct z3fold_pool {
        const struct zpool_ops *zpool_ops;
        struct workqueue_struct *compact_wq;
        struct workqueue_struct *release_wq;
+       struct wait_queue_head isolate_wait;
        struct work_struct work;
        struct inode *inode;
+       bool destroying;
+       int isolated;
 };
 
 /*
@@ -769,6 +775,7 @@ static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp,
                goto out_c;
        spin_lock_init(&pool->lock);
        spin_lock_init(&pool->stale_lock);
+       init_waitqueue_head(&pool->isolate_wait);
        pool->unbuddied = __alloc_percpu(sizeof(struct list_head)*NCHUNKS, 2);
        if (!pool->unbuddied)
                goto out_pool;
@@ -808,6 +815,15 @@ out:
        return NULL;
 }
 
+static bool pool_isolated_are_drained(struct z3fold_pool *pool)
+{
+       bool ret;
+
+       spin_lock(&pool->lock);
+       ret = pool->isolated == 0;
+       spin_unlock(&pool->lock);
+       return ret;
+}
 /**
  * z3fold_destroy_pool() - destroys an existing z3fold pool
  * @pool:      the z3fold pool to be destroyed
@@ -817,9 +833,35 @@ out:
 static void z3fold_destroy_pool(struct z3fold_pool *pool)
 {
        kmem_cache_destroy(pool->c_handle);
-       z3fold_unregister_migration(pool);
-       destroy_workqueue(pool->release_wq);
+       /*
+        * We set pool-> destroying under lock to ensure that
+        * z3fold_page_isolate() sees any changes to destroying. This way we
+        * avoid the need for any memory barriers.
+        */
+
+       spin_lock(&pool->lock);
+       pool->destroying = true;
+       spin_unlock(&pool->lock);
+
+       /*
+        * We need to ensure that no pages are being migrated while we destroy
+        * these workqueues, as migration can queue work on either of the
+        * workqueues.
+        */
+       wait_event(pool->isolate_wait, !pool_isolated_are_drained(pool));
+
+       /*
+        * We need to destroy pool->compact_wq before pool->release_wq,
+        * as any pending work on pool->compact_wq will call
+        * queue_work(pool->release_wq, &pool->work).
+        *
+        * There are still outstanding pages until both workqueues are drained,
+        * so we cannot unregister migration until then.
+        */
+
        destroy_workqueue(pool->compact_wq);
+       destroy_workqueue(pool->release_wq);
+       z3fold_unregister_migration(pool);
        kfree(pool);
 }
 
@@ -1297,6 +1339,28 @@ static u64 z3fold_get_pool_size(struct z3fold_pool *pool)
        return atomic64_read(&pool->pages_nr);
 }
 
+/*
+ * z3fold_dec_isolated() expects to be called while pool->lock is held.
+ */
+static void z3fold_dec_isolated(struct z3fold_pool *pool)
+{
+       assert_spin_locked(&pool->lock);
+       VM_BUG_ON(pool->isolated <= 0);
+       pool->isolated--;
+
+       /*
+        * If we have no more isolated pages, we have to see if
+        * z3fold_destroy_pool() is waiting for a signal.
+        */
+       if (pool->isolated == 0 && waitqueue_active(&pool->isolate_wait))
+               wake_up_all(&pool->isolate_wait);
+}
+
+static void z3fold_inc_isolated(struct z3fold_pool *pool)
+{
+       pool->isolated++;
+}
+
 static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
 {
        struct z3fold_header *zhdr;
@@ -1323,6 +1387,34 @@ static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
                spin_lock(&pool->lock);
                if (!list_empty(&page->lru))
                        list_del(&page->lru);
+               /*
+                * We need to check for destruction while holding pool->lock, as
+                * otherwise destruction could see 0 isolated pages, and
+                * proceed.
+                */
+               if (unlikely(pool->destroying)) {
+                       spin_unlock(&pool->lock);
+                       /*
+                        * If this page isn't stale, somebody else holds a
+                        * reference to it. Let't drop our refcount so that they
+                        * can call the release logic.
+                        */
+                       if (unlikely(kref_put(&zhdr->refcount,
+                                             release_z3fold_page_locked))) {
+                               /*
+                                * If we get here we have kref problems, so we
+                                * should freak out.
+                                */
+                               WARN(1, "Z3fold is experiencing kref problems\n");
+                               z3fold_page_unlock(zhdr);
+                               return false;
+                       }
+                       z3fold_page_unlock(zhdr);
+                       return false;
+               }
+
+
+               z3fold_inc_isolated(pool);
                spin_unlock(&pool->lock);
                z3fold_page_unlock(zhdr);
                return true;
@@ -1391,6 +1483,10 @@ static int z3fold_page_migrate(struct address_space *mapping, struct page *newpa
 
        queue_work_on(new_zhdr->cpu, pool->compact_wq, &new_zhdr->work);
 
+       spin_lock(&pool->lock);
+       z3fold_dec_isolated(pool);
+       spin_unlock(&pool->lock);
+
        page_mapcount_reset(page);
        put_page(page);
        return 0;
@@ -1410,10 +1506,14 @@ static void z3fold_page_putback(struct page *page)
        INIT_LIST_HEAD(&page->lru);
        if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) {
                atomic64_dec(&pool->pages_nr);
+               spin_lock(&pool->lock);
+               z3fold_dec_isolated(pool);
+               spin_unlock(&pool->lock);
                return;
        }
        spin_lock(&pool->lock);
        list_add(&page->lru, &pool->lru);
+       z3fold_dec_isolated(pool);
        spin_unlock(&pool->lock);
        z3fold_page_unlock(zhdr);
 }
index 57fbb7ced69f3a47111db0f665ec05b26e4186db..e98bb6ab4f7e76c8b3f6d29c165b43fd6a6da964 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/mount.h>
 #include <linux/pseudo_fs.h>
 #include <linux/migrate.h>
+#include <linux/wait.h>
 #include <linux/pagemap.h>
 #include <linux/fs.h>
 
@@ -268,6 +269,10 @@ struct zs_pool {
 #ifdef CONFIG_COMPACTION
        struct inode *inode;
        struct work_struct free_work;
+       /* A wait queue for when migration races with async_free_zspage() */
+       struct wait_queue_head migration_wait;
+       atomic_long_t isolated_pages;
+       bool destroying;
 #endif
 };
 
@@ -1862,6 +1867,31 @@ static void dec_zspage_isolation(struct zspage *zspage)
        zspage->isolated--;
 }
 
+static void putback_zspage_deferred(struct zs_pool *pool,
+                                   struct size_class *class,
+                                   struct zspage *zspage)
+{
+       enum fullness_group fg;
+
+       fg = putback_zspage(class, zspage);
+       if (fg == ZS_EMPTY)
+               schedule_work(&pool->free_work);
+
+}
+
+static inline void zs_pool_dec_isolated(struct zs_pool *pool)
+{
+       VM_BUG_ON(atomic_long_read(&pool->isolated_pages) <= 0);
+       atomic_long_dec(&pool->isolated_pages);
+       /*
+        * There's no possibility of racing, since wait_for_isolated_drain()
+        * checks the isolated count under &class->lock after enqueuing
+        * on migration_wait.
+        */
+       if (atomic_long_read(&pool->isolated_pages) == 0 && pool->destroying)
+               wake_up_all(&pool->migration_wait);
+}
+
 static void replace_sub_page(struct size_class *class, struct zspage *zspage,
                                struct page *newpage, struct page *oldpage)
 {
@@ -1931,6 +1961,7 @@ static bool zs_page_isolate(struct page *page, isolate_mode_t mode)
         */
        if (!list_empty(&zspage->list) && !is_zspage_isolated(zspage)) {
                get_zspage_mapping(zspage, &class_idx, &fullness);
+               atomic_long_inc(&pool->isolated_pages);
                remove_zspage(class, zspage, fullness);
        }
 
@@ -2030,8 +2061,16 @@ static int zs_page_migrate(struct address_space *mapping, struct page *newpage,
         * Page migration is done so let's putback isolated zspage to
         * the list if @page is final isolated subpage in the zspage.
         */
-       if (!is_zspage_isolated(zspage))
-               putback_zspage(class, zspage);
+       if (!is_zspage_isolated(zspage)) {
+               /*
+                * We cannot race with zs_destroy_pool() here because we wait
+                * for isolation to hit zero before we start destroying.
+                * Also, we ensure that everyone can see pool->destroying before
+                * we start waiting.
+                */
+               putback_zspage_deferred(pool, class, zspage);
+               zs_pool_dec_isolated(pool);
+       }
 
        reset_page(page);
        put_page(page);
@@ -2077,13 +2116,12 @@ static void zs_page_putback(struct page *page)
        spin_lock(&class->lock);
        dec_zspage_isolation(zspage);
        if (!is_zspage_isolated(zspage)) {
-               fg = putback_zspage(class, zspage);
                /*
                 * Due to page_lock, we cannot free zspage immediately
                 * so let's defer.
                 */
-               if (fg == ZS_EMPTY)
-                       schedule_work(&pool->free_work);
+               putback_zspage_deferred(pool, class, zspage);
+               zs_pool_dec_isolated(pool);
        }
        spin_unlock(&class->lock);
 }
@@ -2107,8 +2145,36 @@ static int zs_register_migration(struct zs_pool *pool)
        return 0;
 }
 
+static bool pool_isolated_are_drained(struct zs_pool *pool)
+{
+       return atomic_long_read(&pool->isolated_pages) == 0;
+}
+
+/* Function for resolving migration */
+static void wait_for_isolated_drain(struct zs_pool *pool)
+{
+
+       /*
+        * We're in the process of destroying the pool, so there are no
+        * active allocations. zs_page_isolate() fails for completely free
+        * zspages, so we need only wait for the zs_pool's isolated
+        * count to hit zero.
+        */
+       wait_event(pool->migration_wait,
+                  pool_isolated_are_drained(pool));
+}
+
 static void zs_unregister_migration(struct zs_pool *pool)
 {
+       pool->destroying = true;
+       /*
+        * We need a memory barrier here to ensure global visibility of
+        * pool->destroying. Thus pool->isolated pages will either be 0 in which
+        * case we don't care, or it will be > 0 and pool->destroying will
+        * ensure that we wake up once isolation hits 0.
+        */
+       smp_mb();
+       wait_for_isolated_drain(pool); /* This can block */
        flush_work(&pool->free_work);
        iput(pool->inode);
 }
@@ -2346,6 +2412,10 @@ struct zs_pool *zs_create_pool(const char *name)
        if (!pool->name)
                goto err;
 
+#ifdef CONFIG_COMPACTION
+       init_waitqueue_head(&pool->migration_wait);
+#endif
+
        if (create_cache(pool))
                goto err;
 
index 240ed70912d6a014c0a48280741989133034396c..d78938e3e0085d9cff138b805148a0e77de3f654 100644 (file)
@@ -277,17 +277,23 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
  * batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached
  * @buff_pos: current position in the skb
  * @packet_len: total length of the skb
- * @tvlv_len: tvlv length of the previously considered OGM
+ * @ogm_packet: potential OGM in buffer
  *
  * Return: true if there is enough space for another OGM, false otherwise.
  */
-static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
-                                     __be16 tvlv_len)
+static bool
+batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
+                         const struct batadv_ogm_packet *ogm_packet)
 {
        int next_buff_pos = 0;
 
-       next_buff_pos += buff_pos + BATADV_OGM_HLEN;
-       next_buff_pos += ntohs(tvlv_len);
+       /* check if there is enough space for the header */
+       next_buff_pos += buff_pos + sizeof(*ogm_packet);
+       if (next_buff_pos > packet_len)
+               return false;
+
+       /* check if there is enough space for the optional TVLV */
+       next_buff_pos += ntohs(ogm_packet->tvlv_len);
 
        return (next_buff_pos <= packet_len) &&
               (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
@@ -315,7 +321,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
 
        /* adjust all flags and log packets */
        while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
-                                        batadv_ogm_packet->tvlv_len)) {
+                                        batadv_ogm_packet)) {
                /* we might have aggregated direct link packets with an
                 * ordinary base packet
                 */
@@ -1704,7 +1710,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
 
        /* unpack the aggregated packets and process them one by one */
        while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
-                                        ogm_packet->tvlv_len)) {
+                                        ogm_packet)) {
                batadv_iv_ogm_process(skb, ogm_offset, if_incoming);
 
                ogm_offset += BATADV_OGM_HLEN;
index fad95ef64e01a9670ed66f9a81658718a14fc716..bc06e3cdfa84f63cc003867d4453a88249d3fb18 100644 (file)
@@ -631,17 +631,23 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
  * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated
  * @buff_pos: current position in the skb
  * @packet_len: total length of the skb
- * @tvlv_len: tvlv length of the previously considered OGM
+ * @ogm2_packet: potential OGM2 in buffer
  *
  * Return: true if there is enough space for another OGM, false otherwise.
  */
-static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
-                                    __be16 tvlv_len)
+static bool
+batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
+                        const struct batadv_ogm2_packet *ogm2_packet)
 {
        int next_buff_pos = 0;
 
-       next_buff_pos += buff_pos + BATADV_OGM2_HLEN;
-       next_buff_pos += ntohs(tvlv_len);
+       /* check if there is enough space for the header */
+       next_buff_pos += buff_pos + sizeof(*ogm2_packet);
+       if (next_buff_pos > packet_len)
+               return false;
+
+       /* check if there is enough space for the optional TVLV */
+       next_buff_pos += ntohs(ogm2_packet->tvlv_len);
 
        return (next_buff_pos <= packet_len) &&
               (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
@@ -818,7 +824,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
        ogm_packet = (struct batadv_ogm2_packet *)skb->data;
 
        while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
-                                       ogm_packet->tvlv_len)) {
+                                       ogm_packet)) {
                batadv_v_ogm_process(skb, ogm_offset, if_incoming);
 
                ogm_offset += BATADV_OGM2_HLEN;
index 67d7f83009ae1e0c1fc8e9e694d3d33a9f93d7d5..1d5bdf3a4b65526c7c4b90283d97366e10ba19c3 100644 (file)
@@ -2303,7 +2303,7 @@ __batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid,
 
        while (bucket_tmp < hash->size) {
                if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash,
-                                                  *bucket, &idx_tmp))
+                                                  bucket_tmp, &idx_tmp))
                        break;
 
                bucket_tmp++;
@@ -2420,8 +2420,10 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
        batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
        batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
        batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
-       batadv_mcast_want_rtr4_update(bat_priv, orig, BATADV_NO_FLAGS);
-       batadv_mcast_want_rtr6_update(bat_priv, orig, BATADV_NO_FLAGS);
+       batadv_mcast_want_rtr4_update(bat_priv, orig,
+                                     BATADV_MCAST_WANT_NO_RTR4);
+       batadv_mcast_want_rtr6_update(bat_priv, orig,
+                                     BATADV_MCAST_WANT_NO_RTR6);
 
        spin_unlock_bh(&orig->mcast_handler_lock);
 }
index 6f08fd122a8ddea43600c856a6be171dc7625d9c..7e052d6f759b659dbee0edd7546c367cf14b8e9e 100644 (file)
@@ -164,7 +164,7 @@ batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype)
 {
        struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype);
 
-       return attr ? nla_get_u32(attr) : 0;
+       return (attr && nla_len(attr) == sizeof(u32)) ? nla_get_u32(attr) : 0;
 }
 
 /**
index b9585e7d9d2e9492b0d495ae58b8da9029bce6b7..04bc79359a1736b28e83f0eb88828ceefd430f25 100644 (file)
@@ -3202,6 +3202,7 @@ struct hci_dev *hci_alloc_dev(void)
        hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE;
        hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE;
        hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
+       hdev->min_enc_key_size = HCI_MIN_ENC_KEY_SIZE;
 
        mutex_init(&hdev->lock);
        mutex_init(&hdev->req_lock);
index bb67f4a5479a2c79d724956c883d80e2a0c93345..402e2cc54044acc3ec7243915a177affdb004c14 100644 (file)
@@ -433,6 +433,35 @@ static int auto_accept_delay_set(void *data, u64 val)
        return 0;
 }
 
+static int min_encrypt_key_size_set(void *data, u64 val)
+{
+       struct hci_dev *hdev = data;
+
+       if (val < 1 || val > 16)
+               return -EINVAL;
+
+       hci_dev_lock(hdev);
+       hdev->min_enc_key_size = val;
+       hci_dev_unlock(hdev);
+
+       return 0;
+}
+
+static int min_encrypt_key_size_get(void *data, u64 *val)
+{
+       struct hci_dev *hdev = data;
+
+       hci_dev_lock(hdev);
+       *val = hdev->min_enc_key_size;
+       hci_dev_unlock(hdev);
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(min_encrypt_key_size_fops,
+                       min_encrypt_key_size_get,
+                       min_encrypt_key_size_set, "%llu\n");
+
 static int auto_accept_delay_get(void *data, u64 *val)
 {
        struct hci_dev *hdev = data;
@@ -545,6 +574,8 @@ void hci_debugfs_create_bredr(struct hci_dev *hdev)
        if (lmp_ssp_capable(hdev)) {
                debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs,
                                    hdev, &ssp_debug_mode_fops);
+               debugfs_create_file("min_encrypt_key_size", 0644, hdev->debugfs,
+                                   hdev, &min_encrypt_key_size_fops);
                debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
                                    hdev, &auto_accept_delay_fops);
        }
index cdb00c2ef242387c0d6824e0ec07c3a19b85eb8f..c1d3a303d97fbda890e546755535199af0420d2e 100644 (file)
@@ -5660,11 +5660,6 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
                return send_conn_param_neg_reply(hdev, handle,
                                                 HCI_ERROR_UNKNOWN_CONN_ID);
 
-       if (min < hcon->le_conn_min_interval ||
-           max > hcon->le_conn_max_interval)
-               return send_conn_param_neg_reply(hdev, handle,
-                                                HCI_ERROR_INVALID_LL_PARAMS);
-
        if (hci_check_conn_params(min, max, latency, timeout))
                return send_conn_param_neg_reply(hdev, handle,
                                                 HCI_ERROR_INVALID_LL_PARAMS);
index 5abd423b55fa9c3839eb37d412c16a8735f901a5..8d889969ae7edaf2acf653098aaae0d98618776b 100644 (file)
@@ -101,6 +101,7 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock,
 {
        struct sk_buff *skb;
        struct sock *sk = sock->sk;
+       int ret;
 
        BT_DBG("session %p data %p size %d", session, data, size);
 
@@ -114,13 +115,17 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock,
        }
 
        skb_put_u8(skb, hdr);
-       if (data && size > 0)
+       if (data && size > 0) {
                skb_put_data(skb, data, size);
+               ret = size;
+       } else {
+               ret = 0;
+       }
 
        skb_queue_tail(transmit, skb);
        wake_up_interruptible(sk_sleep(sk));
 
-       return 0;
+       return ret;
 }
 
 static int hidp_send_ctrl_message(struct hidp_session *session,
index cc506fe99b4d7e092eefd90f9ea41bce9297dfca..da7fdbdf9c41af026969f6045513d3e7685434bc 100644 (file)
@@ -1361,7 +1361,7 @@ static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
         * actually encrypted before enforcing a key size.
         */
        return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
-               hcon->enc_key_size >= HCI_MIN_ENC_KEY_SIZE);
+               hcon->enc_key_size >= hcon->hdev->min_enc_key_size);
 }
 
 static void l2cap_do_start(struct l2cap_chan *chan)
@@ -5305,14 +5305,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
 
        memset(&rsp, 0, sizeof(rsp));
 
-       if (min < hcon->le_conn_min_interval ||
-           max > hcon->le_conn_max_interval) {
-               BT_DBG("requested connection interval exceeds current bounds.");
-               err = -EINVAL;
-       } else {
-               err = hci_check_conn_params(min, max, latency, to_multiplier);
-       }
-
+       err = hci_check_conn_params(min, max, latency, to_multiplier);
        if (err)
                rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
        else
index d164f63a4345c5667e5190f92900d79d3d8806d8..8a8f9e5f264f2a70b246094fa7c31f1be8c0deef 100644 (file)
@@ -37,12 +37,15 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
        int err;
 
        if (dev->priv_flags & IFF_EBRIDGE) {
+               err = br_vlan_bridge_event(dev, event, ptr);
+               if (err)
+                       return notifier_from_errno(err);
+
                if (event == NETDEV_REGISTER) {
                        /* register of bridge completed, add sysfs entries */
                        br_sysfs_addbr(dev);
                        return NOTIFY_DONE;
                }
-               br_vlan_bridge_event(dev, event, ptr);
        }
 
        /* not a port of a bridge */
index bf6acd34234daa8a1da4aff928c169837bcf58c1..63f9c08625f055b7779dd471707f16cf6f7b4ba1 100644 (file)
@@ -437,7 +437,7 @@ static int nlmsg_populate_rtr_fill(struct sk_buff *skb,
        struct nlmsghdr *nlh;
        struct nlattr *nest;
 
-       nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), 0);
        if (!nlh)
                return -EMSGSIZE;
 
index 3d8deac2353d045964c52981a1eaac96d6f23025..f8cac3702712028ef596ce994c7b872cc4e353d1 100644 (file)
@@ -1388,6 +1388,9 @@ br_multicast_leave_group(struct net_bridge *br,
                        if (!br_port_group_equal(p, port, src))
                                continue;
 
+                       if (p->flags & MDB_PG_FLAGS_PERMANENT)
+                               break;
+
                        rcu_assign_pointer(*pp, p->next);
                        hlist_del_init(&p->mglist);
                        del_timer(&p->timer);
index d3f9592f4ff8d8435861cd95dd0d130e8fa22fbb..af7800103e51e5aee724ff314697d17ec583aeba 100644 (file)
@@ -496,6 +496,10 @@ static unsigned int br_nf_pre_routing(void *priv,
                if (!brnet->call_ip6tables &&
                    !br_opt_get(br, BROPT_NF_CALL_IP6TABLES))
                        return NF_ACCEPT;
+               if (!ipv6_mod_enabled()) {
+                       pr_warn_once("Module ipv6 is disabled, so call_ip6tables is not supported.");
+                       return NF_DROP;
+               }
 
                nf_bridge_pull_encap_header_rcsum(skb);
                return br_nf_pre_routing_ipv6(priv, skb, state);
index e8cf03b43b7d6c5225f6be08d285a2cbe0307fa2..646504db0220eaadf112a14a82a56f5223d264fa 100644 (file)
@@ -894,8 +894,8 @@ int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask);
 void br_vlan_get_stats(const struct net_bridge_vlan *v,
                       struct br_vlan_stats *stats);
 void br_vlan_port_event(struct net_bridge_port *p, unsigned long event);
-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
-                         void *ptr);
+int br_vlan_bridge_event(struct net_device *dev, unsigned long event,
+                        void *ptr);
 
 static inline struct net_bridge_vlan_group *br_vlan_group(
                                        const struct net_bridge *br)
@@ -1085,9 +1085,10 @@ static inline void br_vlan_port_event(struct net_bridge_port *p,
 {
 }
 
-static inline void br_vlan_bridge_event(struct net_device *dev,
-                                       unsigned long event, void *ptr)
+static inline int br_vlan_bridge_event(struct net_device *dev,
+                                      unsigned long event, void *ptr)
 {
+       return 0;
 }
 #endif
 
index 021cc9f66804d6db567d7a139d6e68ab10798665..f5b2aeebbfe98d82a084c78be2747a14ebcbc938 100644 (file)
@@ -1053,7 +1053,6 @@ int br_vlan_init(struct net_bridge *br)
 {
        struct net_bridge_vlan_group *vg;
        int ret = -ENOMEM;
-       bool changed;
 
        vg = kzalloc(sizeof(*vg), GFP_KERNEL);
        if (!vg)
@@ -1068,17 +1067,10 @@ int br_vlan_init(struct net_bridge *br)
        br->vlan_proto = htons(ETH_P_8021Q);
        br->default_pvid = 1;
        rcu_assign_pointer(br->vlgrp, vg);
-       ret = br_vlan_add(br, 1,
-                         BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED |
-                         BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL);
-       if (ret)
-               goto err_vlan_add;
 
 out:
        return ret;
 
-err_vlan_add:
-       vlan_tunnel_deinit(vg);
 err_tunnel_init:
        rhashtable_destroy(&vg->vlan_hash);
 err_rhtbl:
@@ -1464,13 +1456,23 @@ static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid)
 }
 
 /* Must be protected by RTNL. */
-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
-                         void *ptr)
+int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr)
 {
        struct netdev_notifier_changeupper_info *info;
-       struct net_bridge *br;
+       struct net_bridge *br = netdev_priv(dev);
+       bool changed;
+       int ret = 0;
 
        switch (event) {
+       case NETDEV_REGISTER:
+               ret = br_vlan_add(br, br->default_pvid,
+                                 BRIDGE_VLAN_INFO_PVID |
+                                 BRIDGE_VLAN_INFO_UNTAGGED |
+                                 BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL);
+               break;
+       case NETDEV_UNREGISTER:
+               br_vlan_delete(br, br->default_pvid);
+               break;
        case NETDEV_CHANGEUPPER:
                info = ptr;
                br_vlan_upper_change(dev, info->upper_dev, info->linking);
@@ -1478,12 +1480,13 @@ void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
 
        case NETDEV_CHANGE:
        case NETDEV_UP:
-               br = netdev_priv(dev);
                if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING))
-                       return;
+                       break;
                br_vlan_link_state_change(dev, br);
                break;
        }
+
+       return ret;
 }
 
 /* Must be protected by RTNL. */
index 154fa558bb90836928bb37e814e8e1c0a785edbf..5040fe43f4b42241722c00272482e234f53bfe9d 100644 (file)
@@ -6,7 +6,7 @@
 menuconfig NF_TABLES_BRIDGE
        depends on BRIDGE && NETFILTER && NF_TABLES
        select NETFILTER_FAMILY_BRIDGE
-       bool "Ethernet Bridge nf_tables support"
+       tristate "Ethernet Bridge nf_tables support"
 
 if NF_TABLES_BRIDGE
 
@@ -25,6 +25,8 @@ config NF_LOG_BRIDGE
        tristate "Bridge packet logging"
        select NF_LOG_COMMON
 
+endif # NF_TABLES_BRIDGE
+
 config NF_CONNTRACK_BRIDGE
        tristate "IPv4/IPV6 bridge connection tracking support"
        depends on NF_CONNTRACK
@@ -39,8 +41,6 @@ config NF_CONNTRACK_BRIDGE
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-endif # NF_TABLES_BRIDGE
-
 menuconfig BRIDGE_NF_EBTABLES
        tristate "Ethernet Bridge tables (ebtables) support"
        depends on BRIDGE && NETFILTER && NETFILTER_XTABLES
index 963dfdc1482724c07ad95a0fc17750c90cbfc964..4096d8a74a2bd7474da1e5ee980d840126f90c83 100644 (file)
@@ -221,7 +221,7 @@ unsigned int ebt_do_table(struct sk_buff *skb,
                        return NF_DROP;
                }
 
-               ADD_COUNTER(*(counter_base + i), 1, skb->len);
+               ADD_COUNTER(*(counter_base + i), skb->len, 1);
 
                /* these should only watch: not modify, nor tell us
                 * what to do with the packet
@@ -959,8 +959,8 @@ static void get_counters(const struct ebt_counter *oldcounters,
                        continue;
                counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
                for (i = 0; i < nentries; i++)
-                       ADD_COUNTER(counters[i], counter_base[i].pcnt,
-                                   counter_base[i].bcnt);
+                       ADD_COUNTER(counters[i], counter_base[i].bcnt,
+                                   counter_base[i].pcnt);
        }
 }
 
@@ -1280,7 +1280,7 @@ static int do_update_counters(struct net *net, const char *name,
 
        /* we add to the counters of the first cpu */
        for (i = 0; i < num_counters; i++)
-               ADD_COUNTER(t->private->counters[i], tmp[i].pcnt, tmp[i].bcnt);
+               ADD_COUNTER(t->private->counters[i], tmp[i].bcnt, tmp[i].pcnt);
 
        write_unlock_bh(&t->lock);
        ret = 0;
@@ -1770,20 +1770,28 @@ static int compat_calc_entry(const struct ebt_entry *e,
        return 0;
 }
 
+static int ebt_compat_init_offsets(unsigned int number)
+{
+       if (number > INT_MAX)
+               return -EINVAL;
+
+       /* also count the base chain policies */
+       number += NF_BR_NUMHOOKS;
+
+       return xt_compat_init_offsets(NFPROTO_BRIDGE, number);
+}
 
 static int compat_table_info(const struct ebt_table_info *info,
                             struct compat_ebt_replace *newinfo)
 {
        unsigned int size = info->entries_size;
        const void *entries = info->entries;
+       int ret;
 
        newinfo->entries_size = size;
-       if (info->nentries) {
-               int ret = xt_compat_init_offsets(NFPROTO_BRIDGE,
-                                                info->nentries);
-               if (ret)
-                       return ret;
-       }
+       ret = ebt_compat_init_offsets(info->nentries);
+       if (ret)
+               return ret;
 
        return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
                                                        entries, newinfo);
@@ -2234,11 +2242,9 @@ static int compat_do_replace(struct net *net, void __user *user,
 
        xt_compat_lock(NFPROTO_BRIDGE);
 
-       if (tmp.nentries) {
-               ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
-               if (ret < 0)
-                       goto out_unlock;
-       }
+       ret = ebt_compat_init_offsets(tmp.nentries);
+       if (ret < 0)
+               goto out_unlock;
 
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
        if (ret < 0)
@@ -2261,8 +2267,10 @@ static int compat_do_replace(struct net *net, void __user *user,
        state.buf_kern_len = size64;
 
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
-       if (WARN_ON(ret < 0))
+       if (WARN_ON(ret < 0)) {
+               vfree(entries_tmp);
                goto out_unlock;
+       }
 
        vfree(entries_tmp);
        tmp.entries_size = size64;
index bed66f536b34535c38e72cd5de4ea0fb6aaf2780..7c9e92b2f806c8979d603e0624b72df141cc2900 100644 (file)
@@ -30,13 +30,9 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
        switch (priv->key) {
        case NFT_META_BRI_IIFNAME:
                br_dev = nft_meta_get_bridge(in);
-               if (!br_dev)
-                       goto err;
                break;
        case NFT_META_BRI_OIFNAME:
                br_dev = nft_meta_get_bridge(out);
-               if (!br_dev)
-                       goto err;
                break;
        case NFT_META_BRI_IIFPVID: {
                u16 p_pvid;
@@ -57,17 +53,15 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
                        goto err;
 
                br_vlan_get_proto(br_dev, &p_proto);
-               nft_reg_store16(dest, p_proto);
+               nft_reg_store16(dest, htons(p_proto));
                return;
        }
        default:
-               goto out;
+               return nft_meta_get_eval(expr, regs, pkt);
        }
 
-       strncpy((char *)dest, br_dev->name, IFNAMSIZ);
+       strncpy((char *)dest, br_dev ? br_dev->name : "", IFNAMSIZ);
        return;
-out:
-       return nft_meta_get_eval(expr, regs, pkt);
 err:
        regs->verdict.code = NFT_BREAK;
 }
index 5275ddf580bc7d64139e323eca15e276357bfdd1..72711053ebe66ce8231fbb79d9c37f682071be64 100644 (file)
@@ -1046,32 +1046,50 @@ static __init int cgw_module_init(void)
        pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n",
                max_hops);
 
-       register_pernet_subsys(&cangw_pernet_ops);
+       ret = register_pernet_subsys(&cangw_pernet_ops);
+       if (ret)
+               return ret;
+
+       ret = -ENOMEM;
        cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
                                      0, 0, NULL);
-
        if (!cgw_cache)
-               return -ENOMEM;
+               goto out_cache_create;
 
        /* set notifier */
        notifier.notifier_call = cgw_notifier;
-       register_netdevice_notifier(&notifier);
+       ret = register_netdevice_notifier(&notifier);
+       if (ret)
+               goto out_register_notifier;
 
        ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_GETROUTE,
                                   NULL, cgw_dump_jobs, 0);
-       if (ret) {
-               unregister_netdevice_notifier(&notifier);
-               kmem_cache_destroy(cgw_cache);
-               return -ENOBUFS;
-       }
-
-       /* Only the first call to rtnl_register_module can fail */
-       rtnl_register_module(THIS_MODULE, PF_CAN, RTM_NEWROUTE,
-                            cgw_create_job, NULL, 0);
-       rtnl_register_module(THIS_MODULE, PF_CAN, RTM_DELROUTE,
-                            cgw_remove_job, NULL, 0);
+       if (ret)
+               goto out_rtnl_register1;
+
+       ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_NEWROUTE,
+                                  cgw_create_job, NULL, 0);
+       if (ret)
+               goto out_rtnl_register2;
+       ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_DELROUTE,
+                                  cgw_remove_job, NULL, 0);
+       if (ret)
+               goto out_rtnl_register3;
 
        return 0;
+
+out_rtnl_register3:
+       rtnl_unregister(PF_CAN, RTM_NEWROUTE);
+out_rtnl_register2:
+       rtnl_unregister(PF_CAN, RTM_GETROUTE);
+out_rtnl_register1:
+       unregister_netdevice_notifier(&notifier);
+out_register_notifier:
+       kmem_cache_destroy(cgw_cache);
+out_cache_create:
+       unregister_pernet_subsys(&cangw_pernet_ops);
+
+       return ret;
 }
 
 static __exit void cgw_module_exit(void)
index 5d6724cee38f90d1cbafcd6e66eb731394dad43c..4f75df40fb121f3c955f916fac5a3bb7f64d7f40 100644 (file)
@@ -136,8 +136,10 @@ void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
        if (key) {
                kfree(key->key);
                key->key = NULL;
-               crypto_free_sync_skcipher(key->tfm);
-               key->tfm = NULL;
+               if (key->tfm) {
+                       crypto_free_sync_skcipher(key->tfm);
+                       key->tfm = NULL;
+               }
        }
 }
 
index 0b2df09b25549265cc40888b0757b94afefe68a5..78ae6e8c953d03427535ea26732d125ed9432531 100644 (file)
@@ -1496,7 +1496,7 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
        struct ceph_osds up, acting;
        bool force_resend = false;
        bool unpaused = false;
-       bool legacy_change;
+       bool legacy_change = false;
        bool split = false;
        bool sort_bitwise = ceph_osdmap_flag(osdc, CEPH_OSDMAP_SORTBITWISE);
        bool recovery_deletes = ceph_osdmap_flag(osdc,
@@ -1584,15 +1584,14 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
                t->osd = acting.primary;
        }
 
-       if (unpaused || legacy_change || force_resend ||
-           (split && con && CEPH_HAVE_FEATURE(con->peer_features,
-                                              RESEND_ON_SPLIT)))
+       if (unpaused || legacy_change || force_resend || split)
                ct_res = CALC_TARGET_NEED_RESEND;
        else
                ct_res = CALC_TARGET_NO_ACTION;
 
 out:
-       dout("%s t %p -> ct_res %d osd %d\n", __func__, t, ct_res, t->osd);
+       dout("%s t %p -> %d%d%d%d ct_res %d osd%d\n", __func__, t, unpaused,
+            legacy_change, force_resend, split, ct_res, t->osd);
        return ct_res;
 }
 
index fc676b2610e3c1e7e236b62d4984647bc0e71916..5156c0edebe8097403c6b78f711df5a373fd2e6d 100644 (file)
@@ -4374,12 +4374,17 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
 
        act = bpf_prog_run_xdp(xdp_prog, xdp);
 
+       /* check if bpf_xdp_adjust_head was used */
        off = xdp->data - orig_data;
-       if (off > 0)
-               __skb_pull(skb, off);
-       else if (off < 0)
-               __skb_push(skb, -off);
-       skb->mac_header += off;
+       if (off) {
+               if (off > 0)
+                       __skb_pull(skb, off);
+               else if (off < 0)
+                       __skb_push(skb, -off);
+
+               skb->mac_header += off;
+               skb_reset_network_header(skb);
+       }
 
        /* check if bpf_xdp_adjust_tail was used. it can only "shrink"
         * pckt.
@@ -8753,6 +8758,8 @@ int register_netdevice(struct net_device *dev)
        ret = notifier_to_errno(ret);
        if (ret) {
                rollback_registered(dev);
+               rcu_barrier();
+
                dev->reg_state = NETREG_UNREGISTERED;
        }
        /*
@@ -9701,6 +9708,8 @@ static void __net_exit default_device_exit(struct net *net)
 
                /* Push remaining network devices to init_net */
                snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
+               if (__dev_get_by_name(&init_net, fb_name))
+                       snprintf(fb_name, IFNAMSIZ, "dev%%d");
                err = dev_change_net_namespace(dev, &init_net, fb_name);
                if (err) {
                        pr_emerg("%s: failed to move %s to init_net: %d\n",
index 4e2a79b2fd77f36ba2a31e9e43af1abc1207766e..4c6a252d42122d711f975f50f5c912e6d3fbcaff 100644 (file)
@@ -7455,12 +7455,12 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct __sk_buff, gso_segs):
                /* si->dst_reg = skb_shinfo(SKB); */
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
-               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
-                                     si->dst_reg, si->src_reg,
-                                     offsetof(struct sk_buff, head));
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
                                      BPF_REG_AX, si->src_reg,
                                      offsetof(struct sk_buff, end));
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct sk_buff, head));
                *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX);
 #else
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
@@ -8757,13 +8757,13 @@ sk_reuseport_is_valid_access(int off, int size,
                return size == size_default;
 
        /* Fields that allow narrowing */
-       case offsetof(struct sk_reuseport_md, eth_protocol):
+       case bpf_ctx_range(struct sk_reuseport_md, eth_protocol):
                if (size < FIELD_SIZEOF(struct sk_buff, protocol))
                        return false;
                /* fall through */
-       case offsetof(struct sk_reuseport_md, ip_protocol):
-       case offsetof(struct sk_reuseport_md, bind_inany):
-       case offsetof(struct sk_reuseport_md, len):
+       case bpf_ctx_range(struct sk_reuseport_md, ip_protocol):
+       case bpf_ctx_range(struct sk_reuseport_md, bind_inany):
+       case bpf_ctx_range(struct sk_reuseport_md, len):
                bpf_ctx_record_field_size(info, size_default);
                return bpf_ctx_narrow_access_ok(off, size, size_default);
 
index 3e6fedb57bc100e8ce002deddbade59371a73065..2470b4b404e62e625b17714f27fa7aba58eef9c5 100644 (file)
@@ -142,8 +142,8 @@ int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr)
                mutex_unlock(&flow_dissector_mutex);
                return -ENOENT;
        }
-       bpf_prog_put(attached);
        RCU_INIT_POINTER(net->flow_dissector_prog, NULL);
+       bpf_prog_put(attached);
        mutex_unlock(&flow_dissector_mutex);
        return 0;
 }
index 76f8db3841d7a3ebe0ee2ab40dff08b30d8a1a34..d63b970784dc74e41d431ef70379f9cb38e53915 100644 (file)
@@ -165,7 +165,7 @@ void flow_rule_match_enc_opts(const struct flow_rule *rule,
 }
 EXPORT_SYMBOL(flow_rule_match_enc_opts);
 
-struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
+struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
                                          void *cb_ident, void *cb_priv,
                                          void (*release)(void *cb_priv))
 {
@@ -175,7 +175,6 @@ struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
        if (!block_cb)
                return ERR_PTR(-ENOMEM);
 
-       block_cb->net = net;
        block_cb->cb = cb;
        block_cb->cb_ident = cb_ident;
        block_cb->cb_priv = cb_priv;
@@ -194,14 +193,13 @@ void flow_block_cb_free(struct flow_block_cb *block_cb)
 }
 EXPORT_SYMBOL(flow_block_cb_free);
 
-struct flow_block_cb *flow_block_cb_lookup(struct flow_block_offload *f,
-                                          tc_setup_cb_t *cb, void *cb_ident)
+struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
+                                          flow_setup_cb_t *cb, void *cb_ident)
 {
        struct flow_block_cb *block_cb;
 
-       list_for_each_entry(block_cb, f->driver_block_list, driver_list) {
-               if (block_cb->net == f->net &&
-                   block_cb->cb == cb &&
+       list_for_each_entry(block_cb, &block->cb_list, list) {
+               if (block_cb->cb == cb &&
                    block_cb->cb_ident == cb_ident)
                        return block_cb;
        }
@@ -228,7 +226,7 @@ unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb)
 }
 EXPORT_SYMBOL(flow_block_cb_decref);
 
-bool flow_block_cb_is_busy(tc_setup_cb_t *cb, void *cb_ident,
+bool flow_block_cb_is_busy(flow_setup_cb_t *cb, void *cb_ident,
                           struct list_head *driver_block_list)
 {
        struct flow_block_cb *block_cb;
@@ -245,7 +243,8 @@ EXPORT_SYMBOL(flow_block_cb_is_busy);
 
 int flow_block_cb_setup_simple(struct flow_block_offload *f,
                               struct list_head *driver_block_list,
-                              tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
+                              flow_setup_cb_t *cb,
+                              void *cb_ident, void *cb_priv,
                               bool ingress_only)
 {
        struct flow_block_cb *block_cb;
@@ -261,8 +260,7 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f,
                if (flow_block_cb_is_busy(cb, cb_ident, driver_block_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net, cb, cb_ident,
-                                              cb_priv, NULL);
+               block_cb = flow_block_cb_alloc(cb, cb_ident, cb_priv, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
 
@@ -270,7 +268,7 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f,
                list_add_tail(&block_cb->driver_list, driver_block_list);
                return 0;
        case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f, cb, cb_ident);
+               block_cb = flow_block_cb_lookup(f->block, cb, cb_ident);
                if (!block_cb)
                        return -ENOENT;
 
index 2cf27da1baebf48e6ced1a29ed5fc112a3def9a6..849380a622ef9d7fc2e8970c342245e15997fbda 100644 (file)
@@ -122,7 +122,7 @@ static void queue_process(struct work_struct *work)
                txq = netdev_get_tx_queue(dev, q_index);
                HARD_TX_LOCK(dev, txq, smp_processor_id());
                if (netif_xmit_frozen_or_stopped(txq) ||
-                   netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) {
+                   !dev_xmit_complete(netpoll_start_xmit(skb, dev, txq))) {
                        skb_queue_head(&npinfo->txq, skb);
                        HARD_TX_UNLOCK(dev, txq);
                        local_irq_restore(flags);
@@ -335,7 +335,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
 
                                HARD_TX_UNLOCK(dev, txq);
 
-                               if (status == NETDEV_TX_OK)
+                               if (dev_xmit_complete(status))
                                        break;
 
                        }
@@ -352,7 +352,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
 
        }
 
-       if (status != NETDEV_TX_OK) {
+       if (!dev_xmit_complete(status)) {
                skb_queue_tail(&npinfo->txq, skb);
                schedule_delayed_work(&npinfo->tx_work,0);
        }
index 0338820ee0ec67ce5b399b629984a0d05033e8c5..982d8d12830e411a2f262da3dffbc407ab40ff64 100644 (file)
@@ -3664,6 +3664,25 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
        int pos;
        int dummy;
 
+       if (list_skb && !list_skb->head_frag && skb_headlen(list_skb) &&
+           (skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY)) {
+               /* gso_size is untrusted, and we have a frag_list with a linear
+                * non head_frag head.
+                *
+                * (we assume checking the first list_skb member suffices;
+                * i.e if either of the list_skb members have non head_frag
+                * head, then the first one has too).
+                *
+                * If head_skb's headlen does not fit requested gso_size, it
+                * means that the frag_list members do NOT terminate on exact
+                * gso_size boundaries. Hence we cannot perform skb_frag_t page
+                * sharing. Therefore we must fallback to copying the frag_list
+                * skbs; we do so by disabling SG.
+                */
+               if (mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb))
+                       features &= ~NETIF_F_SG;
+       }
+
        __skb_push(head_skb, doffset);
        proto = skb_network_protocol(head_skb, &dummy);
        if (unlikely(!proto))
index 93bffaad21354d4a255a973d03bc7bcdf9477432..6832eeb4b785464f873d073f5cd3b41fdf956034 100644 (file)
@@ -585,12 +585,12 @@ EXPORT_SYMBOL_GPL(sk_psock_destroy);
 
 void sk_psock_drop(struct sock *sk, struct sk_psock *psock)
 {
-       rcu_assign_sk_user_data(sk, NULL);
        sk_psock_cork_free(psock);
        sk_psock_zap_ingress(psock);
-       sk_psock_restore_proto(sk, psock);
 
        write_lock_bh(&sk->sk_callback_lock);
+       sk_psock_restore_proto(sk, psock);
+       rcu_assign_sk_user_data(sk, NULL);
        if (psock->progs.skb_parser)
                sk_psock_stop_strp(sk, psock);
        write_unlock_bh(&sk->sk_callback_lock);
index d57b0cc995a0cea45d82bf73d8149aae9f7b2e17..545fac19a711f261fc6cdbdb54a3f08cb9705987 100644 (file)
@@ -1992,6 +1992,19 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
 }
 EXPORT_SYMBOL(skb_set_owner_w);
 
+static bool can_skb_orphan_partial(const struct sk_buff *skb)
+{
+#ifdef CONFIG_TLS_DEVICE
+       /* Drivers depend on in-order delivery for crypto offload,
+        * partial orphan breaks out-of-order-OK logic.
+        */
+       if (skb->decrypted)
+               return false;
+#endif
+       return (skb->destructor == sock_wfree ||
+               (IS_ENABLED(CONFIG_INET) && skb->destructor == tcp_wfree));
+}
+
 /* This helper is used by netem, as it can hold packets in its
  * delay queue. We want to allow the owner socket to send more
  * packets, as if they were already TX completed by a typical driver.
@@ -2003,11 +2016,7 @@ void skb_orphan_partial(struct sk_buff *skb)
        if (skb_is_tcp_pure_ack(skb))
                return;
 
-       if (skb->destructor == sock_wfree
-#ifdef CONFIG_INET
-           || skb->destructor == tcp_wfree
-#endif
-               ) {
+       if (can_skb_orphan_partial(skb)) {
                struct sock *sk = skb->sk;
 
                if (refcount_inc_not_zero(&sk->sk_refcnt)) {
@@ -3278,16 +3287,17 @@ static __init int net_inuse_init(void)
 
 core_initcall(net_inuse_init);
 
-static void assign_proto_idx(struct proto *prot)
+static int assign_proto_idx(struct proto *prot)
 {
        prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR);
 
        if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) {
                pr_err("PROTO_INUSE_NR exhausted\n");
-               return;
+               return -ENOSPC;
        }
 
        set_bit(prot->inuse_idx, proto_inuse_idx);
+       return 0;
 }
 
 static void release_proto_idx(struct proto *prot)
@@ -3296,8 +3306,9 @@ static void release_proto_idx(struct proto *prot)
                clear_bit(prot->inuse_idx, proto_inuse_idx);
 }
 #else
-static inline void assign_proto_idx(struct proto *prot)
+static inline int assign_proto_idx(struct proto *prot)
 {
+       return 0;
 }
 
 static inline void release_proto_idx(struct proto *prot)
@@ -3346,6 +3357,8 @@ static int req_prot_init(const struct proto *prot)
 
 int proto_register(struct proto *prot, int alloc_slab)
 {
+       int ret = -ENOBUFS;
+
        if (alloc_slab) {
                prot->slab = kmem_cache_create_usercopy(prot->name,
                                        prot->obj_size, 0,
@@ -3382,20 +3395,27 @@ int proto_register(struct proto *prot, int alloc_slab)
        }
 
        mutex_lock(&proto_list_mutex);
+       ret = assign_proto_idx(prot);
+       if (ret) {
+               mutex_unlock(&proto_list_mutex);
+               goto out_free_timewait_sock_slab_name;
+       }
        list_add(&prot->node, &proto_list);
-       assign_proto_idx(prot);
        mutex_unlock(&proto_list_mutex);
-       return 0;
+       return ret;
 
 out_free_timewait_sock_slab_name:
-       kfree(prot->twsk_prot->twsk_slab_name);
+       if (alloc_slab && prot->twsk_prot)
+               kfree(prot->twsk_prot->twsk_slab_name);
 out_free_request_sock_slab:
-       req_prot_cleanup(prot->rsk_prot);
+       if (alloc_slab) {
+               req_prot_cleanup(prot->rsk_prot);
 
-       kmem_cache_destroy(prot->slab);
-       prot->slab = NULL;
+               kmem_cache_destroy(prot->slab);
+               prot->slab = NULL;
+       }
 out:
-       return -ENOBUFS;
+       return ret;
 }
 EXPORT_SYMBOL(proto_register);
 
index 3312a5849a974e372a49164abca8f7067a2ed7e7..c13ffbd33d8d6ad4f591571325aaee321df5b242 100644 (file)
@@ -19,6 +19,7 @@ static const struct sock_diag_handler *sock_diag_handlers[AF_MAX];
 static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);
 static DEFINE_MUTEX(sock_diag_table_mutex);
 static struct workqueue_struct *broadcast_wq;
+static atomic64_t cookie_gen;
 
 u64 sock_gen_cookie(struct sock *sk)
 {
@@ -27,7 +28,7 @@ u64 sock_gen_cookie(struct sock *sk)
 
                if (res)
                        return res;
-               res = atomic64_inc_return(&sock_net(sk)->cookie_gen);
+               res = atomic64_inc_return(&cookie_gen);
                atomic64_cmpxchg(&sk->sk_cookie, 0, res);
        }
 }
index 52d4faeee18b0cecc8432ee71db16efb852b8644..50916f9bc4f2e5b7814943e7528f46d5df44b502 100644 (file)
@@ -247,6 +247,8 @@ static void sock_map_free(struct bpf_map *map)
        raw_spin_unlock_bh(&stab->lock);
        rcu_read_unlock();
 
+       synchronize_rcu();
+
        bpf_map_area_free(stab->sks);
        kfree(stab);
 }
@@ -276,16 +278,20 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
                             struct sock **psk)
 {
        struct sock *sk;
+       int err = 0;
 
        raw_spin_lock_bh(&stab->lock);
        sk = *psk;
        if (!sk_test || sk_test == sk)
-               *psk = NULL;
+               sk = xchg(psk, NULL);
+
+       if (likely(sk))
+               sock_map_unref(sk, psk);
+       else
+               err = -EINVAL;
+
        raw_spin_unlock_bh(&stab->lock);
-       if (unlikely(!sk))
-               return -EINVAL;
-       sock_map_unref(sk, psk);
-       return 0;
+       return err;
 }
 
 static void sock_map_delete_from_link(struct bpf_map *map, struct sock *sk,
@@ -328,6 +334,7 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx,
                                  struct sock *sk, u64 flags)
 {
        struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
+       struct inet_connection_sock *icsk = inet_csk(sk);
        struct sk_psock_link *link;
        struct sk_psock *psock;
        struct sock *osk;
@@ -338,6 +345,8 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx,
                return -EINVAL;
        if (unlikely(idx >= map->max_entries))
                return -E2BIG;
+       if (unlikely(icsk->icsk_ulp_data))
+               return -EINVAL;
 
        link = sk_psock_init_link();
        if (!link)
@@ -647,6 +656,7 @@ static int sock_hash_update_common(struct bpf_map *map, void *key,
                                   struct sock *sk, u64 flags)
 {
        struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+       struct inet_connection_sock *icsk = inet_csk(sk);
        u32 key_size = map->key_size, hash;
        struct bpf_htab_elem *elem, *elem_new;
        struct bpf_htab_bucket *bucket;
@@ -657,6 +667,8 @@ static int sock_hash_update_common(struct bpf_map *map, void *key,
        WARN_ON_ONCE(!rcu_read_lock_held());
        if (unlikely(flags > BPF_EXIST))
                return -EINVAL;
+       if (unlikely(icsk->icsk_ulp_data))
+               return -EINVAL;
 
        link = sk_psock_init_link();
        if (!link)
index e94bb02a56295ec2db34ab423a8c7c890df0a696..4f1d4aa5fb38d989a9c81f32dfce3f31bbc1fa47 100644 (file)
@@ -120,7 +120,6 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
        int err = 0;
        long vm_wait = 0;
        long current_timeo = *timeo_p;
-       bool noblock = (*timeo_p ? false : true);
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
        if (sk_stream_memory_free(sk))
@@ -133,11 +132,8 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
 
                if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
                        goto do_error;
-               if (!*timeo_p) {
-                       if (noblock)
-                               set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
-                       goto do_nonblock;
-               }
+               if (!*timeo_p)
+                       goto do_eagain;
                if (signal_pending(current))
                        goto do_interrupted;
                sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
@@ -169,7 +165,13 @@ out:
 do_error:
        err = -EPIPE;
        goto out;
-do_nonblock:
+do_eagain:
+       /* Make sure that whenever EAGAIN is returned, EPOLLOUT event can
+        * be generated later.
+        * When TCP receives ACK packets that make room, tcp_check_space()
+        * only calls tcp_new_space() if SOCK_NOSPACE is set.
+        */
+       set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
        err = -EAGAIN;
        goto out;
 do_interrupted:
index 614c38ece104307a2c54dc76a8014402061ae240..33f41178afccf207abfeafd7e3fa05cf0e832129 100644 (file)
@@ -951,7 +951,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
                                    struct flow_block_offload *f)
 {
        struct flow_block_cb *block_cb;
-       tc_setup_cb_t *cb;
+       flow_setup_cb_t *cb;
 
        if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
                cb = dsa_slave_setup_tc_block_cb_ig;
@@ -967,7 +967,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
                if (flow_block_cb_is_busy(cb, dev, &dsa_slave_block_cb_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net, cb, dev, dev, NULL);
+               block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
 
@@ -975,7 +975,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
                list_add_tail(&block_cb->driver_list, &dsa_slave_block_cb_list);
                return 0;
        case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f, cb, dev);
+               block_cb = flow_block_cb_lookup(f->block, cb, dev);
                if (!block_cb)
                        return -ENOENT;
 
index 4ec5b7f85d51ea2274b69e0ae68fa824fac2edde..09d9286b27ccb9fb215f3bafb0511d49dfaa1062 100644 (file)
@@ -153,6 +153,9 @@ static void dsa_switch_mdb_add_bitmap(struct dsa_switch *ds,
 {
        int port;
 
+       if (!ds->ops->port_mdb_add)
+               return;
+
        for_each_set_bit(port, bitmap, ds->num_ports)
                ds->ops->port_mdb_add(ds, port, mdb);
 }
index 6ebbd799c4eb61648f2466dc3d7498c7b1b954a4..67a1bc635a7b4342d0a7e935272776edf1295f7a 100644 (file)
@@ -28,6 +28,7 @@
  *
  * RSV - VID[9]:
  *     To be used for further expansion of SWITCH_ID or for other purposes.
+ *     Must be transmitted as zero and ignored on receive.
  *
  * SWITCH_ID - VID[8:6]:
  *     Index of switch within DSA tree. Must be between 0 and
@@ -35,6 +36,7 @@
  *
  * RSV - VID[5:4]:
  *     To be used for further expansion of PORT or for other purposes.
+ *     Must be transmitted as zero and ignored on receive.
  *
  * PORT - VID[3:0]:
  *     Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1.
index 26363d72d25b35377bf844466b10e2844cbb70f6..47ee88163a9daede6494af72025d2f86974d167b 100644 (file)
@@ -165,6 +165,7 @@ static struct sk_buff
                                            "Expected meta frame, is %12llx "
                                            "in the DSA master multicast filter?\n",
                                            SJA1105_META_DMAC);
+                       kfree_skb(sp->data->stampable_skb);
                }
 
                /* Hold a reference to avoid dsa_switch_rcv
@@ -211,17 +212,8 @@ static struct sk_buff
                 * for further processing up the network stack.
                 */
                kfree_skb(skb);
-
-               skb = skb_copy(stampable_skb, GFP_ATOMIC);
-               if (!skb) {
-                       dev_err_ratelimited(dp->ds->dev,
-                                           "Failed to copy stampable skb\n");
-                       spin_unlock(&sp->data->meta_lock);
-                       return NULL;
-               }
+               skb = stampable_skb;
                sja1105_transfer_meta(skb, meta);
-               /* The cached copy will be freed now */
-               skb_unref(stampable_skb);
 
                spin_unlock(&sp->data->meta_lock);
        }
index e4aba5d485be6a59c639a23b75172f5015c4280f..bbe9b3b2d3959fef28d1d94a0bcc0a71077d607d 100644 (file)
@@ -170,7 +170,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *skb,
        reasm_data = inet_frag_reasm_prepare(&fq->q, skb, prev_tail);
        if (!reasm_data)
                goto out_oom;
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, false);
 
        skb->dev = ldev;
        skb->tstamp = fq->q.stamp;
index dacbd58e1799225b389afddca14e5923164202de..badc5cfe4dc63e1660696443e7f01e5707e81206 100644 (file)
@@ -1092,7 +1092,7 @@ static struct packet_type ieee802154_packet_type = {
 
 static int __init af_ieee802154_init(void)
 {
-       int rc = -EINVAL;
+       int rc;
 
        rc = proto_register(&ieee802154_raw_prot, 1);
        if (rc)
index 2db089e10ba0ee524ce50cec26c19137002a9992..0913a090b2bf4232d82b6294051d4924052f66b1 100644 (file)
@@ -1582,7 +1582,7 @@ failure:
 }
 
 int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nhc,
-                    unsigned char *flags, bool skip_oif)
+                    u8 rt_family, unsigned char *flags, bool skip_oif)
 {
        if (nhc->nhc_flags & RTNH_F_DEAD)
                *flags |= RTNH_F_DEAD;
@@ -1613,7 +1613,7 @@ int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nhc,
                /* if gateway family does not match nexthop family
                 * gateway is encoded as RTA_VIA
                 */
-               if (nhc->nhc_gw_family != nhc->nhc_family) {
+               if (rt_family != nhc->nhc_gw_family) {
                        int alen = sizeof(struct in6_addr);
                        struct nlattr *nla;
                        struct rtvia *via;
@@ -1654,7 +1654,7 @@ EXPORT_SYMBOL_GPL(fib_nexthop_info);
 
 #if IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) || IS_ENABLED(CONFIG_IPV6)
 int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc,
-                   int nh_weight)
+                   int nh_weight, u8 rt_family)
 {
        const struct net_device *dev = nhc->nhc_dev;
        struct rtnexthop *rtnh;
@@ -1667,7 +1667,7 @@ int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc,
        rtnh->rtnh_hops = nh_weight - 1;
        rtnh->rtnh_ifindex = dev ? dev->ifindex : 0;
 
-       if (fib_nexthop_info(skb, nhc, &flags, true) < 0)
+       if (fib_nexthop_info(skb, nhc, rt_family, &flags, true) < 0)
                goto nla_put_failure;
 
        rtnh->rtnh_flags = flags;
@@ -1693,13 +1693,14 @@ static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
                goto nla_put_failure;
 
        if (unlikely(fi->nh)) {
-               if (nexthop_mpath_fill_node(skb, fi->nh) < 0)
+               if (nexthop_mpath_fill_node(skb, fi->nh, AF_INET) < 0)
                        goto nla_put_failure;
                goto mp_end;
        }
 
        for_nexthops(fi) {
-               if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight) < 0)
+               if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight,
+                                   AF_INET) < 0)
                        goto nla_put_failure;
 #ifdef CONFIG_IP_ROUTE_CLASSID
                if (nh->nh_tclassid &&
@@ -1775,7 +1776,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
                const struct fib_nh_common *nhc = fib_info_nhc(fi, 0);
                unsigned char flags = 0;
 
-               if (fib_nexthop_info(skb, nhc, &flags, false) < 0)
+               if (fib_nexthop_info(skb, nhc, AF_INET, &flags, false) < 0)
                        goto nla_put_failure;
 
                rtm->rtm_flags = flags;
index 2b2b3d291ab061a916ce9aa0371a865cf7eb8107..1ab2fb6bb37d7d8de416d5c7cf84efe21dc8faf3 100644 (file)
@@ -2145,7 +2145,7 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb,
 
                if (filter->dump_exceptions) {
                        err = fib_dump_info_fnhe(skb, cb, tb->tb_id, fi,
-                                                &i_fa, s_fa);
+                                                &i_fa, s_fa, flags);
                        if (err < 0)
                                goto stop;
                }
index 1510e951f4511a351ba0afa7330731bb16331fc9..4298aae74e0ee6266286fa49e9cfda602b2a9cd0 100644 (file)
@@ -582,7 +582,13 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
 
        if (!rt)
                goto out;
-       net = dev_net(rt->dst.dev);
+
+       if (rt->dst.dev)
+               net = dev_net(rt->dst.dev);
+       else if (skb_in->dev)
+               net = dev_net(skb_in->dev);
+       else
+               goto out;
 
        /*
         *      Find the original header. It is expected to be valid, of course.
@@ -902,7 +908,7 @@ static bool icmp_redirect(struct sk_buff *skb)
                return false;
        }
 
-       icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway);
+       icmp_socket_deliver(skb, ntohl(icmp_hdr(skb)->un.gateway));
        return true;
 }
 
index 180f6896b98baade47bf9e2a4b208043fbc6cca3..480d0b22db1a6d0cb36688fff01966fdb7375d1f 100644 (file)
@@ -1475,7 +1475,7 @@ EXPORT_SYMBOL(__ip_mc_inc_group);
 
 void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
 {
-       __ip_mc_inc_group(in_dev, addr, MCAST_EXCLUDE);
+       __ip_mc_inc_group(in_dev, addr, GFP_KERNEL);
 }
 EXPORT_SYMBOL(ip_mc_inc_group);
 
@@ -2197,7 +2197,7 @@ static int __ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr,
        iml->sflist = NULL;
        iml->sfmode = mode;
        rcu_assign_pointer(inet->mc_list, iml);
-       __ip_mc_inc_group(in_dev, addr, mode);
+       ____ip_mc_inc_group(in_dev, addr, mode, GFP_KERNEL);
        err = 0;
 done:
        return err;
index d666756be5f18404ce8e85a95e9f09636d5f2694..10d31733297d7358b55b45d64bc447039365df1d 100644 (file)
@@ -331,7 +331,7 @@ struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key)
        prev = rhashtable_lookup(&fqdir->rhashtable, key, fqdir->f->rhash_params);
        if (!prev)
                fq = inet_frag_create(fqdir, key, &prev);
-       if (prev && !IS_ERR(prev)) {
+       if (!IS_ERR_OR_NULL(prev)) {
                fq = prev;
                if (!refcount_inc_not_zero(&fq->refcnt))
                        fq = NULL;
@@ -475,11 +475,12 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
 EXPORT_SYMBOL(inet_frag_reasm_prepare);
 
 void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
-                           void *reasm_data)
+                           void *reasm_data, bool try_coalesce)
 {
        struct sk_buff **nextp = (struct sk_buff **)reasm_data;
        struct rb_node *rbn;
        struct sk_buff *fp;
+       int sum_truesize;
 
        skb_push(head, head->data - skb_network_header(head));
 
@@ -487,25 +488,41 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
        fp = FRAG_CB(head)->next_frag;
        rbn = rb_next(&head->rbnode);
        rb_erase(&head->rbnode, &q->rb_fragments);
+
+       sum_truesize = head->truesize;
        while (rbn || fp) {
                /* fp points to the next sk_buff in the current run;
                 * rbn points to the next run.
                 */
                /* Go through the current run. */
                while (fp) {
-                       *nextp = fp;
-                       nextp = &fp->next;
-                       fp->prev = NULL;
-                       memset(&fp->rbnode, 0, sizeof(fp->rbnode));
-                       fp->sk = NULL;
-                       head->data_len += fp->len;
-                       head->len += fp->len;
+                       struct sk_buff *next_frag = FRAG_CB(fp)->next_frag;
+                       bool stolen;
+                       int delta;
+
+                       sum_truesize += fp->truesize;
                        if (head->ip_summed != fp->ip_summed)
                                head->ip_summed = CHECKSUM_NONE;
                        else if (head->ip_summed == CHECKSUM_COMPLETE)
                                head->csum = csum_add(head->csum, fp->csum);
-                       head->truesize += fp->truesize;
-                       fp = FRAG_CB(fp)->next_frag;
+
+                       if (try_coalesce && skb_try_coalesce(head, fp, &stolen,
+                                                            &delta)) {
+                               kfree_skb_partial(fp, stolen);
+                       } else {
+                               fp->prev = NULL;
+                               memset(&fp->rbnode, 0, sizeof(fp->rbnode));
+                               fp->sk = NULL;
+
+                               head->data_len += fp->len;
+                               head->len += fp->len;
+                               head->truesize += fp->truesize;
+
+                               *nextp = fp;
+                               nextp = &fp->next;
+                       }
+
+                       fp = next_frag;
                }
                /* Move to the next run. */
                if (rbn) {
@@ -516,7 +533,7 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
                        rbn = rbnext;
                }
        }
-       sub_frag_mem_limit(q->fqdir, head->truesize);
+       sub_frag_mem_limit(q->fqdir, sum_truesize);
 
        *nextp = NULL;
        skb_mark_not_on_list(head);
index 4385eb9e781ffc017a65d166ddf12c11fc901c0e..cfeb8890f94ee95b2246ba98beb338a33fc45d1d 100644 (file)
@@ -393,6 +393,11 @@ err:
        return err;
 }
 
+static bool ip_frag_coalesce_ok(const struct ipq *qp)
+{
+       return qp->q.key.v4.user == IP_DEFRAG_LOCAL_DELIVER;
+}
+
 /* Build a new IP datagram from all its fragments. */
 static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
                         struct sk_buff *prev_tail, struct net_device *dev)
@@ -421,7 +426,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
        if (len > 65535)
                goto out_oversize;
 
-       inet_frag_reasm_finish(&qp->q, skb, reasm_data);
+       inet_frag_reasm_finish(&qp->q, skb, reasm_data,
+                              ip_frag_coalesce_ok(qp));
 
        skb->dev = dev;
        IPCB(skb)->frag_max_size = max(qp->max_df_size, qp->q.max_size);
index 43adfc1641bacac2df882970e1eafca318896041..2f01cf6fa0deffb6f86a4db89b0aa8b951d0f352 100644 (file)
@@ -275,6 +275,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb,
        const struct iphdr  *tiph = &tunnel->parms.iph;
        u8 ipproto;
 
+       if (!pskb_inet_may_pull(skb))
+               goto tx_error;
+
        switch (skb->protocol) {
        case htons(ETH_P_IP):
                ipproto = IPPROTO_IPIP;
index 4d6bf7ac07925dc0d8f0a0e6e43af559763bbf7e..6bdb1ab8af6170938ecfe55b43d4de18352a7fc7 100644 (file)
@@ -416,8 +416,8 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par)
             ctinfo == IP_CT_RELATED_REPLY))
                return XT_CONTINUE;
 
-       /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
-        * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
+       /* nf_conntrack_proto_icmp guarantees us that we only have ICMP_ECHO,
+        * TIMESTAMP, INFO_REQUEST or ICMP_ADDRESS type icmp packets from here
         * on, which all have an ID field [relevant for hashing]. */
 
        hash = clusterip_hashfn(skb, cipinfo->config);
index 8e7f84ec783da52e78a2f040a13f6bd60f2efee5..0e70f3f65f6fe3dfe5394731079021688d9f8a51 100644 (file)
@@ -36,6 +36,8 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
                        opts.options |= XT_SYNPROXY_OPT_ECN;
 
                opts.options &= info->options;
+               opts.mss_encode = opts.mss;
+               opts.mss = info->mss;
                if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP)
                        synproxy_init_timestamp_cookie(info, &opts);
                else
index 59031670b16a016d34fab235c2a1d86bd4210f73..cc23f1ce239c28ac9c12ef1a5ef5316407e2bee9 100644 (file)
@@ -78,6 +78,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
        flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
        flow.flowi4_tos = RT_TOS(iph->tos);
        flow.flowi4_scope = RT_SCOPE_UNIVERSE;
+       flow.flowi4_oif = l3mdev_master_ifindex_rcu(xt_in(par));
 
        return rpfilter_lookup_reverse(xt_net(par), &flow, xt_in(par), info->flags) ^ invert;
 }
index 87b711fd5a442633fc493dee2fcacc3ff34b9095..3e2685c120c772f428c6c23a7d6d245354aa5ce1 100644 (file)
@@ -221,11 +221,11 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
-               ret = nf_ct_expect_related(rtp_exp);
+               ret = nf_ct_expect_related(rtp_exp, 0);
                if (ret == 0) {
                        rtcp_exp->tuple.dst.u.udp.port =
                            htons(nated_port + 1);
-                       ret = nf_ct_expect_related(rtcp_exp);
+                       ret = nf_ct_expect_related(rtcp_exp, 0);
                        if (ret == 0)
                                break;
                        else if (ret == -EBUSY) {
@@ -296,7 +296,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
@@ -352,7 +352,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
@@ -444,7 +444,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
@@ -537,7 +537,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
index 517300d587a7df0110430a85c08917104626f858..b6a6f18c3dd144d2feb4b1841845bca5535092fc 100644 (file)
@@ -2728,7 +2728,8 @@ EXPORT_SYMBOL_GPL(ip_route_output_flow);
 /* called with rcu_read_lock held */
 static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
                        struct rtable *rt, u32 table_id, struct flowi4 *fl4,
-                       struct sk_buff *skb, u32 portid, u32 seq)
+                       struct sk_buff *skb, u32 portid, u32 seq,
+                       unsigned int flags)
 {
        struct rtmsg *r;
        struct nlmsghdr *nlh;
@@ -2736,7 +2737,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
        u32 error;
        u32 metrics[RTAX_MAX];
 
-       nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*r), 0);
+       nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*r), flags);
        if (!nlh)
                return -EMSGSIZE;
 
@@ -2860,7 +2861,7 @@ nla_put_failure:
 static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb,
                            struct netlink_callback *cb, u32 table_id,
                            struct fnhe_hash_bucket *bucket, int genid,
-                           int *fa_index, int fa_start)
+                           int *fa_index, int fa_start, unsigned int flags)
 {
        int i;
 
@@ -2891,7 +2892,7 @@ static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb,
                        err = rt_fill_info(net, fnhe->fnhe_daddr, 0, rt,
                                           table_id, NULL, skb,
                                           NETLINK_CB(cb->skb).portid,
-                                          cb->nlh->nlmsg_seq);
+                                          cb->nlh->nlmsg_seq, flags);
                        if (err)
                                return err;
 next:
@@ -2904,7 +2905,7 @@ next:
 
 int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb,
                       u32 table_id, struct fib_info *fi,
-                      int *fa_index, int fa_start)
+                      int *fa_index, int fa_start, unsigned int flags)
 {
        struct net *net = sock_net(cb->skb->sk);
        int nhsel, genid = fnhe_genid(net);
@@ -2922,7 +2923,8 @@ int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb,
                err = 0;
                if (bucket)
                        err = fnhe_dump_bucket(net, skb, cb, table_id, bucket,
-                                              genid, fa_index, fa_start);
+                                              genid, fa_index, fa_start,
+                                              flags);
                rcu_read_unlock();
                if (err)
                        return err;
@@ -3183,7 +3185,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
                                    fl4.flowi4_tos, res.fi, 0);
        } else {
                err = rt_fill_info(net, dst, src, rt, table_id, &fl4, skb,
-                                  NETLINK_CB(in_skb).portid, nlh->nlmsg_seq);
+                                  NETLINK_CB(in_skb).portid,
+                                  nlh->nlmsg_seq, 0);
        }
        if (err < 0)
                goto errout_rcu;
index 776905899ac06bcbaa7ece1f580303478e736d56..61082065b26a068975c411b74eb46739ab0632ca 100644 (file)
@@ -935,6 +935,22 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
        return mss_now;
 }
 
+/* In some cases, both sendpage() and sendmsg() could have added
+ * an skb to the write queue, but failed adding payload on it.
+ * We need to remove it to consume less memory, but more
+ * importantly be able to generate EPOLLOUT for Edge Trigger epoll()
+ * users.
+ */
+static void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb)
+{
+       if (skb && !skb->len) {
+               tcp_unlink_write_queue(skb, sk);
+               if (tcp_write_queue_empty(sk))
+                       tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
+               sk_wmem_free_skb(sk, skb);
+       }
+}
+
 ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
                         size_t size, int flags)
 {
@@ -984,6 +1000,9 @@ new_segment:
                        if (!skb)
                                goto wait_for_memory;
 
+#ifdef CONFIG_TLS_DEVICE
+                       skb->decrypted = !!(flags & MSG_SENDPAGE_DECRYPTED);
+#endif
                        skb_entail(sk, skb);
                        copy = size_goal;
                }
@@ -1061,6 +1080,7 @@ out:
        return copied;
 
 do_error:
+       tcp_remove_empty_skb(sk, tcp_write_queue_tail(sk));
        if (copied)
                goto out;
 out_err:
@@ -1385,18 +1405,11 @@ out_nopush:
        sock_zerocopy_put(uarg);
        return copied + copied_syn;
 
+do_error:
+       skb = tcp_write_queue_tail(sk);
 do_fault:
-       if (!skb->len) {
-               tcp_unlink_write_queue(skb, sk);
-               /* It is the one place in all of TCP, except connection
-                * reset, where we can be unlinking the send_head.
-                */
-               if (tcp_write_queue_empty(sk))
-                       tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
-               sk_wmem_free_skb(sk, skb);
-       }
+       tcp_remove_empty_skb(sk, skb);
 
-do_error:
        if (copied + copied_syn)
                goto out;
 out_err:
index 3d1e1540138440a0c0f6a65aabd888626ad0e384..8a56e09cfb0ed3ebf03795ae4b5d1eb3f04221ba 100644 (file)
@@ -398,10 +398,14 @@ more_data:
 static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 {
        struct sk_msg tmp, *msg_tx = NULL;
-       int flags = msg->msg_flags | MSG_NO_SHARED_FRAGS;
        int copied = 0, err = 0;
        struct sk_psock *psock;
        long timeo;
+       int flags;
+
+       /* Don't let internal do_tcp_sendpages() flags through */
+       flags = (msg->msg_flags & ~MSG_SENDPAGE_DECRYPTED);
+       flags |= MSG_NO_SHARED_FRAGS;
 
        psock = sk_psock_get(sk);
        if (unlikely(!psock))
index c21e8a22fb3bb39d06eb3ee7eb4cfae5066b6f48..8a1cd93dbb09d2f06ff6e2f39b496ca28341093f 100644 (file)
@@ -266,7 +266,7 @@ static void tcp_ecn_accept_cwr(struct sock *sk, const struct sk_buff *skb)
 
 static void tcp_ecn_withdraw_cwr(struct tcp_sock *tp)
 {
-       tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR;
+       tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
 }
 
 static void __tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb)
index 4af1f5dae9d3e937ef39685355c9d3f19ff3ee3b..8a645f304e6c0a581e0ad26d7d4083491fab0578 100644 (file)
@@ -1288,6 +1288,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *buff;
        int nsize, old_factor;
+       long limit;
        int nlen;
        u8 flags;
 
@@ -1298,8 +1299,16 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        if (nsize < 0)
                nsize = 0;
 
-       if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf &&
-                    tcp_queue != TCP_FRAG_IN_WRITE_QUEUE)) {
+       /* tcp_sendmsg() can overshoot sk_wmem_queued by one full size skb.
+        * We need some allowance to not penalize applications setting small
+        * SO_SNDBUF values.
+        * Also allow first and last skb in retransmit queue to be split.
+        */
+       limit = sk->sk_sndbuf + 2 * SKB_TRUESIZE(GSO_MAX_SIZE);
+       if (unlikely((sk->sk_wmem_queued >> 1) > limit &&
+                    tcp_queue != TCP_FRAG_IN_WRITE_QUEUE &&
+                    skb != tcp_rtx_queue_head(sk) &&
+                    skb != tcp_rtx_queue_tail(sk))) {
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG);
                return -ENOMEM;
        }
@@ -1311,6 +1320,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        buff = sk_stream_alloc_skb(sk, nsize, gfp, true);
        if (!buff)
                return -ENOMEM; /* We'll just try again later. */
+       skb_copy_decrypted(buff, skb);
 
        sk->sk_wmem_queued += buff->truesize;
        sk_mem_charge(sk, buff->truesize);
@@ -1865,6 +1875,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
        buff = sk_stream_alloc_skb(sk, 0, gfp, true);
        if (unlikely(!buff))
                return -ENOMEM;
+       skb_copy_decrypted(buff, skb);
 
        sk->sk_wmem_queued += buff->truesize;
        sk_mem_charge(sk, buff->truesize);
@@ -2042,7 +2053,7 @@ static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len)
                if (len <= skb->len)
                        break;
 
-               if (unlikely(TCP_SKB_CB(skb)->eor))
+               if (unlikely(TCP_SKB_CB(skb)->eor) || tcp_has_tx_tstamp(skb))
                        return false;
 
                len -= skb->len;
@@ -2134,6 +2145,7 @@ static int tcp_mtu_probe(struct sock *sk)
        sk_mem_charge(sk, nskb->truesize);
 
        skb = tcp_send_head(sk);
+       skb_copy_decrypted(nskb, skb);
 
        TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
        TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
@@ -2158,6 +2170,7 @@ static int tcp_mtu_probe(struct sock *sk)
                         * we need to propagate it to the new skb.
                         */
                        TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor;
+                       tcp_skb_collapse_tstamp(nskb, skb);
                        tcp_unlink_write_queue(skb, sk);
                        sk_wmem_free_skb(sk, skb);
                } else {
index 3d8a1d8354719378ef157e36dbe21c57af9a4b7c..4849edb62d52964c61ef2d0601c16baa662e196d 100644 (file)
@@ -96,6 +96,19 @@ void tcp_get_available_ulp(char *buf, size_t maxlen)
        rcu_read_unlock();
 }
 
+void tcp_update_ulp(struct sock *sk, struct proto *proto)
+{
+       struct inet_connection_sock *icsk = inet_csk(sk);
+
+       if (!icsk->icsk_ulp_ops) {
+               sk->sk_prot = proto;
+               return;
+       }
+
+       if (icsk->icsk_ulp_ops->update)
+               icsk->icsk_ulp_ops->update(sk, proto);
+}
+
 void tcp_cleanup_ulp(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
index dc73888c7859a2d0d499fabd14aa8b71e12b0e77..6a576ff92c399fbb686c839c525e700f2579b1a9 100644 (file)
@@ -478,7 +478,7 @@ static struct inet6_dev *ipv6_find_idev(struct net_device *dev)
        if (!idev) {
                idev = ipv6_add_dev(dev);
                if (IS_ERR(idev))
-                       return NULL;
+                       return idev;
        }
 
        if (dev->flags&IFF_UP)
@@ -1045,7 +1045,8 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
        int err = 0;
 
        if (addr_type == IPV6_ADDR_ANY ||
-           addr_type & IPV6_ADDR_MULTICAST ||
+           (addr_type & IPV6_ADDR_MULTICAST &&
+            !(cfg->ifa_flags & IFA_F_MCAUTOJOIN)) ||
            (!(idev->dev->flags & IFF_LOOPBACK) &&
             !netif_is_l3_master(idev->dev) &&
             addr_type & IPV6_ADDR_LOOPBACK))
@@ -2465,8 +2466,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
        ASSERT_RTNL();
 
        idev = ipv6_find_idev(dev);
-       if (!idev)
-               return ERR_PTR(-ENOBUFS);
+       if (IS_ERR(idev))
+               return idev;
 
        if (idev->cnf.disable_ipv6)
                return ERR_PTR(-EACCES);
@@ -3158,7 +3159,7 @@ static void init_loopback(struct net_device *dev)
        ASSERT_RTNL();
 
        idev = ipv6_find_idev(dev);
-       if (!idev) {
+       if (IS_ERR(idev)) {
                pr_debug("%s: add_dev failed\n", __func__);
                return;
        }
@@ -3373,7 +3374,7 @@ static void addrconf_sit_config(struct net_device *dev)
         */
 
        idev = ipv6_find_idev(dev);
-       if (!idev) {
+       if (IS_ERR(idev)) {
                pr_debug("%s: add_dev failed\n", __func__);
                return;
        }
@@ -3398,7 +3399,7 @@ static void addrconf_gre_config(struct net_device *dev)
        ASSERT_RTNL();
 
        idev = ipv6_find_idev(dev);
-       if (!idev) {
+       if (IS_ERR(idev)) {
                pr_debug("%s: add_dev failed\n", __func__);
                return;
        }
@@ -4772,8 +4773,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
                         IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
 
        idev = ipv6_find_idev(dev);
-       if (!idev)
-               return -ENOBUFS;
+       if (IS_ERR(idev))
+               return PTR_ERR(idev);
 
        if (!ipv6_allow_optimistic_dad(net, idev))
                cfg.ifa_flags &= ~IFA_F_OPTIMISTIC;
index c2049c72f3e533a7077674ca6dac43b527eb8b7f..dd2d0b96326074d3255eee91891938dc1d948483 100644 (file)
@@ -660,12 +660,13 @@ static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
                                    struct flowi6 *fl6, __u8 *dsfield,
                                    int *encap_limit)
 {
-       struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+       struct ipv6hdr *ipv6h;
        struct ip6_tnl *t = netdev_priv(dev);
        __u16 offset;
 
        offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
        /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+       ipv6h = ipv6_hdr(skb);
 
        if (offset > 0) {
                struct ipv6_tlv_tnl_enc_lim *tel;
index 3134fbb65d7f268d2b8785b3feb622a36c2d15c3..754a484d35df6eb03b82593cbb66a78718e30326 100644 (file)
@@ -1278,12 +1278,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+       dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
 
        if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
                return -1;
 
-       dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
-
        skb_set_inner_ipproto(skb, IPPROTO_IPIP);
 
        err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1367,12 +1366,11 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+       dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
 
        if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
                return -1;
 
-       dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
-
        skb_set_inner_ipproto(skb, IPPROTO_IPV6);
 
        err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
index 7f3f13c3791636f92c5c46aa6235c69682dea151..eaa4c2cc2fbb2e784b5641135d28dd38a0616421 100644 (file)
@@ -787,14 +787,15 @@ static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
        if (pmc) {
                im->idev = pmc->idev;
                if (im->mca_sfmode == MCAST_INCLUDE) {
-                       im->mca_tomb = pmc->mca_tomb;
-                       im->mca_sources = pmc->mca_sources;
+                       swap(im->mca_tomb, pmc->mca_tomb);
+                       swap(im->mca_sources, pmc->mca_sources);
                        for (psf = im->mca_sources; psf; psf = psf->sf_next)
                                psf->sf_crcount = idev->mc_qrv;
                } else {
                        im->mca_crcount = idev->mc_qrv;
                }
                in6_dev_put(pmc->idev);
+               ip6_mc_clear_src(pmc);
                kfree(pmc);
        }
        spin_unlock_bh(&im->mca_lock);
index e77ea1ed5eddd41faeb5879c93879d0d29d6b903..5cdb4a69d277c49e04a1967cec9ea9e713f0e3ad 100644 (file)
@@ -36,6 +36,8 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
                        opts.options |= XT_SYNPROXY_OPT_ECN;
 
                opts.options &= info->options;
+               opts.mss_encode = opts.mss;
+               opts.mss = info->mss;
                if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP)
                        synproxy_init_timestamp_cookie(info, &opts);
                else
index 6bcaf735718343f9bb75ebed5fd1d4b2ab78201c..d800801a5dd27ca0527fb8b9008595813c06338a 100644 (file)
@@ -55,7 +55,9 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
        if (rpfilter_addr_linklocal(&iph->saddr)) {
                lookup_flags |= RT6_LOOKUP_F_IFACE;
                fl6.flowi6_oif = dev->ifindex;
-       } else if ((flags & XT_RPFILTER_LOOSE) == 0)
+       /* Set flowi6_oif for vrf devices to lookup route in l3mdev domain. */
+       } else if (netif_is_l3_master(dev) || netif_is_l3_slave(dev) ||
+                 (flags & XT_RPFILTER_LOOSE) == 0)
                fl6.flowi6_oif = dev->ifindex;
 
        rt = (void *)ip6_route_lookup(net, &fl6, skb, lookup_flags);
@@ -70,7 +72,9 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
                goto out;
        }
 
-       if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))
+       if (rt->rt6i_idev->dev == dev ||
+           l3mdev_master_ifindex_rcu(rt->rt6i_idev->dev) == dev->ifindex ||
+           (flags & XT_RPFILTER_LOOSE))
                ret = true;
  out:
        ip6_rt_put(rt);
index 0f82c150543b75f42c35f0199244a3a8cf5dd3f7..fed9666a2f7da13cd2d686b71a1454401a18b7b4 100644 (file)
@@ -348,7 +348,7 @@ static int nf_ct_frag6_reasm(struct frag_queue *fq, struct sk_buff *skb,
 
        skb_reset_transport_header(skb);
 
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, false);
 
        skb->ignore_df = 1;
        skb->dev = dev;
index 87d2d8c1db7cc86940d6216b50d3bdadfb588937..98ac32b49d8c9a4fe6158d8c9e7b759373483709 100644 (file)
@@ -223,7 +223,7 @@ static int __net_init ping_v6_proc_init_net(struct net *net)
        return 0;
 }
 
-static void __net_init ping_v6_proc_exit_net(struct net *net)
+static void __net_exit ping_v6_proc_exit_net(struct net *net)
 {
        remove_proc_entry("icmp6", net->proc_net);
 }
index ca05b16f1bb95d4122a79fa9759011fd204f3e6f..1f5d4d196dccee12ee979f305b1b904864ff246e 100644 (file)
@@ -282,7 +282,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb,
 
        skb_reset_transport_header(skb);
 
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, true);
 
        skb->dev = dev;
        ipv6_hdr(skb)->payload_len = htons(payload_len);
index e49fec767a10af5f6f03983f10cdf9d9f626ed3e..546088e50815158a81ebe953a3a1ec820243c367 100644 (file)
@@ -1951,7 +1951,7 @@ static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
                nexthop_for_each_fib6_nh(from->nh, fib6_nh_find_match, &arg);
 
                if (!arg.match)
-                       return;
+                       goto unlock;
                fib6_nh = arg.match;
        } else {
                fib6_nh = from->fib6_nh;
@@ -4388,13 +4388,14 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
        struct fib6_config cfg = {
                .fc_table = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL,
                .fc_ifindex = idev->dev->ifindex,
-               .fc_flags = RTF_UP | RTF_ADDRCONF | RTF_NONEXTHOP,
+               .fc_flags = RTF_UP | RTF_NONEXTHOP,
                .fc_dst = *addr,
                .fc_dst_len = 128,
                .fc_protocol = RTPROT_KERNEL,
                .fc_nlinfo.nl_net = net,
                .fc_ignore_dev_down = true,
        };
+       struct fib6_info *f6i;
 
        if (anycast) {
                cfg.fc_type = RTN_ANYCAST;
@@ -4404,7 +4405,10 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
                cfg.fc_flags |= RTF_LOCAL;
        }
 
-       return ip6_route_info_create(&cfg, gfp_flags, NULL);
+       f6i = ip6_route_info_create(&cfg, gfp_flags, NULL);
+       if (!IS_ERR(f6i))
+               f6i->dst_nocount = true;
+       return f6i;
 }
 
 /* remove deleted ip from prefsrc entries */
@@ -5325,11 +5329,11 @@ static int rt6_fill_node_nexthop(struct sk_buff *skb, struct nexthop *nh,
        if (nexthop_is_multipath(nh)) {
                struct nlattr *mp;
 
-               mp = nla_nest_start(skb, RTA_MULTIPATH);
+               mp = nla_nest_start_noflag(skb, RTA_MULTIPATH);
                if (!mp)
                        goto nla_put_failure;
 
-               if (nexthop_mpath_fill_node(skb, nh))
+               if (nexthop_mpath_fill_node(skb, nh, AF_INET6))
                        goto nla_put_failure;
 
                nla_nest_end(skb, mp);
@@ -5337,7 +5341,7 @@ static int rt6_fill_node_nexthop(struct sk_buff *skb, struct nexthop *nh,
                struct fib6_nh *fib6_nh;
 
                fib6_nh = nexthop_fib6_nh(nh);
-               if (fib_nexthop_info(skb, &fib6_nh->nh_common,
+               if (fib_nexthop_info(skb, &fib6_nh->nh_common, AF_INET6,
                                     flags, false) < 0)
                        goto nla_put_failure;
        }
@@ -5466,13 +5470,14 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
                        goto nla_put_failure;
 
                if (fib_add_nexthop(skb, &rt->fib6_nh->nh_common,
-                                   rt->fib6_nh->fib_nh_weight) < 0)
+                                   rt->fib6_nh->fib_nh_weight, AF_INET6) < 0)
                        goto nla_put_failure;
 
                list_for_each_entry_safe(sibling, next_sibling,
                                         &rt->fib6_siblings, fib6_siblings) {
                        if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common,
-                                           sibling->fib6_nh->fib_nh_weight) < 0)
+                                           sibling->fib6_nh->fib_nh_weight,
+                                           AF_INET6) < 0)
                                goto nla_put_failure;
                }
 
@@ -5489,7 +5494,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
 
                rtm->rtm_flags |= nh_flags;
        } else {
-               if (fib_nexthop_info(skb, &rt->fib6_nh->nh_common,
+               if (fib_nexthop_info(skb, &rt->fib6_nh->nh_common, AF_INET6,
                                     &nh_flags, false) < 0)
                        goto nla_put_failure;
 
index 09e1694b6d341a5f1cf81e49643f9267ac4033c4..ebb62a4ebe30d3bd6347f72711b23655cddc00c5 100644 (file)
@@ -512,7 +512,9 @@ static void iucv_sock_close(struct sock *sk)
                        sk->sk_state = IUCV_DISCONN;
                        sk->sk_state_change(sk);
                }
-       case IUCV_DISCONN:   /* fall through */
+               /* fall through */
+
+       case IUCV_DISCONN:
                sk->sk_state = IUCV_CLOSING;
                sk->sk_state_change(sk);
 
@@ -525,8 +527,9 @@ static void iucv_sock_close(struct sock *sk)
                                        iucv_sock_in_state(sk, IUCV_CLOSED, 0),
                                        timeo);
                }
+               /* fall through */
 
-       case IUCV_CLOSING:   /* fall through */
+       case IUCV_CLOSING:
                sk->sk_state = IUCV_CLOSED;
                sk->sk_state_change(sk);
 
@@ -535,8 +538,9 @@ static void iucv_sock_close(struct sock *sk)
 
                skb_queue_purge(&iucv->send_skb_q);
                skb_queue_purge(&iucv->backlog_skb_q);
+               /* fall through */
 
-       default:   /* fall through */
+       default:
                iucv_sever_path(sk, 1);
        }
 
@@ -2247,10 +2251,10 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
                        kfree_skb(skb);
                        break;
                }
-               /* fall through and receive non-zero length data */
+               /* fall through and receive non-zero length data */
        case (AF_IUCV_FLAG_SHT):
                /* shutdown request */
-               /* fall through and receive zero length data */
+               /* fall through and receive zero length data */
        case 0:
                /* plain data frame */
                IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class;
index 1d0e5904dedf0bd180f2cd56400ac0da2038c0dd..c54cb59593ef8133c74bd30b771eb020573a27e2 100644 (file)
@@ -1681,6 +1681,9 @@ static const struct proto_ops pppol2tp_ops = {
        .recvmsg        = pppol2tp_recvmsg,
        .mmap           = sock_no_mmap,
        .ioctl          = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = pppox_compat_ioctl,
+#endif
 };
 
 static const struct pppox_proto pppol2tp_proto = {
index 76cc9e967fa626e6c3af77941128cb3fbb31659b..4105c97c7ba1f4bbae8bd66c977047992a648a4c 100644 (file)
@@ -936,8 +936,10 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 
        err = ieee80211_set_probe_resp(sdata, params->probe_resp,
                                       params->probe_resp_len, csa);
-       if (err < 0)
+       if (err < 0) {
+               kfree(new);
                return err;
+       }
        if (err == 0)
                changed |= BSS_CHANGED_AP_PROBE_RESP;
 
@@ -949,8 +951,10 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
                                                         params->civicloc,
                                                         params->civicloc_len);
 
-               if (err < 0)
+               if (err < 0) {
+                       kfree(new);
                        return err;
+               }
 
                changed |= BSS_CHANGED_FTM_RESPONDER;
        }
@@ -1525,7 +1529,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        struct sta_info *sta;
        struct ieee80211_sub_if_data *sdata;
        int err;
-       int layer2_update;
 
        if (params->vlan) {
                sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
@@ -1542,6 +1545,11 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (is_multicast_ether_addr(mac))
                return -EINVAL;
 
+       if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER) &&
+           sdata->vif.type == NL80211_IFTYPE_STATION &&
+           !sdata->u.mgd.associated)
+               return -EINVAL;
+
        sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
        if (!sta)
                return -ENOMEM;
@@ -1549,10 +1557,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
                sta->sta.tdls = true;
 
-       if (sta->sta.tdls && sdata->vif.type == NL80211_IFTYPE_STATION &&
-           !sdata->u.mgd.associated)
-               return -EINVAL;
-
        err = sta_apply_parameters(local, sta, params);
        if (err) {
                sta_info_free(local, sta);
@@ -1568,18 +1572,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
            test_sta_flag(sta, WLAN_STA_ASSOC))
                rate_control_rate_init(sta);
 
-       layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
-               sdata->vif.type == NL80211_IFTYPE_AP;
-
        err = sta_info_insert_rcu(sta);
        if (err) {
                rcu_read_unlock();
                return err;
        }
 
-       if (layer2_update)
-               cfg80211_send_layer2_update(sta->sdata->dev, sta->sta.addr);
-
        rcu_read_unlock();
 
        return 0;
@@ -1677,10 +1675,11 @@ static int ieee80211_change_station(struct wiphy *wiphy,
                sta->sdata = vlansdata;
                ieee80211_check_fast_xmit(sta);
 
-               if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+               if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
                        ieee80211_vif_inc_num_mcast(sta->sdata);
-
-               cfg80211_send_layer2_update(sta->sdata->dev, sta->sta.addr);
+                       cfg80211_send_layer2_update(sta->sdata->dev,
+                                                   sta->sta.addr);
+               }
        }
 
        err = sta_apply_parameters(local, sta, params);
index acd4afb4944b875717a5365ac6406f9c6db4dda5..c9a8a2433e8ac51f9c63827887113b357ea23a95 100644 (file)
@@ -187,11 +187,16 @@ int drv_conf_tx(struct ieee80211_local *local,
        if (!check_sdata_in_driver(sdata))
                return -EIO;
 
-       if (WARN_ONCE(params->cw_min == 0 ||
-                     params->cw_min > params->cw_max,
-                     "%s: invalid CW_min/CW_max: %d/%d\n",
-                     sdata->name, params->cw_min, params->cw_max))
+       if (params->cw_min == 0 || params->cw_min > params->cw_max) {
+               /*
+                * If we can't configure hardware anyway, don't warn. We may
+                * never have initialized the CW parameters.
+                */
+               WARN_ONCE(local->ops->conf_tx,
+                         "%s: invalid CW_min/CW_max: %d/%d\n",
+                         sdata->name, params->cw_min, params->cw_max);
                return -EINVAL;
+       }
 
        trace_drv_conf_tx(local, sdata, ac, params);
        if (local->ops->conf_tx)
index 06aac0aaae646cda1f3bca4aab7363922225be58..8dc6580e17871c4f8095079b226d18e1a41d51a5 100644 (file)
@@ -1222,7 +1222,6 @@ static void ieee80211_if_setup(struct net_device *dev)
 static void ieee80211_if_setup_no_queue(struct net_device *dev)
 {
        ieee80211_if_setup(dev);
-       dev->features |= NETIF_F_LLTX;
        dev->priv_flags |= IFF_NO_QUEUE;
 }
 
index a99ad032530946fd8c5d82cfd799ba598284e10d..4c888dc9bd8133eb0025ae919aa98ab002904740 100644 (file)
@@ -2042,6 +2042,16 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local,
                ieee80211_regulatory_limit_wmm_params(sdata, &params[ac], ac);
        }
 
+       /* WMM specification requires all 4 ACIs. */
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               if (params[ac].cw_min == 0) {
+                       sdata_info(sdata,
+                                  "AP has invalid WMM params (missing AC %d), using defaults\n",
+                                  ac);
+                       return false;
+               }
+       }
+
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                mlme_dbg(sdata,
                         "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
index 3c1ab870fefe5b147a82680749ab99275108c367..768d14c9a7161c56c78d11253bb6e152c999ecdb 100644 (file)
@@ -2447,11 +2447,13 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
                      skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) &&
                     sdata->control_port_over_nl80211)) {
                struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-               bool noencrypt = status->flag & RX_FLAG_DECRYPTED;
+               bool noencrypt = !(status->flag & RX_FLAG_DECRYPTED);
 
                cfg80211_rx_control_port(dev, skb, noencrypt);
                dev_kfree_skb(skb);
        } else {
+               memset(skb->cb, 0, sizeof(skb->cb));
+
                /* deliver to local stack */
                if (rx->napi)
                        napi_gro_receive(rx->napi, skb);
@@ -2546,8 +2548,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
 
        if (skb) {
                skb->protocol = eth_type_trans(skb, dev);
-               memset(skb->cb, 0, sizeof(skb->cb));
-
                ieee80211_deliver_skb_to_local_stack(skb, rx);
        }
 
index 95eb8220e2e47def69ad381539330ec1d47bd599..5fb368cc26338dc048212367c6233a6018f5b091 100644 (file)
@@ -1979,6 +1979,10 @@ int sta_info_move_state(struct sta_info *sta,
                        ieee80211_check_fast_xmit(sta);
                        ieee80211_check_fast_rx(sta);
                }
+               if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+                   sta->sdata->vif.type == NL80211_IFTYPE_AP)
+                       cfg80211_send_layer2_update(sta->sdata->dev,
+                                                   sta->sta.addr);
                break;
        default:
                break;
index 1b224fa27367fbf4ce7cc7385eb27f8051081704..ad1e58184c4e4581dd111c506f0fe19a72aa6810 100644 (file)
@@ -3796,9 +3796,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
        }
 
        /* Always allow software iftypes */
-       if (local->hw.wiphy->software_iftypes & BIT(iftype) ||
-           (iftype == NL80211_IFTYPE_AP_VLAN &&
-            local->hw.wiphy->flags & WIPHY_FLAG_4ADDR_AP)) {
+       if (cfg80211_iftype_allowed(local->hw.wiphy, iftype, 0, 1)) {
                if (radar_detect)
                        return -EINVAL;
                return 0;
@@ -3833,7 +3831,8 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
 
                if (sdata_iter == sdata ||
                    !ieee80211_sdata_running(sdata_iter) ||
-                   local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
+                   cfg80211_iftype_allowed(local->hw.wiphy,
+                                           wdev_iter->iftype, 0, 1))
                        continue;
 
                params.iftype_num[wdev_iter->iftype]++;
index d25e91d7bdc18526301c6228f5943aec7f9becc8..44b675016393a450e7ec7c73e2dfb514ade4e5f9 100644 (file)
@@ -133,12 +133,12 @@ static int mpls_xmit(struct sk_buff *skb)
        mpls_stats_inc_outucastpkts(out_dev, skb);
 
        if (rt) {
-               if (rt->rt_gw_family == AF_INET)
-                       err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4,
-                                        skb);
-               else if (rt->rt_gw_family == AF_INET6)
+               if (rt->rt_gw_family == AF_INET6)
                        err = neigh_xmit(NEIGH_ND_TABLE, out_dev, &rt->rt_gw6,
                                         skb);
+               else
+                       err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4,
+                                        skb);
        } else if (rt6) {
                if (ipv6_addr_v4mapped(&rt6->rt6i_gateway)) {
                        /* 6PE (RFC 4798) */
index 5c3fad8cba575376df16ff60609e054b0b041255..0187e65176c05c1ac93a18d77a12323e6a692576 100644 (file)
@@ -54,7 +54,7 @@ static void ncsi_cmd_build_header(struct ncsi_pkt_hdr *h,
        checksum = ncsi_calculate_checksum((unsigned char *)h,
                                           sizeof(*h) + nca->payload);
        pchecksum = (__be32 *)((void *)h + sizeof(struct ncsi_pkt_hdr) +
-                   nca->payload);
+                   ALIGN(nca->payload, 4));
        *pchecksum = htonl(checksum);
 }
 
@@ -309,14 +309,21 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca)
 
 int ncsi_xmit_cmd(struct ncsi_cmd_arg *nca)
 {
+       struct ncsi_cmd_handler *nch = NULL;
        struct ncsi_request *nr;
+       unsigned char type;
        struct ethhdr *eh;
-       struct ncsi_cmd_handler *nch = NULL;
        int i, ret;
 
+       /* Use OEM generic handler for Netlink request */
+       if (nca->req_flags == NCSI_REQ_FLAG_NETLINK_DRIVEN)
+               type = NCSI_PKT_CMD_OEM;
+       else
+               type = nca->type;
+
        /* Search for the handler */
        for (i = 0; i < ARRAY_SIZE(ncsi_cmd_handlers); i++) {
-               if (ncsi_cmd_handlers[i].type == nca->type) {
+               if (ncsi_cmd_handlers[i].type == type) {
                        if (ncsi_cmd_handlers[i].handler)
                                nch = &ncsi_cmd_handlers[i];
                        else
index 7581bf9198858864fb4854a5e5c8a845e8093387..d876bd55f356159aa8862d8369d056151dd668e6 100644 (file)
@@ -47,7 +47,8 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
        if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED ||
            ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR) {
                netdev_dbg(nr->ndp->ndev.dev,
-                          "NCSI: non zero response/reason code\n");
+                          "NCSI: non zero response/reason code %04xh, %04xh\n",
+                           ntohs(h->code), ntohs(h->reason));
                return -EPERM;
        }
 
@@ -55,7 +56,7 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
         * sender doesn't support checksum according to NCSI
         * specification.
         */
-       pchecksum = (__be32 *)((void *)(h + 1) + payload - 4);
+       pchecksum = (__be32 *)((void *)(h + 1) + ALIGN(payload, 4) - 4);
        if (ntohl(*pchecksum) == 0)
                return 0;
 
@@ -63,7 +64,9 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
                                           sizeof(*h) + payload - 4);
 
        if (*pchecksum != htonl(checksum)) {
-               netdev_dbg(nr->ndp->ndev.dev, "NCSI: checksum mismatched\n");
+               netdev_dbg(nr->ndp->ndev.dev,
+                          "NCSI: checksum mismatched; recd: %08x calc: %08x\n",
+                          *pchecksum, htonl(checksum));
                return -EINVAL;
        }
 
index 32a45c03786e9d210fd381c6ee65d0ef298ddf76..0d65f4d394943ca6c9857d45b353b06a379f84e1 100644 (file)
@@ -223,8 +223,6 @@ config NF_CONNTRACK_FTP
          of Network Address Translation on them.
 
          This is FTP support on Layer 3 independent connection tracking.
-         Layer 3 independent connection tracking is experimental scheme
-         which generalize ip_conntrack to support other layer 3 protocols.
 
          To compile it as a module, choose M here.  If unsure, say N.
 
@@ -338,7 +336,7 @@ config NF_CONNTRACK_SIP
        help
          SIP is an application-layer control protocol that can establish,
          modify, and terminate multimedia sessions (conferences) such as
-         Internet telephony calls. With the ip_conntrack_sip and
+         Internet telephony calls. With the nf_conntrack_sip and
          the nf_nat_sip modules you can support the protocol on a connection
          tracking/NATing firewall.
 
@@ -1313,7 +1311,7 @@ config NETFILTER_XT_MATCH_HELPER
        depends on NETFILTER_ADVANCED
        help
          Helper matching allows you to match packets in dynamic connections
-         tracked by a conntrack-helper, ie. ip_conntrack_ftp
+         tracked by a conntrack-helper, ie. nf_conntrack_ftp
 
          To compile it as a module, choose M here.  If unsure, say Y.
 
index ca7ac4a25ada2f1527175f03d204d90bedfea7ba..1d4e63326e68c1fe68d2e8542c8bbb4b29b2d859 100644 (file)
@@ -226,7 +226,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
 
        e.id = ip_to_id(map, ip);
 
-       if (opt->flags & IPSET_DIM_ONE_SRC)
+       if (opt->flags & IPSET_DIM_TWO_SRC)
                ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
        else
                ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
index 2e151856ad9992f1ec338f8fd6bed53b98c30be4..e64d5f9a89dd331e48ddf38af1c9978d2507a958 100644 (file)
@@ -1161,7 +1161,7 @@ static int ip_set_rename(struct net *net, struct sock *ctnl,
                return -ENOENT;
 
        write_lock_bh(&ip_set_ref_lock);
-       if (set->ref != 0) {
+       if (set->ref != 0 || set->ref_netlink != 0) {
                ret = -IPSET_ERR_REFERENCED;
                goto out;
        }
index faf59b6a998fecf50c191321d5605d5c5b460dc4..24d8f4df4230ca573098fbcdc83baadfd855e094 100644 (file)
@@ -89,15 +89,11 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb,
        struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 
-        /* MAC can be src only */
-       if (!(opt->flags & IPSET_DIM_TWO_SRC))
-               return 0;
-
        if (skb_mac_header(skb) < skb->head ||
            (skb_mac_header(skb) + ETH_HLEN) > skb->data)
                return -EINVAL;
 
-       if (opt->flags & IPSET_DIM_ONE_SRC)
+       if (opt->flags & IPSET_DIM_TWO_SRC)
                ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
        else
                ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
index 403541996952f0d2ae039559a551a2e0f2107455..08adcb22298622be0dadfc056d86b3b1a378aaf5 100644 (file)
@@ -231,7 +231,7 @@ void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
 
        IP_VS_DBG_BUF(7, "%s: ct=%p, expect tuple=" FMT_TUPLE "\n",
                      __func__, ct, ARG_TUPLE(&exp->tuple));
-       nf_ct_expect_related(exp);
+       nf_ct_expect_related(exp, 0);
        nf_ct_expect_put(exp);
 }
 EXPORT_SYMBOL(ip_vs_nfct_expect_related);
index 42ee659d0d1ebcde7bba4bbe21c73d1c94e1fd23..d011d2eb08486f7e7b5507358f528f0490e0ea90 100644 (file)
@@ -159,7 +159,7 @@ static int amanda_help(struct sk_buff *skb,
                if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
                        ret = nf_nat_amanda(skb, ctinfo, protoff,
                                            off - dataoff, len, exp);
-               else if (nf_ct_expect_related(exp) != 0) {
+               else if (nf_ct_expect_related(exp, 0) != 0) {
                        nf_ct_helper_log(skb, ct, "cannot add expectation");
                        ret = NF_DROP;
                }
index 921a7b95be6821df2ce44c09fa489964fa7bab86..1ba6becc30795a0080a39b9149849af1905f02ae 100644 (file)
@@ -68,7 +68,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
        exp->class                = NF_CT_EXPECT_CLASS_DEFAULT;
        exp->helper               = NULL;
 
-       nf_ct_expect_related(exp);
+       nf_ct_expect_related(exp, 0);
        nf_ct_expect_put(exp);
 
        nf_ct_refresh(ct, skb, timeout * HZ);
index bdfeacee081771023bb734dc465915a74f062a01..81a8ef42b88d3893a210bea4f03b6eb4cbf04f99 100644 (file)
@@ -453,13 +453,12 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
  * table location, we assume id gets exposed to userspace.
  *
  * Following nf_conn items do not change throughout lifetime
- * of the nf_conn after it has been committed to main hash table:
+ * of the nf_conn:
  *
  * 1. nf_conn address
- * 2. nf_conn->ext address
- * 3. nf_conn->master address (normally NULL)
- * 4. tuple
- * 5. the associated net namespace
+ * 2. nf_conn->master address (normally NULL)
+ * 3. the associated net namespace
+ * 4. the original direction tuple
  */
 u32 nf_ct_get_id(const struct nf_conn *ct)
 {
@@ -469,9 +468,10 @@ u32 nf_ct_get_id(const struct nf_conn *ct)
        net_get_random_once(&ct_id_seed, sizeof(ct_id_seed));
 
        a = (unsigned long)ct;
-       b = (unsigned long)ct->master ^ net_hash_mix(nf_ct_net(ct));
-       c = (unsigned long)ct->ext;
-       d = (unsigned long)siphash(&ct->tuplehash, sizeof(ct->tuplehash),
+       b = (unsigned long)ct->master;
+       c = (unsigned long)nf_ct_net(ct);
+       d = (unsigned long)siphash(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+                                  sizeof(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple),
                                   &ct_id_seed);
 #ifdef CONFIG_64BIT
        return siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &ct_id_seed);
@@ -1817,9 +1817,7 @@ EXPORT_SYMBOL_GPL(nf_ct_kill_acct);
 #include <linux/netfilter/nfnetlink_conntrack.h>
 #include <linux/mutex.h>
 
-/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be
- * in ip_conntrack_core, since we don't want the protocols to autoload
- * or depend on ctnetlink */
+/* Generic function for tcp/udp/sctp/dccp and alike. */
 int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
                               const struct nf_conntrack_tuple *tuple)
 {
index ffd1f4906c4f7eecb0b97481e540650cee2bd3e7..65364de915d16ef60b6eb8e1b6be575cc2f0abaf 100644 (file)
@@ -249,13 +249,22 @@ static inline int expect_clash(const struct nf_conntrack_expect *a,
 static inline int expect_matches(const struct nf_conntrack_expect *a,
                                 const struct nf_conntrack_expect *b)
 {
-       return a->master == b->master &&
-              nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
+       return nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
               nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
               net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) &&
               nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master));
 }
 
+static bool master_matches(const struct nf_conntrack_expect *a,
+                          const struct nf_conntrack_expect *b,
+                          unsigned int flags)
+{
+       if (flags & NF_CT_EXP_F_SKIP_MASTER)
+               return true;
+
+       return a->master == b->master;
+}
+
 /* Generally a bad idea to call this: could have matched already. */
 void nf_ct_unexpect_related(struct nf_conntrack_expect *exp)
 {
@@ -399,7 +408,8 @@ static void evict_oldest_expect(struct nf_conn *master,
                nf_ct_remove_expect(last);
 }
 
-static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
+static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
+                                      unsigned int flags)
 {
        const struct nf_conntrack_expect_policy *p;
        struct nf_conntrack_expect *i;
@@ -417,8 +427,10 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
        }
        h = nf_ct_expect_dst_hash(net, &expect->tuple);
        hlist_for_each_entry_safe(i, next, &nf_ct_expect_hash[h], hnode) {
-               if (expect_matches(i, expect)) {
-                       if (i->class != expect->class)
+               if (master_matches(i, expect, flags) &&
+                   expect_matches(i, expect)) {
+                       if (i->class != expect->class ||
+                           i->master != expect->master)
                                return -EALREADY;
 
                        if (nf_ct_remove_expect(i))
@@ -453,12 +465,12 @@ out:
 }
 
 int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
-                               u32 portid, int report)
+                               u32 portid, int report, unsigned int flags)
 {
        int ret;
 
        spin_lock_bh(&nf_conntrack_expect_lock);
-       ret = __nf_ct_expect_check(expect);
+       ret = __nf_ct_expect_check(expect, flags);
        if (ret < 0)
                goto out;
 
index 8c6c11bab5b6726384fa0a2ebd9396fed88e9aad..8d96738b7dfd6bb0527cdb20e50fb2658a25ff8a 100644 (file)
@@ -322,7 +322,7 @@ static int find_pattern(const char *data, size_t dlen,
                i++;
        }
 
-       pr_debug("Skipped up to `%c'!\n", skip);
+       pr_debug("Skipped up to 0x%hhx delimiter!\n", skip);
 
        *numoff = i;
        *numlen = getnum(data + i, dlen - i, cmd, term, numoff);
@@ -525,7 +525,7 @@ skip_nl_seq:
                                 protoff, matchoff, matchlen, exp);
        else {
                /* Can't expect this?  Best to drop packet now. */
-               if (nf_ct_expect_related(exp) != 0) {
+               if (nf_ct_expect_related(exp, 0) != 0) {
                        nf_ct_helper_log(skb, ct, "cannot add expectation");
                        ret = NF_DROP;
                } else
index 8f6ba8162f0be541442296145d9f706c9299a48a..573cb44814813985c61afbedf582a618312e8e1a 100644 (file)
@@ -1,11 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
- *                                  conntrack/NAT module.
+ * BER and PER decoding library for H.323 conntrack/NAT module.
  *
  * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
- * See ip_conntrack_helper_h323_asn1.h for details.
+ * See nf_conntrack_helper_h323_asn1.h for details.
  */
 
 #ifdef __KERNEL__
index 6497e5fc087101b4dc7664616f113e0c4857ce70..8ba037b76ad3af51e953cb5c501749778f070336 100644 (file)
@@ -305,8 +305,8 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
                ret = nat_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
                                   taddr, port, rtp_port, rtp_exp, rtcp_exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(rtp_exp) == 0) {
-                       if (nf_ct_expect_related(rtcp_exp) == 0) {
+               if (nf_ct_expect_related(rtp_exp, 0) == 0) {
+                       if (nf_ct_expect_related(rtcp_exp, 0) == 0) {
                                pr_debug("nf_ct_h323: expect RTP ");
                                nf_ct_dump_tuple(&rtp_exp->tuple);
                                pr_debug("nf_ct_h323: expect RTCP ");
@@ -364,7 +364,7 @@ static int expect_t120(struct sk_buff *skb,
                ret = nat_t120(skb, ct, ctinfo, protoff, data, dataoff, taddr,
                               port, exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(exp) == 0) {
+               if (nf_ct_expect_related(exp, 0) == 0) {
                        pr_debug("nf_ct_h323: expect T.120 ");
                        nf_ct_dump_tuple(&exp->tuple);
                } else
@@ -701,7 +701,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
                ret = nat_h245(skb, ct, ctinfo, protoff, data, dataoff, taddr,
                               port, exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(exp) == 0) {
+               if (nf_ct_expect_related(exp, 0) == 0) {
                        pr_debug("nf_ct_q931: expect H.245 ");
                        nf_ct_dump_tuple(&exp->tuple);
                } else
@@ -825,7 +825,7 @@ static int expect_callforwarding(struct sk_buff *skb,
                                         protoff, data, dataoff,
                                         taddr, port, exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(exp) == 0) {
+               if (nf_ct_expect_related(exp, 0) == 0) {
                        pr_debug("nf_ct_q931: expect Call Forwarding ");
                        nf_ct_dump_tuple(&exp->tuple);
                } else
@@ -1284,7 +1284,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
                ret = nat_q931(skb, ct, ctinfo, protoff, data,
                               taddr, i, port, exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(exp) == 0) {
+               if (nf_ct_expect_related(exp, 0) == 0) {
                        pr_debug("nf_ct_ras: expect Q.931 ");
                        nf_ct_dump_tuple(&exp->tuple);
 
@@ -1349,7 +1349,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
                          IPPROTO_UDP, NULL, &port);
        exp->helper = nf_conntrack_helper_ras;
 
-       if (nf_ct_expect_related(exp) == 0) {
+       if (nf_ct_expect_related(exp, 0) == 0) {
                pr_debug("nf_ct_ras: expect RAS ");
                nf_ct_dump_tuple(&exp->tuple);
        } else
@@ -1561,7 +1561,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
        exp->flags = NF_CT_EXPECT_PERMANENT;
        exp->helper = nf_conntrack_helper_q931;
 
-       if (nf_ct_expect_related(exp) == 0) {
+       if (nf_ct_expect_related(exp, 0) == 0) {
                pr_debug("nf_ct_ras: expect Q.931 ");
                nf_ct_dump_tuple(&exp->tuple);
        } else
@@ -1615,7 +1615,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
        exp->flags = NF_CT_EXPECT_PERMANENT;
        exp->helper = nf_conntrack_helper_q931;
 
-       if (nf_ct_expect_related(exp) == 0) {
+       if (nf_ct_expect_related(exp, 0) == 0) {
                pr_debug("nf_ct_ras: expect Q.931 ");
                nf_ct_dump_tuple(&exp->tuple);
        } else
index 7ac156f1f3bc7958e12a6f99d1df45e3102715e3..e40988a2f22fbaad4cf14256ec5be0c6d4da2052 100644 (file)
@@ -213,7 +213,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
                                                 addr_beg_p - ib_ptr,
                                                 addr_end_p - addr_beg_p,
                                                 exp);
-                       else if (nf_ct_expect_related(exp) != 0) {
+                       else if (nf_ct_expect_related(exp, 0) != 0) {
                                nf_ct_helper_log(skb, ct,
                                                 "cannot add expectation");
                                ret = NF_DROP;
index 1b77444d5b52971c13c7568a8b4f1d4e543d4acd..e2d13cd1887562c80361042c7fe72ad50b8034d5 100644 (file)
@@ -553,10 +553,8 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
                goto nla_put_failure;
 
        if (ctnetlink_dump_status(skb, ct) < 0 ||
-           ctnetlink_dump_timeout(skb, ct) < 0 ||
            ctnetlink_dump_acct(skb, ct, type) < 0 ||
            ctnetlink_dump_timestamp(skb, ct) < 0 ||
-           ctnetlink_dump_protoinfo(skb, ct) < 0 ||
            ctnetlink_dump_helpinfo(skb, ct) < 0 ||
            ctnetlink_dump_mark(skb, ct) < 0 ||
            ctnetlink_dump_secctx(skb, ct) < 0 ||
@@ -568,6 +566,11 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
            ctnetlink_dump_ct_synproxy(skb, ct) < 0)
                goto nla_put_failure;
 
+       if (!test_bit(IPS_OFFLOAD_BIT, &ct->status) &&
+           (ctnetlink_dump_timeout(skb, ct) < 0 ||
+            ctnetlink_dump_protoinfo(skb, ct) < 0))
+               goto nla_put_failure;
+
        nlmsg_end(skb, nlh);
        return skb->len;
 
@@ -2616,7 +2619,7 @@ ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
        if (IS_ERR(exp))
                return PTR_ERR(exp);
 
-       err = nf_ct_expect_related_report(exp, portid, report);
+       err = nf_ct_expect_related_report(exp, portid, report, 0);
        nf_ct_expect_put(exp);
        return err;
 }
@@ -3367,7 +3370,7 @@ ctnetlink_create_expect(struct net *net,
                goto err_rcu;
        }
 
-       err = nf_ct_expect_related_report(exp, portid, report);
+       err = nf_ct_expect_related_report(exp, portid, report, 0);
        nf_ct_expect_put(exp);
 err_rcu:
        rcu_read_unlock();
index b22042ad0fca6cc9503a8bd421d455fa5791a658..a971183f11af77ac1533de77a7778adab37d4758 100644 (file)
@@ -234,9 +234,9 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
        nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre);
        if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK)
                nf_nat_pptp_exp_gre(exp_orig, exp_reply);
-       if (nf_ct_expect_related(exp_orig) != 0)
+       if (nf_ct_expect_related(exp_orig, 0) != 0)
                goto out_put_both;
-       if (nf_ct_expect_related(exp_reply) != 0)
+       if (nf_ct_expect_related(exp_reply, 0) != 0)
                goto out_unexpect_orig;
 
        /* Add GRE keymap entries */
index c2eb365f1723751a13e5799ea0db6c5264000db3..5b05487a60d21cc019d0e9709e0aff9b67bf586a 100644 (file)
@@ -1,7 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * ip_conntrack_proto_gre.c - Version 3.0
- *
  * Connection tracking protocol helper module for GRE.
  *
  * GRE is a generic encapsulation protocol, which is generally not very
index dd53e2b20f6b67aed3552159a0aab40abcb6fa8e..097deba7441ae672dba32a55dd6ee035cb0bab53 100644 (file)
@@ -215,7 +215,7 @@ int nf_conntrack_icmpv4_error(struct nf_conn *tmpl,
                return -NF_ACCEPT;
        }
 
-       /* See ip_conntrack_proto_tcp.c */
+       /* See nf_conntrack_proto_tcp.c */
        if (state->net->ct.sysctl_checksum &&
            state->hook == NF_INET_PRE_ROUTING &&
            nf_ip_checksum(skb, state->hook, dataoff, IPPROTO_ICMP)) {
index d5fdfa00d683098d53d14a1932ef6d8224283d32..85c1f8c213b0f8238141a94484144f74f9a0fd0a 100644 (file)
@@ -472,6 +472,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
        struct ip_ct_tcp_state *receiver = &state->seen[!dir];
        const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
        __u32 seq, ack, sack, end, win, swin;
+       u16 win_raw;
        s32 receiver_offset;
        bool res, in_recv_win;
 
@@ -480,7 +481,8 @@ static bool tcp_in_window(const struct nf_conn *ct,
         */
        seq = ntohl(tcph->seq);
        ack = sack = ntohl(tcph->ack_seq);
-       win = ntohs(tcph->window);
+       win_raw = ntohs(tcph->window);
+       win = win_raw;
        end = segment_seq_plus_len(seq, skb->len, dataoff, tcph);
 
        if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
@@ -655,14 +657,14 @@ static bool tcp_in_window(const struct nf_conn *ct,
                            && state->last_seq == seq
                            && state->last_ack == ack
                            && state->last_end == end
-                           && state->last_win == win)
+                           && state->last_win == win_raw)
                                state->retrans++;
                        else {
                                state->last_dir = dir;
                                state->last_seq = seq;
                                state->last_ack = ack;
                                state->last_end = end;
-                               state->last_win = win;
+                               state->last_win = win_raw;
                                state->retrans = 0;
                        }
                }
index 81448c3db66145c46ad2dcf75fa82cce53c845f7..1aebd6569d4efbeb0bd6763defcde1dec829b165 100644 (file)
@@ -153,7 +153,7 @@ static int help(struct sk_buff *skb,
        nf_ct_dump_tuple(&exp->tuple);
 
        /* Can't expect this?  Best to drop packet now. */
-       if (nf_ct_expect_related(exp) != 0) {
+       if (nf_ct_expect_related(exp, 0) != 0) {
                nf_ct_helper_log(skb, ct, "cannot add expectation");
                ret = NF_DROP;
        }
index 107251731809114f9dd0cf3121a9c99005c76ce9..b83dc9bf0a5dd00c5cf48f66da86593c718e7b89 100644 (file)
@@ -977,11 +977,15 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,
                /* -EALREADY handling works around end-points that send
                 * SDP messages with identical port but different media type,
                 * we pretend expectation was set up.
+                * It also works in the case that SDP messages are sent with
+                * identical expect tuples but for different master conntracks.
                 */
-               int errp = nf_ct_expect_related(rtp_exp);
+               int errp = nf_ct_expect_related(rtp_exp,
+                                               NF_CT_EXP_F_SKIP_MASTER);
 
                if (errp == 0 || errp == -EALREADY) {
-                       int errcp = nf_ct_expect_related(rtcp_exp);
+                       int errcp = nf_ct_expect_related(rtcp_exp,
+                                               NF_CT_EXP_F_SKIP_MASTER);
 
                        if (errcp == 0 || errcp == -EALREADY)
                                ret = NF_ACCEPT;
@@ -1296,7 +1300,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
                ret = hooks->expect(skb, protoff, dataoff, dptr, datalen,
                                    exp, matchoff, matchlen);
        else {
-               if (nf_ct_expect_related(exp) != 0) {
+               if (nf_ct_expect_related(exp, 0) != 0) {
                        nf_ct_helper_log(skb, ct, "cannot add expectation");
                        ret = NF_DROP;
                } else
index e0d392cb3075ab8ee82f69f6fd03f002f9901316..0006503d2da9793ff858cfe3d7218f9709f11c45 100644 (file)
@@ -1037,8 +1037,13 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
        table[NF_SYSCTL_CT_COUNT].data = &net->ct.count;
        table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum;
        table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid;
+       table[NF_SYSCTL_CT_ACCT].data = &net->ct.sysctl_acct;
+       table[NF_SYSCTL_CT_HELPER].data = &net->ct.sysctl_auto_assign_helper;
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
        table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events;
+#endif
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+       table[NF_SYSCTL_CT_TIMESTAMP].data = &net->ct.sysctl_tstamp;
 #endif
        table[NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC].data = &nf_generic_pernet(net)->timeout;
        table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP].data = &nf_icmp_pernet(net)->timeout;
index df6d6d61bd58edf6149bac99e12689831b6e8d04..80ee53f29f68f350d1ff1383161b2dc84f1614cd 100644 (file)
@@ -78,7 +78,7 @@ static int tftp_help(struct sk_buff *skb,
                nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
                if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
                        ret = nf_nat_tftp(skb, ctinfo, exp);
-               else if (nf_ct_expect_related(exp) != 0) {
+               else if (nf_ct_expect_related(exp, 0) != 0) {
                        nf_ct_helper_log(skb, ct, "cannot add expectation");
                        ret = NF_DROP;
                }
index e3d797252a981cdc7e3362be0e157c6db1d429a1..a0b4bf654de2d75765bc27b4ea61c130f32a14a1 100644 (file)
@@ -111,15 +111,16 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
 #define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT        (120 * HZ)
 #define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT        (30 * HZ)
 
-static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
+{
+       return (__s32)(timeout - (u32)jiffies);
+}
+
+static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
 {
        const struct nf_conntrack_l4proto *l4proto;
+       int l4num = nf_ct_protonum(ct);
        unsigned int timeout;
-       int l4num;
-
-       l4num = nf_ct_protonum(ct);
-       if (l4num == IPPROTO_TCP)
-               flow_offload_fixup_tcp(&ct->proto.tcp);
 
        l4proto = nf_ct_l4proto_find(l4num);
        if (!l4proto)
@@ -132,7 +133,20 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct)
        else
                return;
 
-       ct->timeout = nfct_time_stamp + timeout;
+       if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
+               ct->timeout = nfct_time_stamp + timeout;
+}
+
+static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+{
+       if (nf_ct_protonum(ct) == IPPROTO_TCP)
+               flow_offload_fixup_tcp(&ct->proto.tcp);
+}
+
+static void flow_offload_fixup_ct(struct nf_conn *ct)
+{
+       flow_offload_fixup_ct_state(ct);
+       flow_offload_fixup_ct_timeout(ct);
 }
 
 void flow_offload_free(struct flow_offload *flow)
@@ -203,11 +217,16 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
                return err;
        }
 
-       flow->timeout = (u32)jiffies;
+       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
        return 0;
 }
 EXPORT_SYMBOL_GPL(flow_offload_add);
 
+static inline bool nf_flow_has_expired(const struct flow_offload *flow)
+{
+       return nf_flow_timeout_delta(flow->timeout) <= 0;
+}
+
 static void flow_offload_del(struct nf_flowtable *flow_table,
                             struct flow_offload *flow)
 {
@@ -223,6 +242,11 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
        e = container_of(flow, struct flow_offload_entry, flow);
        clear_bit(IPS_OFFLOAD_BIT, &e->ct->status);
 
+       if (nf_flow_has_expired(flow))
+               flow_offload_fixup_ct(e->ct);
+       else if (flow->flags & FLOW_OFFLOAD_TEARDOWN)
+               flow_offload_fixup_ct_timeout(e->ct);
+
        flow_offload_free(flow);
 }
 
@@ -298,11 +322,6 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table,
        return err;
 }
 
-static inline bool nf_flow_has_expired(const struct flow_offload *flow)
-{
-       return (__s32)(flow->timeout - (u32)jiffies) <= 0;
-}
-
 static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
 {
        struct nf_flowtable *flow_table = data;
index cdfc33517e85b5e0542195b019898bbe8efbcfa8..b9e7dd6e60ce2b1327709fb38a0eab5e7e2d1af6 100644 (file)
@@ -214,6 +214,24 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
        return true;
 }
 
+static int nf_flow_offload_dst_check(struct dst_entry *dst)
+{
+       if (unlikely(dst_xfrm(dst)))
+               return dst_check(dst, 0) ? 0 : -1;
+
+       return 0;
+}
+
+static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+                                     const struct nf_hook_state *state,
+                                     struct dst_entry *dst)
+{
+       skb_orphan(skb);
+       skb_dst_set_noref(skb, dst);
+       dst_output(state->net, state->sk, skb);
+       return NF_STOLEN;
+}
+
 unsigned int
 nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
                        const struct nf_hook_state *state)
@@ -254,12 +272,25 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
        if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff))
                return NF_ACCEPT;
 
+       if (nf_flow_offload_dst_check(&rt->dst)) {
+               flow_offload_teardown(flow);
+               return NF_ACCEPT;
+       }
+
        if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
                return NF_DROP;
 
        flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
        iph = ip_hdr(skb);
        ip_decrease_ttl(iph);
+       skb->tstamp = 0;
+
+       if (unlikely(dst_xfrm(&rt->dst))) {
+               memset(skb->cb, 0, sizeof(struct inet_skb_parm));
+               IPCB(skb)->iif = skb->dev->ifindex;
+               IPCB(skb)->flags = IPSKB_FORWARDED;
+               return nf_flow_xmit_xfrm(skb, state, &rt->dst);
+       }
 
        skb->dev = outdev;
        nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
@@ -467,6 +498,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
                                sizeof(*ip6h)))
                return NF_ACCEPT;
 
+       if (nf_flow_offload_dst_check(&rt->dst)) {
+               flow_offload_teardown(flow);
+               return NF_ACCEPT;
+       }
+
        if (skb_try_make_writable(skb, sizeof(*ip6h)))
                return NF_DROP;
 
@@ -476,6 +512,14 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
        flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
        ip6h = ipv6_hdr(skb);
        ip6h->hop_limit--;
+       skb->tstamp = 0;
+
+       if (unlikely(dst_xfrm(&rt->dst))) {
+               memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
+               IP6CB(skb)->iif = skb->dev->ifindex;
+               IP6CB(skb)->flags = IP6SKB_FORWARDED;
+               return nf_flow_xmit_xfrm(skb, state, &rt->dst);
+       }
 
        skb->dev = outdev;
        nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
index a352604d6186a93359d9487db434d4350c56e8cb..3bc7e0854efe4d0265f9e442bca10a140c65ab2a 100644 (file)
@@ -48,7 +48,7 @@ static unsigned int help(struct sk_buff *skb,
                int res;
 
                exp->tuple.dst.u.tcp.port = htons(port);
-               res = nf_ct_expect_related(exp);
+               res = nf_ct_expect_related(exp, 0);
                if (res == 0)
                        break;
                else if (res != -EBUSY) {
index 9ab410455992ff999344d79b3cef7f2a61dbff07..3f6023ed496664b0b2e2275c065c80ac46176171 100644 (file)
@@ -519,7 +519,7 @@ another_round:
  * and NF_INET_LOCAL_OUT, we change the destination to map into the
  * range. It might not be possible to get a unique tuple, but we try.
  * At worst (or if we race), we will end up with a final duplicate in
- * __ip_conntrack_confirm and drop the packet. */
+ * __nf_conntrack_confirm and drop the packet. */
 static void
 get_unique_tuple(struct nf_conntrack_tuple *tuple,
                 const struct nf_conntrack_tuple *orig_tuple,
index d48484a9d52dc438c7a30fe745eaf64d56e96efc..aace6768a64e716611f1c83925941d8ea20a9abf 100644 (file)
@@ -91,7 +91,7 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
index dfb7ef8845bdfcbe9898815ba55fabed5fe402b8..c691ab8d234cf153e96081b6281ed86639e35021 100644 (file)
@@ -53,7 +53,7 @@ static unsigned int help(struct sk_buff *skb,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
index e338d91980d894cfd85899054bf4fb05916b9684..f0a735e868518f80ddcaf852432c96186053f961 100644 (file)
@@ -414,7 +414,7 @@ static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
                int ret;
 
                exp->tuple.dst.u.udp.port = htons(port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, NF_CT_EXP_F_SKIP_MASTER);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
@@ -607,7 +607,8 @@ static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
                int ret;
 
                rtp_exp->tuple.dst.u.udp.port = htons(port);
-               ret = nf_ct_expect_related(rtp_exp);
+               ret = nf_ct_expect_related(rtp_exp,
+                                          NF_CT_EXP_F_SKIP_MASTER);
                if (ret == -EBUSY)
                        continue;
                else if (ret < 0) {
@@ -615,7 +616,8 @@ static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
                        break;
                }
                rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
-               ret = nf_ct_expect_related(rtcp_exp);
+               ret = nf_ct_expect_related(rtcp_exp,
+                                          NF_CT_EXP_F_SKIP_MASTER);
                if (ret == 0)
                        break;
                else if (ret == -EBUSY) {
index 833a11f68031334207e5560faa1fc02b74bf9921..1a591132d6eb937902d578526fc4b08692c8178a 100644 (file)
@@ -30,7 +30,7 @@ static unsigned int help(struct sk_buff *skb,
                = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
        exp->dir = IP_CT_DIR_REPLY;
        exp->expectfn = nf_nat_follow_master;
-       if (nf_ct_expect_related(exp) != 0) {
+       if (nf_ct_expect_related(exp, 0) != 0) {
                nf_ct_helper_log(skb, exp->master, "cannot add expectation");
                return NF_DROP;
        }
index b101f187eda8a3825437b4f383366eb460fe1841..c769462a839e068bb7fea42f248d40bf0d5505fb 100644 (file)
@@ -470,7 +470,7 @@ synproxy_send_client_synack(struct net *net,
        struct iphdr *iph, *niph;
        struct tcphdr *nth;
        unsigned int tcp_hdr_size;
-       u16 mss = opts->mss;
+       u16 mss = opts->mss_encode;
 
        iph = ip_hdr(skb);
 
@@ -687,7 +687,7 @@ ipv4_synproxy_hook(void *priv, struct sk_buff *skb,
        state = &ct->proto.tcp;
        switch (state->state) {
        case TCP_CONNTRACK_CLOSE:
-               if (th->rst && !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
+               if (th->rst && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
                        nf_ct_seqadj_init(ct, ctinfo, synproxy->isn -
                                                      ntohl(th->seq) + 1);
                        break;
@@ -884,7 +884,7 @@ synproxy_send_client_synack_ipv6(struct net *net,
        struct ipv6hdr *iph, *niph;
        struct tcphdr *nth;
        unsigned int tcp_hdr_size;
-       u16 mss = opts->mss;
+       u16 mss = opts->mss_encode;
 
        iph = ipv6_hdr(skb);
 
@@ -1111,7 +1111,7 @@ ipv6_synproxy_hook(void *priv, struct sk_buff *skb,
        state = &ct->proto.tcp;
        switch (state->state) {
        case TCP_CONNTRACK_CLOSE:
-               if (th->rst && !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
+               if (th->rst && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
                        nf_ct_seqadj_init(ct, ctinfo, synproxy->isn -
                                                      ntohl(th->seq) + 1);
                        break;
index ed17a7c29b86f50578eae91827394d624c63c3cb..d47469f824a10a8628c165cedef587a49528c725 100644 (file)
@@ -138,9 +138,14 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
                return;
 
        list_for_each_entry_reverse(trans, &net->nft.commit_list, list) {
-               if (trans->msg_type == NFT_MSG_NEWSET &&
-                   nft_trans_set(trans) == set) {
-                       set->bound = true;
+               switch (trans->msg_type) {
+               case NFT_MSG_NEWSET:
+                       if (nft_trans_set(trans) == set)
+                               nft_trans_set_bound(trans) = true;
+                       break;
+               case NFT_MSG_NEWSETELEM:
+                       if (nft_trans_elem_set(trans) == set)
+                               nft_trans_elem_set_bound(trans) = true;
                        break;
                }
        }
@@ -1662,7 +1667,11 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
 
                chain->flags |= NFT_BASE_CHAIN | flags;
                basechain->policy = NF_ACCEPT;
-               INIT_LIST_HEAD(&basechain->cb_list);
+               if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
+                   nft_chain_offload_priority(basechain) < 0)
+                       return -EOPNOTSUPP;
+
+               flow_block_init(&basechain->flow_block);
        } else {
                chain = kzalloc(sizeof(*chain), GFP_KERNEL);
                if (chain == NULL)
@@ -1900,6 +1909,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
 
        if (nla[NFTA_CHAIN_FLAGS])
                flags = ntohl(nla_get_be32(nla[NFTA_CHAIN_FLAGS]));
+       else if (chain)
+               flags = chain->flags;
 
        nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
 
@@ -6904,7 +6915,7 @@ static int __nf_tables_abort(struct net *net)
                        break;
                case NFT_MSG_NEWSET:
                        trans->ctx.table->use--;
-                       if (nft_trans_set(trans)->bound) {
+                       if (nft_trans_set_bound(trans)) {
                                nft_trans_destroy(trans);
                                break;
                        }
@@ -6916,7 +6927,7 @@ static int __nf_tables_abort(struct net *net)
                        nft_trans_destroy(trans);
                        break;
                case NFT_MSG_NEWSETELEM:
-                       if (nft_trans_elem_set(trans)->bound) {
+                       if (nft_trans_elem_set_bound(trans)) {
                                nft_trans_destroy(trans);
                                break;
                        }
index 2c3302845f675356e3fd36ae253fafd052a25348..c0d18c1d77ac05e0c9b1f98a33f2e18616bc3add 100644 (file)
@@ -103,10 +103,11 @@ void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
 }
 
 static void nft_flow_offload_common_init(struct flow_cls_common_offload *common,
-                                        __be16 proto,
-                                       struct netlink_ext_ack *extack)
+                                        __be16 proto, int priority,
+                                        struct netlink_ext_ack *extack)
 {
        common->protocol = proto;
+       common->prio = priority;
        common->extack = extack;
 }
 
@@ -116,7 +117,7 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain,
        struct flow_block_cb *block_cb;
        int err;
 
-       list_for_each_entry(block_cb, &basechain->cb_list, list) {
+       list_for_each_entry(block_cb, &basechain->flow_block.cb_list, list) {
                err = block_cb->cb(type, type_data, block_cb->cb_priv);
                if (err < 0)
                        return err;
@@ -124,6 +125,15 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain,
        return 0;
 }
 
+int nft_chain_offload_priority(struct nft_base_chain *basechain)
+{
+       if (basechain->ops.priority <= 0 ||
+           basechain->ops.priority > USHRT_MAX)
+               return -1;
+
+       return 0;
+}
+
 static int nft_flow_offload_rule(struct nft_trans *trans,
                                 enum flow_cls_command command)
 {
@@ -142,7 +152,8 @@ static int nft_flow_offload_rule(struct nft_trans *trans,
        if (flow)
                proto = flow->proto;
 
-       nft_flow_offload_common_init(&cls_flow.common, proto, &extack);
+       nft_flow_offload_common_init(&cls_flow.common, proto,
+                                    basechain->ops.priority, &extack);
        cls_flow.command = command;
        cls_flow.cookie = (unsigned long) rule;
        if (flow)
@@ -154,7 +165,7 @@ static int nft_flow_offload_rule(struct nft_trans *trans,
 static int nft_flow_offload_bind(struct flow_block_offload *bo,
                                 struct nft_base_chain *basechain)
 {
-       list_splice(&bo->cb_list, &basechain->cb_list);
+       list_splice(&bo->cb_list, &basechain->flow_block.cb_list);
        return 0;
 }
 
@@ -198,6 +209,7 @@ static int nft_flow_offload_chain(struct nft_trans *trans,
                return -EOPNOTSUPP;
 
        bo.command = cmd;
+       bo.block = &basechain->flow_block;
        bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
        bo.extack = &extack;
        INIT_LIST_HEAD(&bo.cb_list);
index 92077d4591090426ae6fd9335064e95214e76829..4abbb452cf6c60400087f02963c2b58ba08896d7 100644 (file)
@@ -578,7 +578,7 @@ static int nfnetlink_bind(struct net *net, int group)
        ss = nfnetlink_get_subsys(type << 8);
        rcu_read_unlock();
        if (!ss)
-               request_module("nfnetlink-subsys-%d", type);
+               request_module_nowait("nfnetlink-subsys-%d", type);
        return 0;
 }
 #endif
index 3fd540b2c6baf0cdf934d5b3ac12e140651e1e56..b5d5d071d765504522917ecd502116e193f76cf0 100644 (file)
@@ -193,7 +193,7 @@ static inline void nft_chain_filter_inet_init(void) {}
 static inline void nft_chain_filter_inet_fini(void) {}
 #endif /* CONFIG_NF_TABLES_IPV6 */
 
-#ifdef CONFIG_NF_TABLES_BRIDGE
+#if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE)
 static unsigned int
 nft_do_chain_bridge(void *priv,
                    struct sk_buff *skb,
index 2f89bde3c61cb93690238c8c53ccad3556806417..ff9ac8ae0031f037efe5ce1061ceabf79fde925a 100644 (file)
@@ -142,3 +142,6 @@ MODULE_ALIAS_NFT_CHAIN(AF_INET, "nat");
 #ifdef CONFIG_NF_TABLES_IPV6
 MODULE_ALIAS_NFT_CHAIN(AF_INET6, "nat");
 #endif
+#ifdef CONFIG_NF_TABLES_INET
+MODULE_ALIAS_NFT_CHAIN(1, "nat");      /* NFPROTO_INET */
+#endif
index 827ab6196df9964ab11ace6980d196155c6388ee..46ca8bcca1bd5c31f900b4d89f11ee55b27098d9 100644 (file)
@@ -1252,7 +1252,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
                          priv->l4proto, NULL, &priv->dport);
        exp->timeout.expires = jiffies + priv->timeout * HZ;
 
-       if (nf_ct_expect_related(exp) != 0)
+       if (nf_ct_expect_related(exp, 0) != 0)
                regs->verdict.code = NF_DROP;
 }
 
index 2cf3f32fe6d2543fd338b0a545aca3fd975ec04f..a2e726ae7f07737b8dc5d420cacbf00885a90ba0 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables_core.h>
 #include <net/netfilter/nf_tables.h>
+#include <net/ipv6.h>
 
 #include <net/netfilter/nft_fib.h>
 
@@ -34,6 +35,8 @@ static void nft_fib_netdev_eval(const struct nft_expr *expr,
                }
                break;
        case ETH_P_IPV6:
+               if (!ipv6_mod_enabled())
+                       break;
                switch (priv->result) {
                case NFT_FIB_RESULT_OIF:
                case NFT_FIB_RESULT_OIFNAME:
index aa5f571d43619a4dc21f7036986228e78b640066..01705ad74a9aa5cff33d5615021d6f9a13ccf347 100644 (file)
@@ -72,11 +72,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 {
        struct nft_flow_offload *priv = nft_expr_priv(expr);
        struct nf_flowtable *flowtable = &priv->flowtable->data;
+       struct tcphdr _tcph, *tcph = NULL;
        enum ip_conntrack_info ctinfo;
        struct nf_flow_route route;
        struct flow_offload *flow;
        enum ip_conntrack_dir dir;
-       bool is_tcp = false;
        struct nf_conn *ct;
        int ret;
 
@@ -89,7 +89,10 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 
        switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
        case IPPROTO_TCP:
-               is_tcp = true;
+               tcph = skb_header_pointer(pkt->skb, pkt->xt.thoff,
+                                         sizeof(_tcph), &_tcph);
+               if (unlikely(!tcph || tcph->fin || tcph->rst))
+                       goto out;
                break;
        case IPPROTO_UDP:
                break;
@@ -115,7 +118,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
        if (!flow)
                goto err_flow_alloc;
 
-       if (is_tcp) {
+       if (tcph) {
                ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
                ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
        }
@@ -146,6 +149,11 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx,
        return nft_chain_validate_hooks(ctx->chain, hook_mask);
 }
 
+static const struct nla_policy nft_flow_offload_policy[NFTA_FLOW_MAX + 1] = {
+       [NFTA_FLOW_TABLE_NAME]  = { .type = NLA_STRING,
+                                   .len = NFT_NAME_MAXLEN - 1 },
+};
+
 static int nft_flow_offload_init(const struct nft_ctx *ctx,
                                 const struct nft_expr *expr,
                                 const struct nlattr * const tb[])
@@ -204,6 +212,7 @@ static const struct nft_expr_ops nft_flow_offload_ops = {
 static struct nft_expr_type nft_flow_offload_type __read_mostly = {
        .name           = "flow_offload",
        .ops            = &nft_flow_offload_ops,
+       .policy         = nft_flow_offload_policy,
        .maxattr        = NFTA_FLOW_MAX,
        .owner          = THIS_MODULE,
 };
index fe93e731dc7fb961a11841f6609d42a2ebde9d78..b836d550b9199513023055ce2fef752ac87cfd17 100644 (file)
@@ -129,7 +129,7 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
        priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);
 
        priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
-       if (priv->modulus <= 1)
+       if (priv->modulus < 1)
                return -ERANGE;
 
        if (priv->offset + priv->modulus - 1 < priv->offset)
index 76866f77e3435d86d88d220e1b33c87cdcd95a4a..f69afb9ff3cbe04a5b36d9aef3964fb2e6962926 100644 (file)
@@ -60,24 +60,16 @@ void nft_meta_get_eval(const struct nft_expr *expr,
                *dest = skb->mark;
                break;
        case NFT_META_IIF:
-               if (in == NULL)
-                       goto err;
-               *dest = in->ifindex;
+               *dest = in ? in->ifindex : 0;
                break;
        case NFT_META_OIF:
-               if (out == NULL)
-                       goto err;
-               *dest = out->ifindex;
+               *dest = out ? out->ifindex : 0;
                break;
        case NFT_META_IIFNAME:
-               if (in == NULL)
-                       goto err;
-               strncpy((char *)dest, in->name, IFNAMSIZ);
+               strncpy((char *)dest, in ? in->name : "", IFNAMSIZ);
                break;
        case NFT_META_OIFNAME:
-               if (out == NULL)
-                       goto err;
-               strncpy((char *)dest, out->name, IFNAMSIZ);
+               strncpy((char *)dest, out ? out->name : "", IFNAMSIZ);
                break;
        case NFT_META_IIFTYPE:
                if (in == NULL)
@@ -546,7 +538,7 @@ nft_meta_select_ops(const struct nft_ctx *ctx,
        if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
                return ERR_PTR(-EINVAL);
 
-#ifdef CONFIG_NF_TABLES_BRIDGE
+#if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE) && IS_MODULE(CONFIG_NFT_BRIDGE_META)
        if (ctx->family == NFPROTO_BRIDGE)
                return ERR_PTR(-EAGAIN);
 #endif
index 8487eeff5c0ec8b1f0de14de92ba81e05db20b86..43eeb1f609f135ab7db6033e067c032b48c8a49a 100644 (file)
@@ -291,4 +291,4 @@ module_exit(nft_redir_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
-MODULE_ALIAS_NFT_EXPR("nat");
+MODULE_ALIAS_NFT_EXPR("redir");
index d7f3776dfd719d402ae178890107db8ebd1627f2..637ce3e8c575ce1b95dfcd340347176772cdff2d 100644 (file)
@@ -47,9 +47,6 @@ static void nft_socket_eval(const struct nft_expr *expr,
                return;
        }
 
-       /* So that subsequent socket matching not to require other lookups. */
-       skb->sk = sk;
-
        switch(priv->key) {
        case NFT_SOCKET_TRANSPARENT:
                nft_reg_store8(dest, inet_sk_transparent(sk));
@@ -66,6 +63,9 @@ static void nft_socket_eval(const struct nft_expr *expr,
                WARN_ON(1);
                regs->verdict.code = NFT_BREAK;
        }
+
+       if (sk != skb->sk)
+               sock_gen_put(sk);
 }
 
 static const struct nla_policy nft_socket_policy[NFTA_SOCKET_MAX + 1] = {
index 80060ade8a5b31b25defec4162f5120b16934db4..928e661d1517d0aa48e729c74b143c5e36f712de 100644 (file)
@@ -31,6 +31,8 @@ static void nft_synproxy_tcp_options(struct synproxy_options *opts,
                opts->options |= NF_SYNPROXY_OPT_ECN;
 
        opts->options &= priv->info.options;
+       opts->mss_encode = opts->mss;
+       opts->mss = info->mss;
        if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP)
                synproxy_init_timestamp_cookie(info, opts);
        else
index d0ab1adf5bff81a71fd489b24ce856e66016f781..5aab6df74e0f253012ea67a229547ebca5a60724 100644 (file)
@@ -54,25 +54,39 @@ nfacct_mt_destroy(const struct xt_mtdtor_param *par)
        nfnl_acct_put(info->nfacct);
 }
 
-static struct xt_match nfacct_mt_reg __read_mostly = {
-       .name       = "nfacct",
-       .family     = NFPROTO_UNSPEC,
-       .checkentry = nfacct_mt_checkentry,
-       .match      = nfacct_mt,
-       .destroy    = nfacct_mt_destroy,
-       .matchsize  = sizeof(struct xt_nfacct_match_info),
-       .usersize   = offsetof(struct xt_nfacct_match_info, nfacct),
-       .me         = THIS_MODULE,
+static struct xt_match nfacct_mt_reg[] __read_mostly = {
+       {
+               .name       = "nfacct",
+               .revision   = 0,
+               .family     = NFPROTO_UNSPEC,
+               .checkentry = nfacct_mt_checkentry,
+               .match      = nfacct_mt,
+               .destroy    = nfacct_mt_destroy,
+               .matchsize  = sizeof(struct xt_nfacct_match_info),
+               .usersize   = offsetof(struct xt_nfacct_match_info, nfacct),
+               .me         = THIS_MODULE,
+       },
+       {
+               .name       = "nfacct",
+               .revision   = 1,
+               .family     = NFPROTO_UNSPEC,
+               .checkentry = nfacct_mt_checkentry,
+               .match      = nfacct_mt,
+               .destroy    = nfacct_mt_destroy,
+               .matchsize  = sizeof(struct xt_nfacct_match_info_v1),
+               .usersize   = offsetof(struct xt_nfacct_match_info_v1, nfacct),
+               .me         = THIS_MODULE,
+       },
 };
 
 static int __init nfacct_mt_init(void)
 {
-       return xt_register_match(&nfacct_mt_reg);
+       return xt_register_matches(nfacct_mt_reg, ARRAY_SIZE(nfacct_mt_reg));
 }
 
 static void __exit nfacct_mt_exit(void)
 {
-       xt_unregister_match(&nfacct_mt_reg);
+       xt_unregister_matches(nfacct_mt_reg, ARRAY_SIZE(nfacct_mt_reg));
 }
 
 module_init(nfacct_mt_init);
index ead7c60222086579cc9f21ea2aa8b37747b35db1..b92b22ce8abd3f41b90901c4cae2e75918cc0645 100644 (file)
@@ -101,11 +101,9 @@ static int physdev_mt_check(const struct xt_mtchk_param *par)
        if (info->bitmask & (XT_PHYSDEV_OP_OUT | XT_PHYSDEV_OP_ISOUT) &&
            (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
             info->invert & XT_PHYSDEV_OP_BRIDGED) &&
-           par->hook_mask & ((1 << NF_INET_LOCAL_OUT) |
-           (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) {
+           par->hook_mask & (1 << NF_INET_LOCAL_OUT)) {
                pr_info_ratelimited("--physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic\n");
-               if (par->hook_mask & (1 << NF_INET_LOCAL_OUT))
-                       return -EINVAL;
+               return -EINVAL;
        }
 
        if (!brnf_probed) {
index 96740d389377170b90a5d3d2dba3482bd293eb9a..c4f54ad2b98afb44002415ce1daf2afef646d8c0 100644 (file)
@@ -967,6 +967,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 
        window = skb->data[20];
 
+       sock_hold(make);
        skb->sk             = make;
        skb->destructor     = sock_efree;
        make->sk_state      = TCP_ESTABLISHED;
index 848c6eb550644feaf5e9a785123861fdc4cb1c15..05249eb4508231186ba15b12a2330068b1d26b0d 100644 (file)
@@ -67,6 +67,7 @@ struct ovs_conntrack_info {
        struct md_mark mark;
        struct md_labels labels;
        char timeout[CTNL_TIMEOUT_NAME_MAX];
+       struct nf_ct_timeout *nf_ct_timeout;
 #if IS_ENABLED(CONFIG_NF_NAT)
        struct nf_nat_range2 range;  /* Only present for SRC NAT and DST NAT. */
 #endif
@@ -524,6 +525,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                return -EPFNOSUPPORT;
        }
 
+       /* The key extracted from the fragment that completed this datagram
+        * likely didn't have an L4 header, so regenerate it.
+        */
+       ovs_flow_key_update_l3l4(skb, key);
+
        key->ip.frag = OVS_FRAG_TYPE_NONE;
        skb_clear_hash(skb);
        skb->ignore_df = 1;
@@ -697,6 +703,14 @@ static bool skb_nfct_cached(struct net *net,
                if (help && rcu_access_pointer(help->helper) != info->helper)
                        return false;
        }
+       if (info->nf_ct_timeout) {
+               struct nf_conn_timeout *timeout_ext;
+
+               timeout_ext = nf_ct_timeout_find(ct);
+               if (!timeout_ext || info->nf_ct_timeout !=
+                   rcu_dereference(timeout_ext->timeout))
+                       return false;
+       }
        /* Force conntrack entry direction to the current packet? */
        if (info->force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
                /* Delete the conntrack entry if confirmed, else just release
@@ -1565,7 +1579,7 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
                case OVS_CT_ATTR_TIMEOUT:
                        memcpy(info->timeout, nla_data(a), nla_len(a));
                        if (!memchr(info->timeout, '\0', nla_len(a))) {
-                               OVS_NLERR(log, "Invalid conntrack helper");
+                               OVS_NLERR(log, "Invalid conntrack timeout");
                                return -EINVAL;
                        }
                        break;
@@ -1657,6 +1671,10 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
                                      ct_info.timeout))
                        pr_info_ratelimited("Failed to associated timeout "
                                            "policy `%s'\n", ct_info.timeout);
+               else
+                       ct_info.nf_ct_timeout = rcu_dereference(
+                               nf_ct_timeout_find(ct_info.ct)->timeout);
+
        }
 
        if (helper) {
index 892287d06c1768d3f16b029859f344c560984ff1..d01410e520979dd4a05336568f80dd6e0362bd93 100644 (file)
@@ -1047,7 +1047,7 @@ error:
 }
 
 /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */
-static struct sw_flow_actions *get_flow_actions(struct net *net,
+static noinline_for_stack struct sw_flow_actions *get_flow_actions(struct net *net,
                                                const struct nlattr *a,
                                                const struct sw_flow_key *key,
                                                const struct sw_flow_mask *mask,
@@ -1081,12 +1081,13 @@ static struct sw_flow_actions *get_flow_actions(struct net *net,
  * we should not to return match object with dangling reference
  * to mask.
  * */
-static int ovs_nla_init_match_and_action(struct net *net,
-                                        struct sw_flow_match *match,
-                                        struct sw_flow_key *key,
-                                        struct nlattr **a,
-                                        struct sw_flow_actions **acts,
-                                        bool log)
+static noinline_for_stack int
+ovs_nla_init_match_and_action(struct net *net,
+                             struct sw_flow_match *match,
+                             struct sw_flow_key *key,
+                             struct nlattr **a,
+                             struct sw_flow_actions **acts,
+                             bool log)
 {
        struct sw_flow_mask mask;
        int error = 0;
index dca3b1e2acf060a5665e2c52484a60180292e51f..9d81d2c7bf8212e5d50063634e8ab064b2005040 100644 (file)
@@ -59,7 +59,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
 void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
                           const struct sk_buff *skb)
 {
-       struct flow_stats *stats;
+       struct sw_flow_stats *stats;
        unsigned int cpu = smp_processor_id();
        int len = skb->len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
 
@@ -87,7 +87,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
                        if (likely(flow->stats_last_writer != -1) &&
                            likely(!rcu_access_pointer(flow->stats[cpu]))) {
                                /* Try to allocate CPU-specific stats. */
-                               struct flow_stats *new_stats;
+                               struct sw_flow_stats *new_stats;
 
                                new_stats =
                                        kmem_cache_alloc_node(flow_stats_cache,
@@ -134,7 +134,7 @@ void ovs_flow_stats_get(const struct sw_flow *flow,
 
        /* We open code this to make sure cpu 0 is always considered */
        for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) {
-               struct flow_stats *stats = rcu_dereference_ovsl(flow->stats[cpu]);
+               struct sw_flow_stats *stats = rcu_dereference_ovsl(flow->stats[cpu]);
 
                if (stats) {
                        /* Local CPU may write on non-local stats, so we must
@@ -158,7 +158,7 @@ void ovs_flow_stats_clear(struct sw_flow *flow)
 
        /* We open code this to make sure cpu 0 is always considered */
        for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) {
-               struct flow_stats *stats = ovsl_dereference(flow->stats[cpu]);
+               struct sw_flow_stats *stats = ovsl_dereference(flow->stats[cpu]);
 
                if (stats) {
                        spin_lock_bh(&stats->lock);
@@ -523,78 +523,15 @@ static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
 }
 
 /**
- * key_extract - extracts a flow key from an Ethernet frame.
+ * key_extract_l3l4 - extracts L3/L4 header information.
  * @skb: sk_buff that contains the frame, with skb->data pointing to the
- * Ethernet header
+ *       L3 header
  * @key: output flow key
  *
- * The caller must ensure that skb->len >= ETH_HLEN.
- *
- * Returns 0 if successful, otherwise a negative errno value.
- *
- * Initializes @skb header fields as follows:
- *
- *    - skb->mac_header: the L2 header.
- *
- *    - skb->network_header: just past the L2 header, or just past the
- *      VLAN header, to the first byte of the L2 payload.
- *
- *    - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
- *      on output, then just past the IP header, if one is present and
- *      of a correct length, otherwise the same as skb->network_header.
- *      For other key->eth.type values it is left untouched.
- *
- *    - skb->protocol: the type of the data starting at skb->network_header.
- *      Equals to key->eth.type.
  */
-static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
 {
        int error;
-       struct ethhdr *eth;
-
-       /* Flags are always used as part of stats */
-       key->tp.flags = 0;
-
-       skb_reset_mac_header(skb);
-
-       /* Link layer. */
-       clear_vlan(key);
-       if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
-               if (unlikely(eth_type_vlan(skb->protocol)))
-                       return -EINVAL;
-
-               skb_reset_network_header(skb);
-               key->eth.type = skb->protocol;
-       } else {
-               eth = eth_hdr(skb);
-               ether_addr_copy(key->eth.src, eth->h_source);
-               ether_addr_copy(key->eth.dst, eth->h_dest);
-
-               __skb_pull(skb, 2 * ETH_ALEN);
-               /* We are going to push all headers that we pull, so no need to
-               * update skb->csum here.
-               */
-
-               if (unlikely(parse_vlan(skb, key)))
-                       return -ENOMEM;
-
-               key->eth.type = parse_ethertype(skb);
-               if (unlikely(key->eth.type == htons(0)))
-                       return -ENOMEM;
-
-               /* Multiple tagged packets need to retain TPID to satisfy
-                * skb_vlan_pop(), which will later shift the ethertype into
-                * skb->protocol.
-                */
-               if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
-                       skb->protocol = key->eth.cvlan.tpid;
-               else
-                       skb->protocol = key->eth.type;
-
-               skb_reset_network_header(skb);
-               __skb_push(skb, skb->data - skb_mac_header(skb));
-       }
-       skb_reset_mac_len(skb);
 
        /* Network layer. */
        if (key->eth.type == htons(ETH_P_IP)) {
@@ -623,6 +560,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
                offset = nh->frag_off & htons(IP_OFFSET);
                if (offset) {
                        key->ip.frag = OVS_FRAG_TYPE_LATER;
+                       memset(&key->tp, 0, sizeof(key->tp));
                        return 0;
                }
                if (nh->frag_off & htons(IP_MF) ||
@@ -740,8 +678,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
                        return error;
                }
 
-               if (key->ip.frag == OVS_FRAG_TYPE_LATER)
+               if (key->ip.frag == OVS_FRAG_TYPE_LATER) {
+                       memset(&key->tp, 0, sizeof(key->tp));
                        return 0;
+               }
                if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
                        key->ip.frag = OVS_FRAG_TYPE_FIRST;
 
@@ -788,6 +728,92 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
        return 0;
 }
 
+/**
+ * key_extract - extracts a flow key from an Ethernet frame.
+ * @skb: sk_buff that contains the frame, with skb->data pointing to the
+ * Ethernet header
+ * @key: output flow key
+ *
+ * The caller must ensure that skb->len >= ETH_HLEN.
+ *
+ * Returns 0 if successful, otherwise a negative errno value.
+ *
+ * Initializes @skb header fields as follows:
+ *
+ *    - skb->mac_header: the L2 header.
+ *
+ *    - skb->network_header: just past the L2 header, or just past the
+ *      VLAN header, to the first byte of the L2 payload.
+ *
+ *    - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
+ *      on output, then just past the IP header, if one is present and
+ *      of a correct length, otherwise the same as skb->network_header.
+ *      For other key->eth.type values it is left untouched.
+ *
+ *    - skb->protocol: the type of the data starting at skb->network_header.
+ *      Equals to key->eth.type.
+ */
+static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+{
+       struct ethhdr *eth;
+
+       /* Flags are always used as part of stats */
+       key->tp.flags = 0;
+
+       skb_reset_mac_header(skb);
+
+       /* Link layer. */
+       clear_vlan(key);
+       if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
+               if (unlikely(eth_type_vlan(skb->protocol)))
+                       return -EINVAL;
+
+               skb_reset_network_header(skb);
+               key->eth.type = skb->protocol;
+       } else {
+               eth = eth_hdr(skb);
+               ether_addr_copy(key->eth.src, eth->h_source);
+               ether_addr_copy(key->eth.dst, eth->h_dest);
+
+               __skb_pull(skb, 2 * ETH_ALEN);
+               /* We are going to push all headers that we pull, so no need to
+                * update skb->csum here.
+                */
+
+               if (unlikely(parse_vlan(skb, key)))
+                       return -ENOMEM;
+
+               key->eth.type = parse_ethertype(skb);
+               if (unlikely(key->eth.type == htons(0)))
+                       return -ENOMEM;
+
+               /* Multiple tagged packets need to retain TPID to satisfy
+                * skb_vlan_pop(), which will later shift the ethertype into
+                * skb->protocol.
+                */
+               if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
+                       skb->protocol = key->eth.cvlan.tpid;
+               else
+                       skb->protocol = key->eth.type;
+
+               skb_reset_network_header(skb);
+               __skb_push(skb, skb->data - skb_mac_header(skb));
+       }
+
+       skb_reset_mac_len(skb);
+
+       /* Fill out L3/L4 key info, if any */
+       return key_extract_l3l4(skb, key);
+}
+
+/* In the case of conntrack fragment handling it expects L3 headers,
+ * add a helper.
+ */
+int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
+{
+       return key_extract_l3l4(skb, key);
+}
+
 int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
 {
        int res;
index 3e2cc2202d668c9833c9330498226e4cef098c84..b830d5ff7af4de82d7ccddcd851e892f4311f6d4 100644 (file)
@@ -194,7 +194,7 @@ struct sw_flow_actions {
        struct nlattr actions[];
 };
 
-struct flow_stats {
+struct sw_flow_stats {
        u64 packet_count;               /* Number of packets matched. */
        u64 byte_count;                 /* Number of bytes matched. */
        unsigned long used;             /* Last used time (in jiffies). */
@@ -216,7 +216,7 @@ struct sw_flow {
        struct cpumask cpu_used_mask;
        struct sw_flow_mask *mask;
        struct sw_flow_actions __rcu *sf_acts;
-       struct flow_stats __rcu *stats[]; /* One for each CPU.  First one
+       struct sw_flow_stats __rcu *stats[]; /* One for each CPU.  First one
                                           * is allocated at flow creation time,
                                           * the rest are allocated on demand
                                           * while holding the 'stats[0].lock'.
@@ -270,6 +270,7 @@ void ovs_flow_stats_clear(struct sw_flow *);
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
 int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
+int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key);
 int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
                         struct sk_buff *skb,
                         struct sw_flow_key *key);
index 988fd8a94e43ec106892b0213106e878e7f98733..cf3582c5ed70c388fd019df293d14172ce27422b 100644 (file)
@@ -66,7 +66,7 @@ void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
 struct sw_flow *ovs_flow_alloc(void)
 {
        struct sw_flow *flow;
-       struct flow_stats *stats;
+       struct sw_flow_stats *stats;
 
        flow = kmem_cache_zalloc(flow_cache, GFP_KERNEL);
        if (!flow)
@@ -110,7 +110,7 @@ static void flow_free(struct sw_flow *flow)
        for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask))
                if (flow->stats[cpu])
                        kmem_cache_free(flow_stats_cache,
-                                       (struct flow_stats __force *)flow->stats[cpu]);
+                                       (struct sw_flow_stats __force *)flow->stats[cpu]);
        kmem_cache_free(flow_cache, flow);
 }
 
@@ -712,13 +712,13 @@ int ovs_flow_init(void)
 
        flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow)
                                       + (nr_cpu_ids
-                                         * sizeof(struct flow_stats *)),
+                                         * sizeof(struct sw_flow_stats *)),
                                       0, 0, NULL);
        if (flow_cache == NULL)
                return -ENOMEM;
 
        flow_stats_cache
-               = kmem_cache_create("sw_flow_stats", sizeof(struct flow_stats),
+               = kmem_cache_create("sw_flow_stats", sizeof(struct sw_flow_stats),
                                    0, SLAB_HWCACHE_ALIGN, NULL);
        if (flow_stats_cache == NULL) {
                kmem_cache_destroy(flow_cache);
index 8d54f3047768d2272cbd28a7bcda33df800aa589..e2742b006d255f598fc98953dbb823f615d2bf9a 100644 (file)
@@ -2618,6 +2618,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
        mutex_lock(&po->pg_vec_lock);
 
+       /* packet_sendmsg() check on tx_ring.pg_vec was lockless,
+        * we need to confirm it under protection of pg_vec_lock.
+        */
+       if (unlikely(!po->tx_ring.pg_vec)) {
+               err = -EBUSY;
+               goto out;
+       }
        if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
index 841f198ea1a8853c57e6b9f7309d02bbf11d3ba5..66e4b61a350d5472776286e415192fba140d8a36 100644 (file)
@@ -154,7 +154,7 @@ static void psample_group_destroy(struct psample_group *group)
 {
        psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP);
        list_del(&group->list);
-       kfree(group);
+       kfree_rcu(group, rcu);
 }
 
 static struct psample_group *
index ccff1e544c2183ba709d488c80015b8932370fbc..e35869e81766ea6660176c94fa910dbe2614bf61 100644 (file)
@@ -84,11 +84,14 @@ static ssize_t qrtr_tun_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (!kbuf)
                return -ENOMEM;
 
-       if (!copy_from_iter_full(kbuf, len, from))
+       if (!copy_from_iter_full(kbuf, len, from)) {
+               kfree(kbuf);
                return -EFAULT;
+       }
 
        ret = qrtr_endpoint_post(&tun->ep, kbuf, len);
 
+       kfree(kbuf);
        return ret < 0 ? ret : len;
 }
 
index 0f4398e7f2a7add7c20b6fdd333c40af4e719c92..05464fd7c17afcc708eec3e4305ca85d039048d3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -239,34 +239,30 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                goto out;
        }
 
-       sock_set_flag(sk, SOCK_RCU_FREE);
-       ret = rds_add_bound(rs, binding_addr, &port, scope_id);
-       if (ret)
-               goto out;
-
-       if (rs->rs_transport) { /* previously bound */
+       /* The transport can be set using SO_RDS_TRANSPORT option before the
+        * socket is bound.
+        */
+       if (rs->rs_transport) {
                trans = rs->rs_transport;
                if (trans->laddr_check(sock_net(sock->sk),
                                       binding_addr, scope_id) != 0) {
                        ret = -ENOPROTOOPT;
-                       rds_remove_bound(rs);
-               } else {
-                       ret = 0;
+                       goto out;
                }
-               goto out;
-       }
-       trans = rds_trans_get_preferred(sock_net(sock->sk), binding_addr,
-                                       scope_id);
-       if (!trans) {
-               ret = -EADDRNOTAVAIL;
-               rds_remove_bound(rs);
-               pr_info_ratelimited("RDS: %s could not find a transport for %pI6c, load rds_tcp or rds_rdma?\n",
-                                   __func__, binding_addr);
-               goto out;
+       } else {
+               trans = rds_trans_get_preferred(sock_net(sock->sk),
+                                               binding_addr, scope_id);
+               if (!trans) {
+                       ret = -EADDRNOTAVAIL;
+                       pr_info_ratelimited("RDS: %s could not find a transport for %pI6c, load rds_tcp or rds_rdma?\n",
+                                           __func__, binding_addr);
+                       goto out;
+               }
+               rs->rs_transport = trans;
        }
 
-       rs->rs_transport = trans;
-       ret = 0;
+       sock_set_flag(sk, SOCK_RCU_FREE);
+       ret = rds_add_bound(rs, binding_addr, &port, scope_id);
 
 out:
        release_sock(sk);
index ec05d91aa9a2b39b0b904a275b0731ba540ebb3c..45acab2de0cf3e09b295d2faf7db3b3c78528fc5 100644 (file)
@@ -291,7 +291,7 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn,
                                    void *buffer)
 {
        struct rds_info_rdma_connection *iinfo = buffer;
-       struct rds_ib_connection *ic;
+       struct rds_ib_connection *ic = conn->c_transport_data;
 
        /* We will only ever look at IB transports */
        if (conn->c_trans != &rds_ib_transport)
@@ -301,15 +301,16 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn,
 
        iinfo->src_addr = conn->c_laddr.s6_addr32[3];
        iinfo->dst_addr = conn->c_faddr.s6_addr32[3];
-       iinfo->tos = conn->c_tos;
+       if (ic) {
+               iinfo->tos = conn->c_tos;
+               iinfo->sl = ic->i_sl;
+       }
 
        memset(&iinfo->src_gid, 0, sizeof(iinfo->src_gid));
        memset(&iinfo->dst_gid, 0, sizeof(iinfo->dst_gid));
        if (rds_conn_state(conn) == RDS_CONN_UP) {
                struct rds_ib_device *rds_ibdev;
 
-               ic = conn->c_transport_data;
-
                rdma_read_gids(ic->i_cm_id, (union ib_gid *)&iinfo->src_gid,
                               (union ib_gid *)&iinfo->dst_gid);
 
@@ -329,7 +330,7 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn,
                                     void *buffer)
 {
        struct rds6_info_rdma_connection *iinfo6 = buffer;
-       struct rds_ib_connection *ic;
+       struct rds_ib_connection *ic = conn->c_transport_data;
 
        /* We will only ever look at IB transports */
        if (conn->c_trans != &rds_ib_transport)
@@ -337,6 +338,10 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn,
 
        iinfo6->src_addr = conn->c_laddr;
        iinfo6->dst_addr = conn->c_faddr;
+       if (ic) {
+               iinfo6->tos = conn->c_tos;
+               iinfo6->sl = ic->i_sl;
+       }
 
        memset(&iinfo6->src_gid, 0, sizeof(iinfo6->src_gid));
        memset(&iinfo6->dst_gid, 0, sizeof(iinfo6->dst_gid));
@@ -344,7 +349,6 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn,
        if (rds_conn_state(conn) == RDS_CONN_UP) {
                struct rds_ib_device *rds_ibdev;
 
-               ic = conn->c_transport_data;
                rdma_read_gids(ic->i_cm_id, (union ib_gid *)&iinfo6->src_gid,
                               (union ib_gid *)&iinfo6->dst_gid);
                rds_ibdev = ic->rds_ibdev;
index 303c6ee8bdb7b0835448068e64dc992fda0380a1..f2b558e8b5eaf738cd6b1a46dc98c20205d5ab7b 100644 (file)
@@ -220,6 +220,7 @@ struct rds_ib_connection {
        /* Send/Recv vectors */
        int                     i_scq_vector;
        int                     i_rcq_vector;
+       u8                      i_sl;
 };
 
 /* This assumes that atomic_t is at least 32 bits */
index fddaa09f7b0dbd68d1d19cef054dccaa6369e45c..233f1368162b4f1be8596ba2d4803fdced10b41a 100644 (file)
@@ -152,6 +152,9 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
                  RDS_PROTOCOL_MINOR(conn->c_version),
                  ic->i_flowctl ? ", flow control" : "");
 
+       /* receive sl from the peer */
+       ic->i_sl = ic->i_cm_id->route.path_rec->sl;
+
        atomic_set(&ic->i_cq_quiesce, 0);
 
        /* Init rings and fill recv. this needs to wait until protocol
index ff74c4bbb9fc883f4107432c11a47f3d6f840137..5f741e51b4baa46f825b7a676969cde3159b2c21 100644 (file)
@@ -43,6 +43,9 @@ static struct rdma_cm_id *rds_rdma_listen_id;
 static struct rdma_cm_id *rds6_rdma_listen_id;
 #endif
 
+/* Per IB specification 7.7.3, service level is a 4-bit field. */
+#define TOS_TO_SL(tos)         ((tos) & 0xF)
+
 static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
                                         struct rdma_cm_event *event,
                                         bool isv6)
@@ -97,15 +100,19 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
                        struct rds_ib_connection *ibic;
 
                        ibic = conn->c_transport_data;
-                       if (ibic && ibic->i_cm_id == cm_id)
+                       if (ibic && ibic->i_cm_id == cm_id) {
+                               cm_id->route.path_rec[0].sl =
+                                       TOS_TO_SL(conn->c_tos);
                                ret = trans->cm_initiate_connect(cm_id, isv6);
-                       else
+                       } else {
                                rds_conn_drop(conn);
+                       }
                }
                break;
 
        case RDMA_CM_EVENT_ESTABLISHED:
-               trans->cm_connect_complete(conn, event);
+               if (conn)
+                       trans->cm_connect_complete(conn, event);
                break;
 
        case RDMA_CM_EVENT_REJECTED:
@@ -137,6 +144,8 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
                break;
 
        case RDMA_CM_EVENT_DISCONNECTED:
+               if (!conn)
+                       break;
                rdsdebug("DISCONNECT event - dropping connection "
                         "%pI6c->%pI6c\n", &conn->c_laddr,
                         &conn->c_faddr);
index 853de48760880603bf60142700cd668100ca289e..a42ba7fa06d5d0a04e9829ffdf5561c3e648353a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -811,6 +811,7 @@ void rds6_inc_info_copy(struct rds_incoming *inc,
 
        minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence);
        minfo6.len = be32_to_cpu(inc->i_hdr.h_len);
+       minfo6.tos = inc->i_conn->c_tos;
 
        if (flip) {
                minfo6.laddr = *daddr;
@@ -824,6 +825,8 @@ void rds6_inc_info_copy(struct rds_incoming *inc,
                minfo6.fport = inc->i_hdr.h_dport;
        }
 
+       minfo6.flags = 0;
+
        rds_info_copy(iter, &minfo6, sizeof(minfo6));
 }
 #endif
index d09eaf1535441fbea8f1b8b6cbba052f2a23d159..d72ddb67bb742a0f6db6db765dd0035c94f636e8 100644 (file)
@@ -193,7 +193,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
 
 service_in_use:
        write_unlock(&local->services_lock);
-       rxrpc_put_local(local);
+       rxrpc_unuse_local(local);
        ret = -EADDRINUSE;
 error_unlock:
        release_sock(&rx->sk);
@@ -402,7 +402,7 @@ EXPORT_SYMBOL(rxrpc_kernel_check_life);
  */
 void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call)
 {
-       rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+       rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                          rxrpc_propose_ack_ping_for_check_life);
        rxrpc_send_ack_packet(call, true, NULL);
 }
@@ -862,7 +862,6 @@ static void rxrpc_sock_destructor(struct sock *sk)
 static int rxrpc_release_sock(struct sock *sk)
 {
        struct rxrpc_sock *rx = rxrpc_sk(sk);
-       struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
 
        _enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
 
@@ -898,10 +897,8 @@ static int rxrpc_release_sock(struct sock *sk)
        rxrpc_release_calls_on_socket(rx);
        flush_workqueue(rxrpc_workqueue);
        rxrpc_purge_queue(&sk->sk_receive_queue);
-       rxrpc_queue_work(&rxnet->service_conn_reaper);
-       rxrpc_queue_work(&rxnet->client_conn_reaper);
 
-       rxrpc_put_local(rx->local);
+       rxrpc_unuse_local(rx->local);
        rx->local = NULL;
        key_put(rx->key);
        rx->key = NULL;
index 80335b4ee4fd6c2b1ae39bed5b9089e35c292b84..8051dfdcf26df1a506043ab887de93dd5c24aadc 100644 (file)
@@ -185,11 +185,17 @@ struct rxrpc_host_header {
  * - max 48 bytes (struct sk_buff::cb)
  */
 struct rxrpc_skb_priv {
-       union {
-               u8              nr_jumbo;       /* Number of jumbo subpackets */
-       };
+       atomic_t        nr_ring_pins;           /* Number of rxtx ring pins */
+       u8              nr_subpackets;          /* Number of subpackets */
+       u8              rx_flags;               /* Received packet flags */
+#define RXRPC_SKB_INCL_LAST    0x01            /* - Includes last packet */
+#define RXRPC_SKB_TX_BUFFER    0x02            /* - Is transmit buffer */
        union {
                int             remain;         /* amount of space remaining for next write */
+
+               /* List of requested ACKs on subpackets */
+               unsigned long   rx_req_ack[(RXRPC_MAX_NR_JUMBO + BITS_PER_LONG - 1) /
+                                          BITS_PER_LONG];
        };
 
        struct rxrpc_host_header hdr;           /* RxRPC packet header from this packet */
@@ -254,7 +260,8 @@ struct rxrpc_security {
  */
 struct rxrpc_local {
        struct rcu_head         rcu;
-       atomic_t                usage;
+       atomic_t                active_users;   /* Number of users of the local endpoint */
+       atomic_t                usage;          /* Number of references to the structure */
        struct rxrpc_net        *rxnet;         /* The network ns in which this resides */
        struct list_head        link;
        struct socket           *socket;        /* my UDP socket */
@@ -612,8 +619,7 @@ struct rxrpc_call {
 #define RXRPC_TX_ANNO_LAST     0x04
 #define RXRPC_TX_ANNO_RESENT   0x08
 
-#define RXRPC_RX_ANNO_JUMBO    0x3f            /* Jumbo subpacket number + 1 if not zero */
-#define RXRPC_RX_ANNO_JLAST    0x40            /* Set if last element of a jumbo packet */
+#define RXRPC_RX_ANNO_SUBPACKET        0x3f            /* Subpacket number in jumbogram */
 #define RXRPC_RX_ANNO_VERIFIED 0x80            /* Set if verified and decrypted */
        rxrpc_seq_t             tx_hard_ack;    /* Dead slot in buffer; the first transmitted but
                                                 * not hard-ACK'd packet follows this.
@@ -649,7 +655,6 @@ struct rxrpc_call {
 
        /* receive-phase ACK management */
        u8                      ackr_reason;    /* reason to ACK */
-       u16                     ackr_skew;      /* skew on packet being ACK'd */
        rxrpc_serial_t          ackr_serial;    /* serial of packet being ACK'd */
        rxrpc_serial_t          ackr_first_seq; /* first sequence number received */
        rxrpc_seq_t             ackr_prev_seq;  /* previous sequence number received */
@@ -743,7 +748,7 @@ int rxrpc_reject_call(struct rxrpc_sock *);
 /*
  * call_event.c
  */
-void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool,
+void rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool, bool,
                       enum rxrpc_propose_ack_trace);
 void rxrpc_process_call(struct work_struct *);
 
@@ -905,6 +910,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *);
 void rxrpc_put_client_conn(struct rxrpc_connection *);
 void rxrpc_discard_expired_client_conns(struct work_struct *);
 void rxrpc_destroy_all_client_connections(struct rxrpc_net *);
+void rxrpc_clean_up_local_conns(struct rxrpc_local *);
 
 /*
  * conn_event.c
@@ -1002,6 +1008,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc
 struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *);
 struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *);
 void rxrpc_put_local(struct rxrpc_local *);
+struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *);
+void rxrpc_unuse_local(struct rxrpc_local *);
 void rxrpc_queue_local(struct rxrpc_local *);
 void rxrpc_destroy_all_locals(struct rxrpc_net *);
 
@@ -1061,6 +1069,7 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *);
 struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *);
 struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *);
 void rxrpc_put_peer(struct rxrpc_peer *);
+void rxrpc_put_peer_locked(struct rxrpc_peer *);
 
 /*
  * proc.c
@@ -1102,6 +1111,7 @@ void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *);
 void rxrpc_packet_destructor(struct sk_buff *);
 void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
+void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_purge_queue(struct sk_buff_head *);
index bc2adeb3acb9c9a54728cd9419c66186c22e4906..cedbbb3a7c2ea27ddef918ca0e3bcc690ddd8f3d 100644 (file)
@@ -43,8 +43,7 @@ static void rxrpc_propose_ping(struct rxrpc_call *call,
  * propose an ACK be sent
  */
 static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
-                               u16 skew, u32 serial, bool immediate,
-                               bool background,
+                               u32 serial, bool immediate, bool background,
                                enum rxrpc_propose_ack_trace why)
 {
        enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use;
@@ -69,14 +68,12 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
                if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) {
                        outcome = rxrpc_propose_ack_update;
                        call->ackr_serial = serial;
-                       call->ackr_skew = skew;
                }
                if (!immediate)
                        goto trace;
        } else if (prior > rxrpc_ack_priority[call->ackr_reason]) {
                call->ackr_reason = ack_reason;
                call->ackr_serial = serial;
-               call->ackr_skew = skew;
        } else {
                outcome = rxrpc_propose_ack_subsume;
        }
@@ -137,11 +134,11 @@ trace:
  * propose an ACK be sent, locking the call structure
  */
 void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
-                      u16 skew, u32 serial, bool immediate, bool background,
+                      u32 serial, bool immediate, bool background,
                       enum rxrpc_propose_ack_trace why)
 {
        spin_lock_bh(&call->lock);
-       __rxrpc_propose_ACK(call, ack_reason, skew, serial,
+       __rxrpc_propose_ACK(call, ack_reason, serial,
                            immediate, background, why);
        spin_unlock_bh(&call->lock);
 }
@@ -202,7 +199,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
                        continue;
 
                skb = call->rxtx_buffer[ix];
-               rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
+               rxrpc_see_skb(skb, rxrpc_skb_seen);
 
                if (anno_type == RXRPC_TX_ANNO_UNACK) {
                        if (ktime_after(skb->tstamp, max_age)) {
@@ -239,7 +236,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
                ack_ts = ktime_sub(now, call->acks_latest_ts);
                if (ktime_to_ns(ack_ts) < call->peer->rtt)
                        goto out;
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                                  rxrpc_propose_ack_ping_for_lost_ack);
                rxrpc_send_ack_packet(call, true, NULL);
                goto out;
@@ -258,18 +255,18 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
                        continue;
 
                skb = call->rxtx_buffer[ix];
-               rxrpc_get_skb(skb, rxrpc_skb_tx_got);
+               rxrpc_get_skb(skb, rxrpc_skb_got);
                spin_unlock_bh(&call->lock);
 
                if (rxrpc_send_data_packet(call, skb, true) < 0) {
-                       rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+                       rxrpc_free_skb(skb, rxrpc_skb_freed);
                        return;
                }
 
                if (rxrpc_is_client_call(call))
                        rxrpc_expose_client_call(call);
 
-               rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
                spin_lock_bh(&call->lock);
 
                /* We need to clear the retransmit state, but there are two
@@ -372,7 +369,7 @@ recheck_state:
        if (time_after_eq(now, t)) {
                trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now);
                cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET);
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, true,
                                  rxrpc_propose_ack_ping_for_keepalive);
                set_bit(RXRPC_CALL_EV_PING, &call->events);
        }
@@ -407,7 +404,7 @@ recheck_state:
        send_ack = NULL;
        if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) {
                call->acks_lost_top = call->tx_top;
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                                  rxrpc_propose_ack_ping_for_lost_ack);
                send_ack = &call->acks_lost_ping;
        }
index 217b12be9e089d7aea3c774c50314c6fd2bdf83d..014548c259ceb9fa82e241a2bcae64ac76b77eb3 100644 (file)
@@ -421,6 +421,19 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
        trace_rxrpc_call(call, op, n, here, NULL);
 }
 
+/*
+ * Clean up the RxTx skb ring.
+ */
+static void rxrpc_cleanup_ring(struct rxrpc_call *call)
+{
+       int i;
+
+       for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
+               rxrpc_free_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned);
+               call->rxtx_buffer[i] = NULL;
+       }
+}
+
 /*
  * Detach a call from its owning socket.
  */
@@ -429,7 +442,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
        const void *here = __builtin_return_address(0);
        struct rxrpc_connection *conn = call->conn;
        bool put = false;
-       int i;
 
        _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
 
@@ -479,13 +491,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
        if (conn)
                rxrpc_disconnect_call(call);
 
-       for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
-               rxrpc_free_skb(call->rxtx_buffer[i],
-                              (call->tx_phase ? rxrpc_skb_tx_cleaned :
-                               rxrpc_skb_rx_cleaned));
-               call->rxtx_buffer[i] = NULL;
-       }
-
+       rxrpc_cleanup_ring(call);
        _leave("");
 }
 
@@ -568,8 +574,6 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
  */
 void rxrpc_cleanup_call(struct rxrpc_call *call)
 {
-       int i;
-
        _net("DESTROY CALL %d", call->debug_id);
 
        memset(&call->sock_node, 0xcd, sizeof(call->sock_node));
@@ -580,13 +584,8 @@ void rxrpc_cleanup_call(struct rxrpc_call *call)
        ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags));
        ASSERTCMP(call->conn, ==, NULL);
 
-       /* Clean up the Rx/Tx buffer */
-       for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++)
-               rxrpc_free_skb(call->rxtx_buffer[i],
-                              (call->tx_phase ? rxrpc_skb_tx_cleaned :
-                               rxrpc_skb_rx_cleaned));
-
-       rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned);
+       rxrpc_cleanup_ring(call);
+       rxrpc_free_skb(call->tx_pending, rxrpc_skb_cleaned);
 
        call_rcu(&call->rcu, rxrpc_rcu_destroy_call);
 }
index aea82f909c60801d347c8f02eeb5d9b9790bff91..3f1da1b49f690d0e3ccf6d93607cd2b0583d293b 100644 (file)
@@ -1162,3 +1162,47 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet)
 
        _leave("");
 }
+
+/*
+ * Clean up the client connections on a local endpoint.
+ */
+void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
+{
+       struct rxrpc_connection *conn, *tmp;
+       struct rxrpc_net *rxnet = local->rxnet;
+       unsigned int nr_active;
+       LIST_HEAD(graveyard);
+
+       _enter("");
+
+       spin_lock(&rxnet->client_conn_cache_lock);
+       nr_active = rxnet->nr_active_client_conns;
+
+       list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns,
+                                cache_link) {
+               if (conn->params.local == local) {
+                       ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_IDLE);
+
+                       trace_rxrpc_client(conn, -1, rxrpc_client_discard);
+                       if (!test_and_clear_bit(RXRPC_CONN_EXPOSED, &conn->flags))
+                               BUG();
+                       conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
+                       list_move(&conn->cache_link, &graveyard);
+                       nr_active--;
+               }
+       }
+
+       rxnet->nr_active_client_conns = nr_active;
+       spin_unlock(&rxnet->client_conn_cache_lock);
+       ASSERTCMP(nr_active, >=, 0);
+
+       while (!list_empty(&graveyard)) {
+               conn = list_entry(graveyard.next,
+                                 struct rxrpc_connection, cache_link);
+               list_del_init(&conn->cache_link);
+
+               rxrpc_put_connection(conn);
+       }
+
+       _leave(" [culled]");
+}
index df6624c140be9be2fc248d5f533a9245c4b07e9c..a1ceef4f5cd07754fff2fa5e1472ff60a50a272e 100644 (file)
@@ -472,7 +472,7 @@ void rxrpc_process_connection(struct work_struct *work)
        /* go through the conn-level event packets, releasing the ref on this
         * connection that each one has when we've finished with it */
        while ((skb = skb_dequeue(&conn->rx_queue))) {
-               rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+               rxrpc_see_skb(skb, rxrpc_skb_seen);
                ret = rxrpc_process_event(conn, skb, &abort_code);
                switch (ret) {
                case -EPROTO:
@@ -484,7 +484,7 @@ void rxrpc_process_connection(struct work_struct *work)
                        goto requeue_and_leave;
                case -ECONNABORTED:
                default:
-                       rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+                       rxrpc_free_skb(skb, rxrpc_skb_freed);
                        break;
                }
        }
@@ -501,6 +501,6 @@ requeue_and_leave:
 protocol_error:
        if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
                goto requeue_and_leave;
-       rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+       rxrpc_free_skb(skb, rxrpc_skb_freed);
        goto out;
 }
index 434ef392212bcdc0b71c7961effadc9b5f4c0b6d..ed05b692213226e7494c3908caa4dcf44f39bf27 100644 (file)
@@ -398,7 +398,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
                if (conn->state == RXRPC_CONN_SERVICE_PREALLOC)
                        continue;
 
-               if (rxnet->live) {
+               if (rxnet->live && !conn->params.local->dead) {
                        idle_timestamp = READ_ONCE(conn->idle_timestamp);
                        expire_at = idle_timestamp + rxrpc_connection_expiry * HZ;
                        if (conn->params.local->service_closed)
index 5bd6f1546e5c6d1cbcdb30881675ceefab01c5b3..157be1ff8697be438a7ee6636e37671169fff3df 100644 (file)
@@ -196,15 +196,14 @@ send_extra_data:
  * Ping the other end to fill our RTT cache and to retrieve the rwind
  * and MTU parameters.
  */
-static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
-                           int skew)
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        ktime_t now = skb->tstamp;
 
        if (call->peer->rtt_usage < 3 ||
            ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now))
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
                                  true, true,
                                  rxrpc_propose_ack_ping_for_params);
 }
@@ -234,7 +233,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
                ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK;
                skb = call->rxtx_buffer[ix];
                annotation = call->rxtx_annotations[ix];
-               rxrpc_see_skb(skb, rxrpc_skb_tx_rotated);
+               rxrpc_see_skb(skb, rxrpc_skb_rotated);
                call->rxtx_buffer[ix] = NULL;
                call->rxtx_annotations[ix] = 0;
                skb->next = list;
@@ -259,7 +258,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
                skb = list;
                list = skb->next;
                skb_mark_not_on_list(skb);
-               rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
        }
 
        return rot_last;
@@ -348,7 +347,7 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
 }
 
 /*
- * Scan a jumbo packet to validate its structure and to work out how many
+ * Scan a data packet to validate its structure and to work out how many
  * subpackets it contains.
  *
  * A jumbo packet is a collection of consecutive packets glued together with
@@ -359,16 +358,21 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
  * the last are RXRPC_JUMBO_DATALEN in size.  The last subpacket may be of any
  * size.
  */
-static bool rxrpc_validate_jumbo(struct sk_buff *skb)
+static bool rxrpc_validate_data(struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        unsigned int offset = sizeof(struct rxrpc_wire_header);
        unsigned int len = skb->len;
-       int nr_jumbo = 1;
        u8 flags = sp->hdr.flags;
 
-       do {
-               nr_jumbo++;
+       for (;;) {
+               if (flags & RXRPC_REQUEST_ACK)
+                       __set_bit(sp->nr_subpackets, sp->rx_req_ack);
+               sp->nr_subpackets++;
+
+               if (!(flags & RXRPC_JUMBO_PACKET))
+                       break;
+
                if (len - offset < RXRPC_JUMBO_SUBPKTLEN)
                        goto protocol_error;
                if (flags & RXRPC_LAST_PACKET)
@@ -377,9 +381,10 @@ static bool rxrpc_validate_jumbo(struct sk_buff *skb)
                if (skb_copy_bits(skb, offset, &flags, 1) < 0)
                        goto protocol_error;
                offset += sizeof(struct rxrpc_jumbo_header);
-       } while (flags & RXRPC_JUMBO_PACKET);
+       }
 
-       sp->nr_jumbo = nr_jumbo;
+       if (flags & RXRPC_LAST_PACKET)
+               sp->rx_flags |= RXRPC_SKB_INCL_LAST;
        return true;
 
 protocol_error:
@@ -400,10 +405,10 @@ protocol_error:
  * (that information is encoded in the ACK packet).
  */
 static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
-                                u8 annotation, bool *_jumbo_bad)
+                                bool is_jumbo, bool *_jumbo_bad)
 {
        /* Discard normal packets that are duplicates. */
-       if (annotation == 0)
+       if (is_jumbo)
                return;
 
        /* Skip jumbo subpackets that are duplicates.  When we've had three or
@@ -417,30 +422,30 @@ static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
 }
 
 /*
- * Process a DATA packet, adding the packet to the Rx ring.
+ * Process a DATA packet, adding the packet to the Rx ring.  The caller's
+ * packet ref must be passed on or discarded.
  */
-static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
-                            u16 skew)
+static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        enum rxrpc_call_state state;
-       unsigned int offset = sizeof(struct rxrpc_wire_header);
-       unsigned int ix;
+       unsigned int j;
        rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
-       rxrpc_seq_t seq = sp->hdr.seq, hard_ack;
-       bool immediate_ack = false, jumbo_bad = false, queued;
-       u16 len;
-       u8 ack = 0, flags, annotation = 0;
+       rxrpc_seq_t seq0 = sp->hdr.seq, hard_ack;
+       bool immediate_ack = false, jumbo_bad = false;
+       u8 ack = 0;
 
        _enter("{%u,%u},{%u,%u}",
-              call->rx_hard_ack, call->rx_top, skb->len, seq);
+              call->rx_hard_ack, call->rx_top, skb->len, seq0);
 
-       _proto("Rx DATA %%%u { #%u f=%02x }",
-              sp->hdr.serial, seq, sp->hdr.flags);
+       _proto("Rx DATA %%%u { #%u f=%02x n=%u }",
+              sp->hdr.serial, seq0, sp->hdr.flags, sp->nr_subpackets);
 
        state = READ_ONCE(call->state);
-       if (state >= RXRPC_CALL_COMPLETE)
+       if (state >= RXRPC_CALL_COMPLETE) {
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
                return;
+       }
 
        if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
                unsigned long timo = READ_ONCE(call->next_req_timo);
@@ -465,156 +470,157 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
            !rxrpc_receiving_reply(call))
                goto unlock;
 
-       call->ackr_prev_seq = seq;
-
+       call->ackr_prev_seq = seq0;
        hard_ack = READ_ONCE(call->rx_hard_ack);
-       if (after(seq, hard_ack + call->rx_winsize)) {
-               ack = RXRPC_ACK_EXCEEDS_WINDOW;
-               ack_serial = serial;
-               goto ack;
-       }
 
-       flags = sp->hdr.flags;
-       if (flags & RXRPC_JUMBO_PACKET) {
+       if (sp->nr_subpackets > 1) {
                if (call->nr_jumbo_bad > 3) {
                        ack = RXRPC_ACK_NOSPACE;
                        ack_serial = serial;
                        goto ack;
                }
-               annotation = 1;
        }
 
-next_subpacket:
-       queued = false;
-       ix = seq & RXRPC_RXTX_BUFF_MASK;
-       len = skb->len;
-       if (flags & RXRPC_JUMBO_PACKET)
-               len = RXRPC_JUMBO_DATALEN;
-
-       if (flags & RXRPC_LAST_PACKET) {
-               if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
-                   seq != call->rx_top) {
-                       rxrpc_proto_abort("LSN", call, seq);
-                       goto unlock;
-               }
-       } else {
-               if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
-                   after_eq(seq, call->rx_top)) {
-                       rxrpc_proto_abort("LSA", call, seq);
-                       goto unlock;
+       for (j = 0; j < sp->nr_subpackets; j++) {
+               rxrpc_serial_t serial = sp->hdr.serial + j;
+               rxrpc_seq_t seq = seq0 + j;
+               unsigned int ix = seq & RXRPC_RXTX_BUFF_MASK;
+               bool terminal = (j == sp->nr_subpackets - 1);
+               bool last = terminal && (sp->rx_flags & RXRPC_SKB_INCL_LAST);
+               u8 flags, annotation = j;
+
+               _proto("Rx DATA+%u %%%u { #%x t=%u l=%u }",
+                    j, serial, seq, terminal, last);
+
+               if (last) {
+                       if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
+                           seq != call->rx_top) {
+                               rxrpc_proto_abort("LSN", call, seq);
+                               goto unlock;
+                       }
+               } else {
+                       if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
+                           after_eq(seq, call->rx_top)) {
+                               rxrpc_proto_abort("LSA", call, seq);
+                               goto unlock;
+                       }
                }
-       }
-
-       trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
-       if (before_eq(seq, hard_ack)) {
-               ack = RXRPC_ACK_DUPLICATE;
-               ack_serial = serial;
-               goto skip;
-       }
 
-       if (flags & RXRPC_REQUEST_ACK && !ack) {
-               ack = RXRPC_ACK_REQUESTED;
-               ack_serial = serial;
-       }
+               flags = 0;
+               if (last)
+                       flags |= RXRPC_LAST_PACKET;
+               if (!terminal)
+                       flags |= RXRPC_JUMBO_PACKET;
+               if (test_bit(j, sp->rx_req_ack))
+                       flags |= RXRPC_REQUEST_ACK;
+               trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
 
-       if (call->rxtx_buffer[ix]) {
-               rxrpc_input_dup_data(call, seq, annotation, &jumbo_bad);
-               if (ack != RXRPC_ACK_DUPLICATE) {
+               if (before_eq(seq, hard_ack)) {
                        ack = RXRPC_ACK_DUPLICATE;
                        ack_serial = serial;
+                       continue;
                }
-               immediate_ack = true;
-               goto skip;
-       }
-
-       /* Queue the packet.  We use a couple of memory barriers here as need
-        * to make sure that rx_top is perceived to be set after the buffer
-        * pointer and that the buffer pointer is set after the annotation and
-        * the skb data.
-        *
-        * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
-        * and also rxrpc_fill_out_ack().
-        */
-       rxrpc_get_skb(skb, rxrpc_skb_rx_got);
-       call->rxtx_annotations[ix] = annotation;
-       smp_wmb();
-       call->rxtx_buffer[ix] = skb;
-       if (after(seq, call->rx_top)) {
-               smp_store_release(&call->rx_top, seq);
-       } else if (before(seq, call->rx_top)) {
-               /* Send an immediate ACK if we fill in a hole */
-               if (!ack) {
-                       ack = RXRPC_ACK_DELAY;
-                       ack_serial = serial;
-               }
-               immediate_ack = true;
-       }
-       if (flags & RXRPC_LAST_PACKET) {
-               set_bit(RXRPC_CALL_RX_LAST, &call->flags);
-               trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq);
-       } else {
-               trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq);
-       }
-       queued = true;
 
-       if (after_eq(seq, call->rx_expect_next)) {
-               if (after(seq, call->rx_expect_next)) {
-                       _net("OOS %u > %u", seq, call->rx_expect_next);
-                       ack = RXRPC_ACK_OUT_OF_SEQUENCE;
-                       ack_serial = serial;
+               if (call->rxtx_buffer[ix]) {
+                       rxrpc_input_dup_data(call, seq, sp->nr_subpackets > 1,
+                                            &jumbo_bad);
+                       if (ack != RXRPC_ACK_DUPLICATE) {
+                               ack = RXRPC_ACK_DUPLICATE;
+                               ack_serial = serial;
+                       }
+                       immediate_ack = true;
+                       continue;
                }
-               call->rx_expect_next = seq + 1;
-       }
 
-skip:
-       offset += len;
-       if (flags & RXRPC_JUMBO_PACKET) {
-               if (skb_copy_bits(skb, offset, &flags, 1) < 0) {
-                       rxrpc_proto_abort("XJF", call, seq);
-                       goto unlock;
-               }
-               offset += sizeof(struct rxrpc_jumbo_header);
-               seq++;
-               serial++;
-               annotation++;
-               if (flags & RXRPC_JUMBO_PACKET)
-                       annotation |= RXRPC_RX_ANNO_JLAST;
                if (after(seq, hard_ack + call->rx_winsize)) {
                        ack = RXRPC_ACK_EXCEEDS_WINDOW;
                        ack_serial = serial;
-                       if (!jumbo_bad) {
-                               call->nr_jumbo_bad++;
-                               jumbo_bad = true;
+                       if (flags & RXRPC_JUMBO_PACKET) {
+                               if (!jumbo_bad) {
+                                       call->nr_jumbo_bad++;
+                                       jumbo_bad = true;
+                               }
                        }
+
                        goto ack;
                }
 
-               _proto("Rx DATA Jumbo %%%u", serial);
-               goto next_subpacket;
-       }
+               if (flags & RXRPC_REQUEST_ACK && !ack) {
+                       ack = RXRPC_ACK_REQUESTED;
+                       ack_serial = serial;
+               }
+
+               /* Queue the packet.  We use a couple of memory barriers here as need
+                * to make sure that rx_top is perceived to be set after the buffer
+                * pointer and that the buffer pointer is set after the annotation and
+                * the skb data.
+                *
+                * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
+                * and also rxrpc_fill_out_ack().
+                */
+               if (!terminal)
+                       rxrpc_get_skb(skb, rxrpc_skb_got);
+               call->rxtx_annotations[ix] = annotation;
+               smp_wmb();
+               call->rxtx_buffer[ix] = skb;
+               if (after(seq, call->rx_top)) {
+                       smp_store_release(&call->rx_top, seq);
+               } else if (before(seq, call->rx_top)) {
+                       /* Send an immediate ACK if we fill in a hole */
+                       if (!ack) {
+                               ack = RXRPC_ACK_DELAY;
+                               ack_serial = serial;
+                       }
+                       immediate_ack = true;
+               }
 
-       if (queued && flags & RXRPC_LAST_PACKET && !ack) {
-               ack = RXRPC_ACK_DELAY;
-               ack_serial = serial;
+               if (terminal) {
+                       /* From this point on, we're not allowed to touch the
+                        * packet any longer as its ref now belongs to the Rx
+                        * ring.
+                        */
+                       skb = NULL;
+               }
+
+               if (last) {
+                       set_bit(RXRPC_CALL_RX_LAST, &call->flags);
+                       if (!ack) {
+                               ack = RXRPC_ACK_DELAY;
+                               ack_serial = serial;
+                       }
+                       trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq);
+               } else {
+                       trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq);
+               }
+
+               if (after_eq(seq, call->rx_expect_next)) {
+                       if (after(seq, call->rx_expect_next)) {
+                               _net("OOS %u > %u", seq, call->rx_expect_next);
+                               ack = RXRPC_ACK_OUT_OF_SEQUENCE;
+                               ack_serial = serial;
+                       }
+                       call->rx_expect_next = seq + 1;
+               }
        }
 
 ack:
        if (ack)
-               rxrpc_propose_ACK(call, ack, skew, ack_serial,
+               rxrpc_propose_ACK(call, ack, ack_serial,
                                  immediate_ack, true,
                                  rxrpc_propose_ack_input_data);
        else
-               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, skew, serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
                                  false, true,
                                  rxrpc_propose_ack_input_data);
 
-       if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1) {
+       if (seq0 == READ_ONCE(call->rx_hard_ack) + 1) {
                trace_rxrpc_notify_socket(call->debug_id, serial);
                rxrpc_notify_socket(call);
        }
 
 unlock:
        spin_unlock(&call->input_lock);
+       rxrpc_free_skb(skb, rxrpc_skb_freed);
        _leave(" [queued]");
 }
 
@@ -822,8 +828,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
  * soft-ACK means that the packet may be discarded and retransmission
  * requested.  A phase is complete when all packets are hard-ACK'd.
  */
-static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
-                           u16 skew)
+static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_ack_summary summary = { 0 };
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
@@ -867,11 +872,11 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
        if (buf.ack.reason == RXRPC_ACK_PING) {
                _proto("Rx ACK %%%u PING Request", sp->hdr.serial);
                rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
-                                 skew, sp->hdr.serial, true, true,
+                                 sp->hdr.serial, true, true,
                                  rxrpc_propose_ack_respond_to_ping);
        } else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
                rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED,
-                                 skew, sp->hdr.serial, true, true,
+                                 sp->hdr.serial, true, true,
                                  rxrpc_propose_ack_respond_to_ack);
        }
 
@@ -948,7 +953,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
            RXRPC_TX_ANNO_LAST &&
            summary.nr_acks == call->tx_top - hard_ack &&
            rxrpc_is_client_call(call))
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
                                  false, true,
                                  rxrpc_propose_ack_ping_for_lost_reply);
 
@@ -1004,7 +1009,7 @@ static void rxrpc_input_abort(struct rxrpc_call *call, struct sk_buff *skb)
  * Process an incoming call packet.
  */
 static void rxrpc_input_call_packet(struct rxrpc_call *call,
-                                   struct sk_buff *skb, u16 skew)
+                                   struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        unsigned long timo;
@@ -1023,11 +1028,11 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
 
        switch (sp->hdr.type) {
        case RXRPC_PACKET_TYPE_DATA:
-               rxrpc_input_data(call, skb, skew);
-               break;
+               rxrpc_input_data(call, skb);
+               goto no_free;
 
        case RXRPC_PACKET_TYPE_ACK:
-               rxrpc_input_ack(call, skb, skew);
+               rxrpc_input_ack(call, skb);
                break;
 
        case RXRPC_PACKET_TYPE_BUSY:
@@ -1051,6 +1056,8 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
                break;
        }
 
+       rxrpc_free_skb(skb, rxrpc_skb_freed);
+no_free:
        _leave("");
 }
 
@@ -1108,8 +1115,12 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local,
 {
        _enter("%p,%p", local, skb);
 
-       skb_queue_tail(&local->event_queue, skb);
-       rxrpc_queue_local(local);
+       if (rxrpc_get_local_maybe(local)) {
+               skb_queue_tail(&local->event_queue, skb);
+               rxrpc_queue_local(local);
+       } else {
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
+       }
 }
 
 /*
@@ -1119,8 +1130,12 @@ static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
 {
        CHECK_SLAB_OKAY(&local->usage);
 
-       skb_queue_tail(&local->reject_queue, skb);
-       rxrpc_queue_local(local);
+       if (rxrpc_get_local_maybe(local)) {
+               skb_queue_tail(&local->reject_queue, skb);
+               rxrpc_queue_local(local);
+       } else {
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
+       }
 }
 
 /*
@@ -1173,7 +1188,6 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
        struct rxrpc_peer *peer = NULL;
        struct rxrpc_sock *rx = NULL;
        unsigned int channel;
-       int skew = 0;
 
        _enter("%p", udp_sk);
 
@@ -1184,7 +1198,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
        if (skb->tstamp == 0)
                skb->tstamp = ktime_get_real();
 
-       rxrpc_new_skb(skb, rxrpc_skb_rx_received);
+       rxrpc_new_skb(skb, rxrpc_skb_received);
 
        skb_pull(skb, sizeof(struct udphdr));
 
@@ -1201,7 +1215,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                static int lose;
                if ((lose++ & 7) == 7) {
                        trace_rxrpc_rx_lose(sp);
-                       rxrpc_free_skb(skb, rxrpc_skb_rx_lost);
+                       rxrpc_free_skb(skb, rxrpc_skb_lost);
                        return 0;
                }
        }
@@ -1233,9 +1247,26 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                if (sp->hdr.callNumber == 0 ||
                    sp->hdr.seq == 0)
                        goto bad_message;
-               if (sp->hdr.flags & RXRPC_JUMBO_PACKET &&
-                   !rxrpc_validate_jumbo(skb))
+               if (!rxrpc_validate_data(skb))
                        goto bad_message;
+
+               /* Unshare the packet so that it can be modified for in-place
+                * decryption.
+                */
+               if (sp->hdr.securityIndex != 0) {
+                       struct sk_buff *nskb = skb_unshare(skb, GFP_ATOMIC);
+                       if (!nskb) {
+                               rxrpc_eaten_skb(skb, rxrpc_skb_unshared_nomem);
+                               goto out;
+                       }
+
+                       if (nskb != skb) {
+                               rxrpc_eaten_skb(skb, rxrpc_skb_received);
+                               skb = nskb;
+                               rxrpc_new_skb(skb, rxrpc_skb_unshared);
+                               sp = rxrpc_skb(skb);
+                       }
+               }
                break;
 
        case RXRPC_PACKET_TYPE_CHALLENGE:
@@ -1301,15 +1332,8 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                        goto out;
                }
 
-               /* Note the serial number skew here */
-               skew = (int)sp->hdr.serial - (int)conn->hi_serial;
-               if (skew >= 0) {
-                       if (skew > 0)
-                               conn->hi_serial = sp->hdr.serial;
-               } else {
-                       skew = -skew;
-                       skew = min(skew, 65535);
-               }
+               if ((int)sp->hdr.serial - (int)conn->hi_serial > 0)
+                       conn->hi_serial = sp->hdr.serial;
 
                /* Call-bound packets are routed by connection channel. */
                channel = sp->hdr.cid & RXRPC_CHANNELMASK;
@@ -1372,15 +1396,18 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                call = rxrpc_new_incoming_call(local, rx, skb);
                if (!call)
                        goto reject_packet;
-               rxrpc_send_ping(call, skb, skew);
+               rxrpc_send_ping(call, skb);
                mutex_unlock(&call->user_mutex);
        }
 
-       rxrpc_input_call_packet(call, skb, skew);
-       goto discard;
+       /* Process a call packet; this either discards or passes on the ref
+        * elsewhere.
+        */
+       rxrpc_input_call_packet(call, skb);
+       goto out;
 
 discard:
-       rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+       rxrpc_free_skb(skb, rxrpc_skb_freed);
 out:
        trace_rxrpc_rx_done(0, 0);
        return 0;
index e93a78f7c05e274ae279dddabcd8bfc8d957dff2..3ce6d628cd759d58c036e2ad3be257b4af9bb5fe 100644 (file)
@@ -90,7 +90,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local)
        if (skb) {
                struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 
-               rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+               rxrpc_see_skb(skb, rxrpc_skb_seen);
                _debug("{%d},{%u}", local->debug_id, sp->hdr.type);
 
                switch (sp->hdr.type) {
@@ -108,7 +108,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local)
                        break;
                }
 
-               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
        }
 
        _leave("");
index b1c71bad510b7c0200b2efed2a1652ecf254ca67..36587260cabd99b280372b9fe0fda70e300bae44 100644 (file)
@@ -79,6 +79,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
        local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL);
        if (local) {
                atomic_set(&local->usage, 1);
+               atomic_set(&local->active_users, 1);
                local->rxnet = rxnet;
                INIT_LIST_HEAD(&local->link);
                INIT_WORK(&local->processor, rxrpc_local_processor);
@@ -92,7 +93,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
                local->debug_id = atomic_inc_return(&rxrpc_debug_id);
                memcpy(&local->srx, srx, sizeof(*srx));
                local->srx.srx_service = 0;
-               trace_rxrpc_local(local, rxrpc_local_new, 1, NULL);
+               trace_rxrpc_local(local->debug_id, rxrpc_local_new, 1, NULL);
        }
 
        _leave(" = %p", local);
@@ -266,11 +267,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
                 * bind the transport socket may still fail if we're attempting
                 * to use a local address that the dying object is still using.
                 */
-               if (!rxrpc_get_local_maybe(local)) {
-                       cursor = cursor->next;
-                       list_del_init(&local->link);
+               if (!rxrpc_use_local(local))
                        break;
-               }
 
                age = "old";
                goto found;
@@ -284,7 +282,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
        if (ret < 0)
                goto sock_error;
 
-       list_add_tail(&local->link, cursor);
+       if (cursor != &rxnet->local_endpoints)
+               list_replace_init(cursor, &local->link);
+       else
+               list_add_tail(&local->link, cursor);
        age = "new";
 
 found:
@@ -320,7 +321,7 @@ struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local)
        int n;
 
        n = atomic_inc_return(&local->usage);
-       trace_rxrpc_local(local, rxrpc_local_got, n, here);
+       trace_rxrpc_local(local->debug_id, rxrpc_local_got, n, here);
        return local;
 }
 
@@ -334,7 +335,8 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
        if (local) {
                int n = atomic_fetch_add_unless(&local->usage, 1, 0);
                if (n > 0)
-                       trace_rxrpc_local(local, rxrpc_local_got, n + 1, here);
+                       trace_rxrpc_local(local->debug_id, rxrpc_local_got,
+                                         n + 1, here);
                else
                        local = NULL;
        }
@@ -342,24 +344,18 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
 }
 
 /*
- * Queue a local endpoint.
+ * Queue a local endpoint and pass the caller's reference to the work item.
  */
 void rxrpc_queue_local(struct rxrpc_local *local)
 {
        const void *here = __builtin_return_address(0);
+       unsigned int debug_id = local->debug_id;
+       int n = atomic_read(&local->usage);
 
        if (rxrpc_queue_work(&local->processor))
-               trace_rxrpc_local(local, rxrpc_local_queued,
-                                 atomic_read(&local->usage), here);
-}
-
-/*
- * A local endpoint reached its end of life.
- */
-static void __rxrpc_put_local(struct rxrpc_local *local)
-{
-       _enter("%d", local->debug_id);
-       rxrpc_queue_work(&local->processor);
+               trace_rxrpc_local(debug_id, rxrpc_local_queued, n, here);
+       else
+               rxrpc_put_local(local);
 }
 
 /*
@@ -372,10 +368,47 @@ void rxrpc_put_local(struct rxrpc_local *local)
 
        if (local) {
                n = atomic_dec_return(&local->usage);
-               trace_rxrpc_local(local, rxrpc_local_put, n, here);
+               trace_rxrpc_local(local->debug_id, rxrpc_local_put, n, here);
 
                if (n == 0)
-                       __rxrpc_put_local(local);
+                       call_rcu(&local->rcu, rxrpc_local_rcu);
+       }
+}
+
+/*
+ * Start using a local endpoint.
+ */
+struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *local)
+{
+       unsigned int au;
+
+       local = rxrpc_get_local_maybe(local);
+       if (!local)
+               return NULL;
+
+       au = atomic_fetch_add_unless(&local->active_users, 1, 0);
+       if (au == 0) {
+               rxrpc_put_local(local);
+               return NULL;
+       }
+
+       return local;
+}
+
+/*
+ * Cease using a local endpoint.  Once the number of active users reaches 0, we
+ * start the closure of the transport in the work processor.
+ */
+void rxrpc_unuse_local(struct rxrpc_local *local)
+{
+       unsigned int au;
+
+       if (local) {
+               au = atomic_dec_return(&local->active_users);
+               if (au == 0)
+                       rxrpc_queue_local(local);
+               else
+                       rxrpc_put_local(local);
        }
 }
 
@@ -393,21 +426,14 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
 
        _enter("%d", local->debug_id);
 
-       /* We can get a race between an incoming call packet queueing the
-        * processor again and the work processor starting the destruction
-        * process which will shut down the UDP socket.
-        */
-       if (local->dead) {
-               _leave(" [already dead]");
-               return;
-       }
        local->dead = true;
 
        mutex_lock(&rxnet->local_mutex);
        list_del_init(&local->link);
        mutex_unlock(&rxnet->local_mutex);
 
-       ASSERT(RB_EMPTY_ROOT(&local->client_conns));
+       rxrpc_clean_up_local_conns(local);
+       rxrpc_service_connection_reaper(&rxnet->service_conn_reaper);
        ASSERT(!local->service);
 
        if (socket) {
@@ -422,13 +448,11 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
         */
        rxrpc_purge_queue(&local->reject_queue);
        rxrpc_purge_queue(&local->event_queue);
-
-       _debug("rcu local %d", local->debug_id);
-       call_rcu(&local->rcu, rxrpc_local_rcu);
 }
 
 /*
- * Process events on an endpoint
+ * Process events on an endpoint.  The work item carries a ref which
+ * we must release.
  */
 static void rxrpc_local_processor(struct work_struct *work)
 {
@@ -436,13 +460,15 @@ static void rxrpc_local_processor(struct work_struct *work)
                container_of(work, struct rxrpc_local, processor);
        bool again;
 
-       trace_rxrpc_local(local, rxrpc_local_processing,
+       trace_rxrpc_local(local->debug_id, rxrpc_local_processing,
                          atomic_read(&local->usage), NULL);
 
        do {
                again = false;
-               if (atomic_read(&local->usage) == 0)
-                       return rxrpc_local_destroyer(local);
+               if (atomic_read(&local->active_users) == 0) {
+                       rxrpc_local_destroyer(local);
+                       break;
+               }
 
                if (!skb_queue_empty(&local->reject_queue)) {
                        rxrpc_reject_packets(local);
@@ -454,6 +480,8 @@ static void rxrpc_local_processor(struct work_struct *work)
                        again = true;
                }
        } while (again);
+
+       rxrpc_put_local(local);
 }
 
 /*
index 948e3fe249ec905208dc6966e7ff56f994ae0bac..935bb60fff56a7899374bf47db09edfb27ba05aa 100644 (file)
@@ -87,7 +87,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
        *_top = top;
 
        pkt->ack.bufferSpace    = htons(8);
-       pkt->ack.maxSkew        = htons(call->ackr_skew);
+       pkt->ack.maxSkew        = htons(0);
        pkt->ack.firstPacket    = htonl(hard_ack + 1);
        pkt->ack.previousPacket = htonl(call->ackr_prev_seq);
        pkt->ack.serial         = htonl(serial);
@@ -228,7 +228,6 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
                        if (ping)
                                clear_bit(RXRPC_CALL_PINGING, &call->flags);
                        rxrpc_propose_ACK(call, pkt->ack.reason,
-                                         ntohs(pkt->ack.maxSkew),
                                          ntohl(pkt->ack.serial),
                                          false, true,
                                          rxrpc_propose_ack_retry_tx);
@@ -566,7 +565,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
        memset(&whdr, 0, sizeof(whdr));
 
        while ((skb = skb_dequeue(&local->reject_queue))) {
-               rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+               rxrpc_see_skb(skb, rxrpc_skb_seen);
                sp = rxrpc_skb(skb);
 
                switch (skb->mark) {
@@ -582,7 +581,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
                        ioc = 2;
                        break;
                default:
-                       rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+                       rxrpc_free_skb(skb, rxrpc_skb_freed);
                        continue;
                }
 
@@ -607,7 +606,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
                                                      rxrpc_tx_point_reject);
                }
 
-               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
        }
 
        _leave("");
index 9f2f45c09e58353d11e1b8abc9345209a92dc726..c97ebdc043e44525eaecdd54bc447c1895bdca74 100644 (file)
@@ -163,11 +163,11 @@ void rxrpc_error_report(struct sock *sk)
                _leave("UDP socket errqueue empty");
                return;
        }
-       rxrpc_new_skb(skb, rxrpc_skb_rx_received);
+       rxrpc_new_skb(skb, rxrpc_skb_received);
        serr = SKB_EXT_ERR(skb);
        if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) {
                _leave("UDP empty message");
-               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
                return;
        }
 
@@ -177,7 +177,7 @@ void rxrpc_error_report(struct sock *sk)
                peer = NULL;
        if (!peer) {
                rcu_read_unlock();
-               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
                _leave(" [no peer]");
                return;
        }
@@ -189,7 +189,7 @@ void rxrpc_error_report(struct sock *sk)
             serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
                rxrpc_adjust_mtu(peer, serr);
                rcu_read_unlock();
-               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+               rxrpc_free_skb(skb, rxrpc_skb_freed);
                rxrpc_put_peer(peer);
                _leave(" [MTU update]");
                return;
@@ -197,7 +197,7 @@ void rxrpc_error_report(struct sock *sk)
 
        rxrpc_store_error(peer, serr);
        rcu_read_unlock();
-       rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+       rxrpc_free_skb(skb, rxrpc_skb_freed);
        rxrpc_put_peer(peer);
 
        _leave("");
@@ -378,7 +378,7 @@ static void rxrpc_peer_keepalive_dispatch(struct rxrpc_net *rxnet,
                spin_lock_bh(&rxnet->peer_hash_lock);
                list_add_tail(&peer->keepalive_link,
                              &rxnet->peer_keepalive[slot & mask]);
-               rxrpc_put_peer(peer);
+               rxrpc_put_peer_locked(peer);
        }
 
        spin_unlock_bh(&rxnet->peer_hash_lock);
index 9d3ce81cf8ae899cd38c92a493b700d4d152f50a..9c3ac96f71cbf8202ccdeca3af388ad8a2ae08b3 100644 (file)
@@ -436,6 +436,24 @@ void rxrpc_put_peer(struct rxrpc_peer *peer)
        }
 }
 
+/*
+ * Drop a ref on a peer record where the caller already holds the
+ * peer_hash_lock.
+ */
+void rxrpc_put_peer_locked(struct rxrpc_peer *peer)
+{
+       const void *here = __builtin_return_address(0);
+       int n;
+
+       n = atomic_dec_return(&peer->usage);
+       trace_rxrpc_peer(peer, rxrpc_peer_put, n, here);
+       if (n == 0) {
+               hash_del_rcu(&peer->hash_link);
+               list_del_init(&peer->keepalive_link);
+               kfree_rcu(peer, rcu);
+       }
+}
+
 /*
  * Make sure all peer records have been discarded.
  */
index 99ce322d7caa0369ecd8905a0de53aac6b4a8909..49bb972539aa1c7534430f5d5362277ea203ddc2 100644 (file)
@@ -89,6 +89,15 @@ struct rxrpc_jumbo_header {
 #define RXRPC_JUMBO_DATALEN    1412    /* non-terminal jumbo packet data length */
 #define RXRPC_JUMBO_SUBPKTLEN  (RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header))
 
+/*
+ * The maximum number of subpackets that can possibly fit in a UDP packet is:
+ *
+ *     ((max_IP - IP_hdr - UDP_hdr) / RXRPC_JUMBO_SUBPKTLEN) + 1
+ *     = ((65535 - 28 - 28) / 1416) + 1
+ *     = 46 non-terminal packets and 1 terminal packet.
+ */
+#define RXRPC_MAX_NR_JUMBO     47
+
 /*****************************************************************************/
 /*
  * on-the-wire Rx ACK packet data payload
index 5abf46cf9e6c4fa0e0271a2acdb32e24b6385870..3b0becb1204156eff6753f2399ec09c40fd233b0 100644 (file)
@@ -141,7 +141,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
        ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
 
        if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
-               rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, false, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, serial, false, true,
                                  rxrpc_propose_ack_terminal_ack);
                //rxrpc_send_ack_packet(call, false, NULL);
        }
@@ -159,7 +159,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
                call->state = RXRPC_CALL_SERVER_ACK_REQUEST;
                call->expect_req_by = jiffies + MAX_JIFFY_OFFSET;
                write_unlock_bh(&call->state_lock);
-               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial, false, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, false, true,
                                  rxrpc_propose_ack_processing_op);
                break;
        default:
@@ -177,7 +177,8 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
        struct sk_buff *skb;
        rxrpc_serial_t serial;
        rxrpc_seq_t hard_ack, top;
-       u8 flags;
+       bool last = false;
+       u8 subpacket;
        int ix;
 
        _enter("%d", call->debug_id);
@@ -189,30 +190,32 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
        hard_ack++;
        ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
        skb = call->rxtx_buffer[ix];
-       rxrpc_see_skb(skb, rxrpc_skb_rx_rotated);
+       rxrpc_see_skb(skb, rxrpc_skb_rotated);
        sp = rxrpc_skb(skb);
-       flags = sp->hdr.flags;
-       serial = sp->hdr.serial;
-       if (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO)
-               serial += (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO) - 1;
+
+       subpacket = call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
+       serial = sp->hdr.serial + subpacket;
+
+       if (subpacket == sp->nr_subpackets - 1 &&
+           sp->rx_flags & RXRPC_SKB_INCL_LAST)
+               last = true;
 
        call->rxtx_buffer[ix] = NULL;
        call->rxtx_annotations[ix] = 0;
        /* Barrier against rxrpc_input_data(). */
        smp_store_release(&call->rx_hard_ack, hard_ack);
 
-       rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+       rxrpc_free_skb(skb, rxrpc_skb_freed);
 
-       _debug("%u,%u,%02x", hard_ack, top, flags);
        trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
-       if (flags & RXRPC_LAST_PACKET) {
+       if (last) {
                rxrpc_end_rx_phase(call, serial);
        } else {
                /* Check to see if there's an ACK that needs sending. */
                if (after_eq(hard_ack, call->ackr_consumed + 2) ||
                    after_eq(top, call->ackr_seen + 2) ||
                    (hard_ack == top && after(hard_ack, call->ackr_consumed)))
-                       rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial,
+                       rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
                                          true, true,
                                          rxrpc_propose_ack_rotate_rx);
                if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY)
@@ -233,18 +236,19 @@ static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        rxrpc_seq_t seq = sp->hdr.seq;
        u16 cksum = sp->hdr.cksum;
+       u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
 
        _enter("");
 
        /* For all but the head jumbo subpacket, the security checksum is in a
         * jumbo header immediately prior to the data.
         */
-       if ((annotation & RXRPC_RX_ANNO_JUMBO) > 1) {
+       if (subpacket > 0) {
                __be16 tmp;
                if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0)
                        BUG();
                cksum = ntohs(tmp);
-               seq += (annotation & RXRPC_RX_ANNO_JUMBO) - 1;
+               seq += subpacket;
        }
 
        return call->conn->security->verify_packet(call, skb, offset, len,
@@ -265,19 +269,18 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
                             u8 *_annotation,
                             unsigned int *_offset, unsigned int *_len)
 {
+       struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        unsigned int offset = sizeof(struct rxrpc_wire_header);
        unsigned int len;
        int ret;
        u8 annotation = *_annotation;
+       u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
 
        /* Locate the subpacket */
+       offset += subpacket * RXRPC_JUMBO_SUBPKTLEN;
        len = skb->len - offset;
-       if ((annotation & RXRPC_RX_ANNO_JUMBO) > 0) {
-               offset += (((annotation & RXRPC_RX_ANNO_JUMBO) - 1) *
-                          RXRPC_JUMBO_SUBPKTLEN);
-               len = (annotation & RXRPC_RX_ANNO_JLAST) ?
-                       skb->len - offset : RXRPC_JUMBO_SUBPKTLEN;
-       }
+       if (subpacket < sp->nr_subpackets - 1)
+               len = RXRPC_JUMBO_DATALEN;
 
        if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) {
                ret = rxrpc_verify_packet(call, skb, annotation, offset, len);
@@ -303,6 +306,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 {
        struct rxrpc_skb_priv *sp;
        struct sk_buff *skb;
+       rxrpc_serial_t serial;
        rxrpc_seq_t hard_ack, top, seq;
        size_t remain;
        bool last;
@@ -336,12 +340,15 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
                        break;
                }
                smp_rmb();
-               rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
+               rxrpc_see_skb(skb, rxrpc_skb_seen);
                sp = rxrpc_skb(skb);
 
-               if (!(flags & MSG_PEEK))
+               if (!(flags & MSG_PEEK)) {
+                       serial = sp->hdr.serial;
+                       serial += call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
                        trace_rxrpc_receive(call, rxrpc_receive_front,
-                                           sp->hdr.serial, seq);
+                                           serial, seq);
+               }
 
                if (msg)
                        sock_recv_timestamp(msg, sock->sk, skb);
index ae8cd8926456b51763e029ba541984ed9f663d06..c60c520fde7c0a57850d53886e0fce9fc622f58c 100644 (file)
@@ -187,10 +187,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
        struct rxrpc_skb_priv *sp;
        struct rxrpc_crypt iv;
        struct scatterlist sg[16];
-       struct sk_buff *trailer;
        unsigned int len;
        u16 check;
-       int nsg;
        int err;
 
        sp = rxrpc_skb(skb);
@@ -214,15 +212,14 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
        crypto_skcipher_encrypt(req);
 
        /* we want to encrypt the skbuff in-place */
-       nsg = skb_cow_data(skb, 0, &trailer);
-       err = -ENOMEM;
-       if (nsg < 0 || nsg > 16)
+       err = -EMSGSIZE;
+       if (skb_shinfo(skb)->nr_frags > 16)
                goto out;
 
        len = data_size + call->conn->size_align - 1;
        len &= ~(call->conn->size_align - 1);
 
-       sg_init_table(sg, nsg);
+       sg_init_table(sg, ARRAY_SIZE(sg));
        err = skb_to_sgvec(skb, sg, 0, len);
        if (unlikely(err < 0))
                goto out;
@@ -319,11 +316,10 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
        struct rxkad_level1_hdr sechdr;
        struct rxrpc_crypt iv;
        struct scatterlist sg[16];
-       struct sk_buff *trailer;
        bool aborted;
        u32 data_size, buf;
        u16 check;
-       int nsg, ret;
+       int ret;
 
        _enter("");
 
@@ -336,11 +332,7 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
        /* Decrypt the skbuff in-place.  TODO: We really want to decrypt
         * directly into the target buffer.
         */
-       nsg = skb_cow_data(skb, 0, &trailer);
-       if (nsg < 0 || nsg > 16)
-               goto nomem;
-
-       sg_init_table(sg, nsg);
+       sg_init_table(sg, ARRAY_SIZE(sg));
        ret = skb_to_sgvec(skb, sg, offset, 8);
        if (unlikely(ret < 0))
                return ret;
@@ -388,10 +380,6 @@ protocol_error:
        if (aborted)
                rxrpc_send_abort_packet(call);
        return -EPROTO;
-
-nomem:
-       _leave(" = -ENOMEM");
-       return -ENOMEM;
 }
 
 /*
@@ -406,7 +394,6 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
        struct rxkad_level2_hdr sechdr;
        struct rxrpc_crypt iv;
        struct scatterlist _sg[4], *sg;
-       struct sk_buff *trailer;
        bool aborted;
        u32 data_size, buf;
        u16 check;
@@ -423,12 +410,11 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
        /* Decrypt the skbuff in-place.  TODO: We really want to decrypt
         * directly into the target buffer.
         */
-       nsg = skb_cow_data(skb, 0, &trailer);
-       if (nsg < 0)
-               goto nomem;
-
        sg = _sg;
-       if (unlikely(nsg > 4)) {
+       nsg = skb_shinfo(skb)->nr_frags;
+       if (nsg <= 4) {
+               nsg = 4;
+       } else {
                sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO);
                if (!sg)
                        goto nomem;
index 5d3f33ce6d4100070dd348edc2018167fce921d3..6a1547b270fef519fc5c334ced74b728f6484d28 100644 (file)
@@ -176,7 +176,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
        skb->tstamp = ktime_get_real();
 
        ix = seq & RXRPC_RXTX_BUFF_MASK;
-       rxrpc_get_skb(skb, rxrpc_skb_tx_got);
+       rxrpc_get_skb(skb, rxrpc_skb_got);
        call->rxtx_annotations[ix] = annotation;
        smp_wmb();
        call->rxtx_buffer[ix] = skb;
@@ -226,6 +226,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
                        rxrpc_set_call_completion(call,
                                                  RXRPC_CALL_LOCAL_ERROR,
                                                  0, ret);
+                       rxrpc_notify_socket(call);
                        goto out;
                }
                _debug("need instant resend %d", ret);
@@ -247,7 +248,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
        }
 
 out:
-       rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+       rxrpc_free_skb(skb, rxrpc_skb_freed);
        _leave(" = %d", ret);
        return ret;
 }
@@ -288,7 +289,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 
        skb = call->tx_pending;
        call->tx_pending = NULL;
-       rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
+       rxrpc_see_skb(skb, rxrpc_skb_seen);
 
        copied = 0;
        do {
@@ -335,7 +336,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                        if (!skb)
                                goto maybe_error;
 
-                       rxrpc_new_skb(skb, rxrpc_skb_tx_new);
+                       sp = rxrpc_skb(skb);
+                       sp->rx_flags |= RXRPC_SKB_TX_BUFFER;
+                       rxrpc_new_skb(skb, rxrpc_skb_new);
 
                        _debug("ALLOC SEND %p", skb);
 
@@ -345,7 +348,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                        skb_reserve(skb, call->conn->security_size);
                        skb->len += call->conn->security_size;
 
-                       sp = rxrpc_skb(skb);
                        sp->remain = chunk;
                        if (sp->remain > skb_tailroom(skb))
                                sp->remain = skb_tailroom(skb);
@@ -438,7 +440,7 @@ out:
        return ret;
 
 call_terminated:
-       rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+       rxrpc_free_skb(skb, rxrpc_skb_freed);
        _leave(" = %d", call->error);
        return call->error;
 
index 9ad5045b7c2f34e2fea3d5541e53c3401e5ab3ad..0348d2bf6f7d8e85ea075c992a5b5368ca0362a0 100644 (file)
@@ -14,7 +14,8 @@
 #include <net/af_rxrpc.h>
 #include "ar-internal.h"
 
-#define select_skb_count(op) (op >= rxrpc_skb_tx_cleaned ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
+#define is_tx_skb(skb) (rxrpc_skb(skb)->rx_flags & RXRPC_SKB_TX_BUFFER)
+#define select_skb_count(skb) (is_tx_skb(skb) ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
 
 /*
  * Note the allocation or reception of a socket buffer.
@@ -22,8 +23,9 @@
 void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
        const void *here = __builtin_return_address(0);
-       int n = atomic_inc_return(select_skb_count(op));
-       trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+       int n = atomic_inc_return(select_skb_count(skb));
+       trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+                       rxrpc_skb(skb)->rx_flags, here);
 }
 
 /*
@@ -33,8 +35,9 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
        const void *here = __builtin_return_address(0);
        if (skb) {
-               int n = atomic_read(select_skb_count(op));
-               trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+               int n = atomic_read(select_skb_count(skb));
+               trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+                               rxrpc_skb(skb)->rx_flags, here);
        }
 }
 
@@ -44,11 +47,22 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
 {
        const void *here = __builtin_return_address(0);
-       int n = atomic_inc_return(select_skb_count(op));
-       trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+       int n = atomic_inc_return(select_skb_count(skb));
+       trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+                       rxrpc_skb(skb)->rx_flags, here);
        skb_get(skb);
 }
 
+/*
+ * Note the dropping of a ref on a socket buffer by the core.
+ */
+void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
+{
+       const void *here = __builtin_return_address(0);
+       int n = atomic_inc_return(&rxrpc_n_rx_skbs);
+       trace_rxrpc_skb(skb, op, 0, n, 0, here);
+}
+
 /*
  * Note the destruction of a socket buffer.
  */
@@ -58,8 +72,9 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
        if (skb) {
                int n;
                CHECK_SLAB_OKAY(&skb->users);
-               n = atomic_dec_return(select_skb_count(op));
-               trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
+               n = atomic_dec_return(select_skb_count(skb));
+               trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
+                               rxrpc_skb(skb)->rx_flags, here);
                kfree_skb(skb);
        }
 }
@@ -72,9 +87,10 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
        const void *here = __builtin_return_address(0);
        struct sk_buff *skb;
        while ((skb = skb_dequeue((list))) != NULL) {
-               int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged));
-               trace_rxrpc_skb(skb, rxrpc_skb_rx_purged,
-                               refcount_read(&skb->users), n, here);
+               int n = atomic_dec_return(select_skb_count(skb));
+               trace_rxrpc_skb(skb, rxrpc_skb_purged,
+                               refcount_read(&skb->users), n,
+                               rxrpc_skb(skb)->rx_flags, here);
                kfree_skb(skb);
        }
 }
index 8126b26f125e019e3b5a16b632e2f7414498bfe4..04b7bd4ec7513c2388275ee5ed1af18b8585a32b 100644 (file)
@@ -285,6 +285,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
        struct tcf_bpf *prog;
        bool is_bpf, is_ebpf;
        int ret, res = 0;
+       u32 index;
 
        if (!nla)
                return -EINVAL;
@@ -298,13 +299,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
-
-       ret = tcf_idr_check_alloc(tn, &parm->index, act, bind);
+       index = parm->index;
+       ret = tcf_idr_check_alloc(tn, &index, act, bind);
        if (!ret) {
-               ret = tcf_idr_create(tn, parm->index, est, act,
+               ret = tcf_idr_create(tn, index, est, act,
                                     &act_bpf_ops, bind, true);
                if (ret < 0) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -421,7 +422,7 @@ static __net_init int bpf_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
-       return tc_action_net_init(tn, &act_bpf_ops);
+       return tc_action_net_init(net, tn, &act_bpf_ops);
 }
 
 static void __net_exit bpf_exit_net(struct list_head *net_list)
index ce36b0f7e1dc15379319858d5e5891d3417ca061..2b43cacf82af4aeaefdc41bf97651d832b1e31f1 100644 (file)
@@ -103,6 +103,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
        struct tcf_connmark_info *ci;
        struct tc_connmark *parm;
        int ret = 0, err;
+       u32 index;
 
        if (!nla)
                return -EINVAL;
@@ -116,13 +117,13 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_CONNMARK_PARMS]);
-
-       ret = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       ret = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!ret) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_connmark_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -230,7 +231,7 @@ static __net_init int connmark_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
-       return tc_action_net_init(tn, &act_connmark_ops);
+       return tc_action_net_init(net, tn, &act_connmark_ops);
 }
 
 static void __net_exit connmark_exit_net(struct list_head *net_list)
index 621fb22ce2a9297f6cab5fd1d675cc2fdd63aa73..d3cfad88dc3a93368449f2aa179f94c64b7a903c 100644 (file)
@@ -52,6 +52,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
        struct tc_csum *parm;
        struct tcf_csum *p;
        int ret = 0, err;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -64,13 +65,13 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
        if (tb[TCA_CSUM_PARMS] == NULL)
                return -EINVAL;
        parm = nla_data(tb[TCA_CSUM_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_csum_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
@@ -713,7 +714,7 @@ static __net_init int csum_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, csum_net_id);
 
-       return tc_action_net_init(tn, &act_csum_ops);
+       return tc_action_net_init(net, tn, &act_csum_ops);
 }
 
 static void __net_exit csum_exit_net(struct list_head *net_list)
index b501ce0cf11675c04c7840cb1d8d0b3ad5029498..cdd6f3818097842f247393e1a88626b6bef95be5 100644 (file)
@@ -666,6 +666,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
        struct tc_ct *parm;
        struct tcf_ct *c;
        int err, res = 0;
+       u32 index;
 
        if (!nla) {
                NL_SET_ERR_MSG_MOD(extack, "Ct requires attributes to be passed");
@@ -681,16 +682,16 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
        parm = nla_data(tb[TCA_CT_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
 
        if (!err) {
-               err = tcf_idr_create(tn, parm->index, est, a,
+               err = tcf_idr_create(tn, index, est, a,
                                     &act_ct_ops, bind, true);
                if (err) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return err;
                }
                res = ACT_P_CREATED;
@@ -938,7 +939,7 @@ static __net_init int ct_init_net(struct net *net)
                tn->labels = true;
        }
 
-       return tc_action_net_init(&tn->tn, &act_ct_ops);
+       return tc_action_net_init(net, &tn->tn, &act_ct_ops);
 }
 
 static void __net_exit ct_exit_net(struct list_head *net_list)
index 10eb2bb998617b38a71764aa307f024a7436f018..0dbcfd1dca7bf354a51892adeed5a5fc3b4889fd 100644 (file)
@@ -157,10 +157,10 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
                           struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
+       u32 dscpmask = 0, dscpstatemask, index;
        struct nlattr *tb[TCA_CTINFO_MAX + 1];
        struct tcf_ctinfo_params *cp_new;
        struct tcf_chain *goto_ch = NULL;
-       u32 dscpmask = 0, dscpstatemask;
        struct tc_ctinfo *actparm;
        struct tcf_ctinfo *ci;
        u8 dscpmaskshift;
@@ -206,12 +206,13 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
        }
 
        /* done the validation:now to the actual action allocation */
-       err = tcf_idr_check_alloc(tn, &actparm->index, a, bind);
+       index = actparm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, actparm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_ctinfo_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, actparm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
@@ -375,7 +376,7 @@ static __net_init int ctinfo_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
 
-       return tc_action_net_init(tn, &act_ctinfo_ops);
+       return tc_action_net_init(net, tn, &act_ctinfo_ops);
 }
 
 static void __net_exit ctinfo_exit_net(struct list_head *net_list)
index b2380c5284e6f5fbcdbb6a5f9a8e9f6b0ddc7394..324f1d1f6d477973596fe334ce682587610a30a7 100644 (file)
@@ -61,6 +61,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        struct tc_gact *parm;
        struct tcf_gact *gact;
        int ret = 0;
+       u32 index;
        int err;
 #ifdef CONFIG_GACT_PROB
        struct tc_gact_p *p_parm = NULL;
@@ -77,6 +78,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        if (tb[TCA_GACT_PARMS] == NULL)
                return -EINVAL;
        parm = nla_data(tb[TCA_GACT_PARMS]);
+       index = parm->index;
 
 #ifndef CONFIG_GACT_PROB
        if (tb[TCA_GACT_PROB] != NULL)
@@ -94,12 +96,12 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        }
 #endif
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_gact_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
@@ -276,7 +278,7 @@ static __net_init int gact_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, gact_net_id);
 
-       return tc_action_net_init(tn, &act_gact_ops);
+       return tc_action_net_init(net, tn, &act_gact_ops);
 }
 
 static void __net_exit gact_exit_net(struct list_head *net_list)
index 41d5398dd2f2ee79bc9fc203df86846bdce0f3a7..3a31e241c6472b42d37414f68ba18c16bd1a9f19 100644 (file)
@@ -479,8 +479,14 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        u8 *saddr = NULL;
        bool exists = false;
        int ret = 0;
+       u32 index;
        int err;
 
+       if (!nla) {
+               NL_SET_ERR_MSG_MOD(extack, "IFE requires attributes to be passed");
+               return -EINVAL;
+       }
+
        err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy,
                                          NULL);
        if (err < 0)
@@ -502,7 +508,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        if (!p)
                return -ENOMEM;
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0) {
                kfree(p);
                return err;
@@ -514,10 +521,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a, &act_ife_ops,
+               ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
                                     bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        kfree(p);
                        return ret;
                }
@@ -883,7 +890,7 @@ static __net_init int ife_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, ife_net_id);
 
-       return tc_action_net_init(tn, &act_ife_ops);
+       return tc_action_net_init(net, tn, &act_ife_ops);
 }
 
 static void __net_exit ife_exit_net(struct list_head *net_list)
index ce2c30a591d23572c947be16e6445168d230daa8..214a03d405cf9bb546903a12262a03a7d1843d0c 100644 (file)
@@ -61,12 +61,13 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t,
        return 0;
 }
 
-static void ipt_destroy_target(struct xt_entry_target *t)
+static void ipt_destroy_target(struct xt_entry_target *t, struct net *net)
 {
        struct xt_tgdtor_param par = {
                .target   = t->u.kernel.target,
                .targinfo = t->data,
                .family   = NFPROTO_IPV4,
+               .net      = net,
        };
        if (par.target->destroy != NULL)
                par.target->destroy(&par);
@@ -78,7 +79,7 @@ static void tcf_ipt_release(struct tc_action *a)
        struct tcf_ipt *ipt = to_ipt(a);
 
        if (ipt->tcfi_t) {
-               ipt_destroy_target(ipt->tcfi_t);
+               ipt_destroy_target(ipt->tcfi_t, a->idrinfo->net);
                kfree(ipt->tcfi_t);
        }
        kfree(ipt->tcfi_tname);
@@ -180,7 +181,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
 
        spin_lock_bh(&ipt->tcf_lock);
        if (ret != ACT_P_CREATED) {
-               ipt_destroy_target(ipt->tcfi_t);
+               ipt_destroy_target(ipt->tcfi_t, net);
                kfree(ipt->tcfi_tname);
                kfree(ipt->tcfi_t);
        }
@@ -350,7 +351,7 @@ static __net_init int ipt_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, ipt_net_id);
 
-       return tc_action_net_init(tn, &act_ipt_ops);
+       return tc_action_net_init(net, tn, &act_ipt_ops);
 }
 
 static void __net_exit ipt_exit_net(struct list_head *net_list)
@@ -399,7 +400,7 @@ static __net_init int xt_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, xt_net_id);
 
-       return tc_action_net_init(tn, &act_xt_ops);
+       return tc_action_net_init(net, tn, &act_xt_ops);
 }
 
 static void __net_exit xt_exit_net(struct list_head *net_list)
index 055faa298c8e90f5c9029735fa411d06308f5d10..9d1bf508075a8c789658ba7a08ac1c0a20cd63eb 100644 (file)
@@ -104,6 +104,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        struct net_device *dev;
        bool exists = false;
        int ret, err;
+       u32 index;
 
        if (!nla) {
                NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed");
@@ -118,8 +119,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
        parm = nla_data(tb[TCA_MIRRED_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -136,21 +137,21 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
                return -EINVAL;
        }
 
        if (!exists) {
                if (!parm->ifindex) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist");
                        return -EINVAL;
                }
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_mirred_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
@@ -452,7 +453,7 @@ static __net_init int mirred_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, mirred_net_id);
 
-       return tc_action_net_init(tn, &act_mirred_ops);
+       return tc_action_net_init(net, tn, &act_mirred_ops);
 }
 
 static void __net_exit mirred_exit_net(struct list_head *net_list)
index ca2597ce4ac9d9296e7c76ec2d9851310bf38004..e168df0e008acef81e579900602138b5da683111 100644 (file)
@@ -138,6 +138,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
        struct tcf_mpls *m;
        int ret = 0, err;
        u8 mpls_ttl = 0;
+       u32 index;
 
        if (!nla) {
                NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes");
@@ -153,6 +154,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
        parm = nla_data(tb[TCA_MPLS_PARMS]);
+       index = parm->index;
 
        /* Verify parameters against action type. */
        switch (parm->m_action) {
@@ -209,7 +211,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -217,10 +219,10 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
                return 0;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_mpls_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -373,7 +375,7 @@ static __net_init int mpls_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, mpls_net_id);
 
-       return tc_action_net_init(tn, &act_mpls_ops);
+       return tc_action_net_init(net, tn, &act_mpls_ops);
 }
 
 static void __net_exit mpls_exit_net(struct list_head *net_list)
index 45923ebb7a4fa3c103111b128274058ea088bee5..ea4c5359e7dfb5668dfc23ac4dfb95672f61304e 100644 (file)
@@ -44,6 +44,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        struct tc_nat *parm;
        int ret = 0, err;
        struct tcf_nat *p;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -56,13 +57,13 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        if (tb[TCA_NAT_PARMS] == NULL)
                return -EINVAL;
        parm = nla_data(tb[TCA_NAT_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_nat_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
@@ -326,7 +327,7 @@ static __net_init int nat_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, nat_net_id);
 
-       return tc_action_net_init(tn, &act_nat_ops);
+       return tc_action_net_init(net, tn, &act_nat_ops);
 }
 
 static void __net_exit nat_exit_net(struct list_head *net_list)
index 45e9d6bfddb3df539d9b76e7cc72e8e5e6b71e8a..cdfaa79382a22c63761cdb7507296946aac3cb12 100644 (file)
@@ -149,6 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
        struct tcf_pedit *p;
        int ret = 0, err;
        int ksize;
+       u32 index;
 
        if (!nla) {
                NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be passed");
@@ -179,18 +180,19 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
        if (IS_ERR(keys_ex))
                return PTR_ERR(keys_ex);
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
                if (!parm->nkeys) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
                        ret = -EINVAL;
                        goto out_free;
                }
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_pedit_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        goto out_free;
                }
                ret = ACT_P_CREATED;
@@ -496,7 +498,7 @@ static __net_init int pedit_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, pedit_net_id);
 
-       return tc_action_net_init(tn, &act_pedit_ops);
+       return tc_action_net_init(net, tn, &act_pedit_ops);
 }
 
 static void __net_exit pedit_exit_net(struct list_head *net_list)
index a065f62fa79c04e10442d870e6bb29523d216f36..6315e0f8d26e3abfb96101bec5f9048db9619c21 100644 (file)
@@ -57,6 +57,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
        struct tc_action_net *tn = net_generic(net, police_net_id);
        struct tcf_police_params *new;
        bool exists = false;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -73,7 +74,8 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_POLICE_TBF]);
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -81,10 +83,10 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
                return 0;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, NULL, a,
+               ret = tcf_idr_create(tn, index, NULL, a,
                                     &act_police_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
@@ -369,7 +371,7 @@ static __net_init int police_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, police_net_id);
 
-       return tc_action_net_init(tn, &act_police_ops);
+       return tc_action_net_init(net, tn, &act_police_ops);
 }
 
 static void __net_exit police_exit_net(struct list_head *net_list)
index 274d7a0c0e25c91186b5513715f7b87534d6476d..10229124a9924efda7745e5917a37fd5c6bff057 100644 (file)
@@ -41,8 +41,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
        struct tc_action_net *tn = net_generic(net, sample_net_id);
        struct nlattr *tb[TCA_SAMPLE_MAX + 1];
        struct psample_group *psample_group;
+       u32 psample_group_num, rate, index;
        struct tcf_chain *goto_ch = NULL;
-       u32 psample_group_num, rate;
        struct tc_sample *parm;
        struct tcf_sample *s;
        bool exists = false;
@@ -59,8 +59,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_SAMPLE_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -68,10 +68,10 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
                return 0;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_sample_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
@@ -102,13 +102,17 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
        goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
        s->rate = rate;
        s->psample_group_num = psample_group_num;
-       RCU_INIT_POINTER(s->psample_group, psample_group);
+       rcu_swap_protected(s->psample_group, psample_group,
+                          lockdep_is_held(&s->tcf_lock));
 
        if (tb[TCA_SAMPLE_TRUNC_SIZE]) {
                s->truncate = true;
                s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]);
        }
        spin_unlock_bh(&s->tcf_lock);
+
+       if (psample_group)
+               psample_group_put(psample_group);
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
@@ -265,7 +269,7 @@ static __net_init int sample_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, sample_net_id);
 
-       return tc_action_net_init(tn, &act_sample_ops);
+       return tc_action_net_init(net, tn, &act_sample_ops);
 }
 
 static void __net_exit sample_exit_net(struct list_head *net_list)
index f28ddbabff7604373bd9374fa283c07f9b3c01ed..6120e56117ca14d2abeb855e20beb33ae7cd9896 100644 (file)
@@ -95,6 +95,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
        struct tcf_defact *d;
        bool exists = false;
        int ret = 0, err;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -108,7 +109,8 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_DEF_PARMS]);
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -119,15 +121,15 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                return -EINVAL;
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_simp_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -230,7 +232,7 @@ static __net_init int simp_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, simp_net_id);
 
-       return tc_action_net_init(tn, &act_simp_ops);
+       return tc_action_net_init(net, tn, &act_simp_ops);
 }
 
 static void __net_exit simp_exit_net(struct list_head *net_list)
index 215a06705cef71d501faa5ecb3a97fbb2f51bfe7..6a8d3337c577493dc9dcc2b70e7946abbc165cfa 100644 (file)
@@ -99,6 +99,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        u16 *queue_mapping = NULL, *ptype = NULL;
        bool exists = false;
        int ret = 0, err;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -146,8 +147,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        }
 
        parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -158,15 +159,15 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                return -EINVAL;
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_skbedit_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -306,6 +307,17 @@ static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index)
        return tcf_idr_search(tn, a, index);
 }
 
+static size_t tcf_skbedit_get_fill_size(const struct tc_action *act)
+{
+       return nla_total_size(sizeof(struct tc_skbedit))
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_PRIORITY */
+               + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_QUEUE_MAPPING */
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MARK */
+               + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_PTYPE */
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MASK */
+               + nla_total_size_64bit(sizeof(u64)); /* TCA_SKBEDIT_FLAGS */
+}
+
 static struct tc_action_ops act_skbedit_ops = {
        .kind           =       "skbedit",
        .id             =       TCA_ID_SKBEDIT,
@@ -315,6 +327,7 @@ static struct tc_action_ops act_skbedit_ops = {
        .init           =       tcf_skbedit_init,
        .cleanup        =       tcf_skbedit_cleanup,
        .walk           =       tcf_skbedit_walker,
+       .get_fill_size  =       tcf_skbedit_get_fill_size,
        .lookup         =       tcf_skbedit_search,
        .size           =       sizeof(struct tcf_skbedit),
 };
@@ -323,7 +336,7 @@ static __net_init int skbedit_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, skbedit_net_id);
 
-       return tc_action_net_init(tn, &act_skbedit_ops);
+       return tc_action_net_init(net, tn, &act_skbedit_ops);
 }
 
 static void __net_exit skbedit_exit_net(struct list_head *net_list)
index 4f07706eff07ec7790c3bee295b893f1f2e6f720..888437f97ba62087992a6b19de615e859fd63563 100644 (file)
@@ -87,12 +87,12 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
        struct tcf_skbmod_params *p, *p_old;
        struct tcf_chain *goto_ch = NULL;
        struct tc_skbmod *parm;
+       u32 lflags = 0, index;
        struct tcf_skbmod *d;
        bool exists = false;
        u8 *daddr = NULL;
        u8 *saddr = NULL;
        u16 eth_type = 0;
-       u32 lflags = 0;
        int ret = 0, err;
 
        if (!nla)
@@ -122,10 +122,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
        }
 
        parm = nla_data(tb[TCA_SKBMOD_PARMS]);
+       index = parm->index;
        if (parm->flags & SKBMOD_F_SWAPMAC)
                lflags = SKBMOD_F_SWAPMAC;
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -136,15 +137,15 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                return -EINVAL;
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_skbmod_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -286,7 +287,7 @@ static __net_init int skbmod_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, skbmod_net_id);
 
-       return tc_action_net_init(tn, &act_skbmod_ops);
+       return tc_action_net_init(net, tn, &act_skbmod_ops);
 }
 
 static void __net_exit skbmod_exit_net(struct list_head *net_list)
index 10dffda1d5cc4d9d0236efaf713502a6367c1f92..2f83a79f76aae656fcea6f2d4a35d45c22e2a501 100644 (file)
@@ -225,6 +225,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        __be16 flags = 0;
        u8 tos, ttl;
        int ret = 0;
+       u32 index;
        int err;
 
        if (!nla) {
@@ -245,7 +246,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        }
 
        parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]);
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -345,7 +347,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_tunnel_key_ops, bind, true);
                if (ret) {
                        NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
@@ -403,7 +405,7 @@ err_out:
        if (exists)
                tcf_idr_release(*a, bind);
        else
-               tcf_idr_cleanup(tn, parm->index);
+               tcf_idr_cleanup(tn, index);
        return ret;
 }
 
@@ -598,7 +600,7 @@ static __net_init int tunnel_key_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
 
-       return tc_action_net_init(tn, &act_tunnel_key_ops);
+       return tc_action_net_init(net, tn, &act_tunnel_key_ops);
 }
 
 static void __net_exit tunnel_key_exit_net(struct list_head *net_list)
index 9269d350fb8aa0ae525cd89fa8d855b9be280731..287a30bf8930e130745c2ccca42f2949975f225d 100644 (file)
@@ -116,6 +116,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        u8 push_prio = 0;
        bool exists = false;
        int ret = 0, err;
+       u32 index;
 
        if (!nla)
                return -EINVAL;
@@ -128,7 +129,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        if (!tb[TCA_VLAN_PARMS])
                return -EINVAL;
        parm = nla_data(tb[TCA_VLAN_PARMS]);
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -144,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                        if (exists)
                                tcf_idr_release(*a, bind);
                        else
-                               tcf_idr_cleanup(tn, parm->index);
+                               tcf_idr_cleanup(tn, index);
                        return -EINVAL;
                }
                push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
@@ -152,7 +154,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                        if (exists)
                                tcf_idr_release(*a, bind);
                        else
-                               tcf_idr_cleanup(tn, parm->index);
+                               tcf_idr_cleanup(tn, index);
                        return -ERANGE;
                }
 
@@ -166,7 +168,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                                if (exists)
                                        tcf_idr_release(*a, bind);
                                else
-                                       tcf_idr_cleanup(tn, parm->index);
+                                       tcf_idr_cleanup(tn, index);
                                return -EPROTONOSUPPORT;
                        }
                } else {
@@ -180,16 +182,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                return -EINVAL;
        }
        action = parm->v_action;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_vlan_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -306,6 +308,14 @@ static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index)
        return tcf_idr_search(tn, a, index);
 }
 
+static size_t tcf_vlan_get_fill_size(const struct tc_action *act)
+{
+       return nla_total_size(sizeof(struct tc_vlan))
+               + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_ID */
+               + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_PROTOCOL */
+               + nla_total_size(sizeof(u8)); /* TCA_VLAN_PUSH_VLAN_PRIORITY */
+}
+
 static struct tc_action_ops act_vlan_ops = {
        .kind           =       "vlan",
        .id             =       TCA_ID_VLAN,
@@ -315,6 +325,7 @@ static struct tc_action_ops act_vlan_ops = {
        .init           =       tcf_vlan_init,
        .cleanup        =       tcf_vlan_cleanup,
        .walk           =       tcf_vlan_walker,
+       .get_fill_size  =       tcf_vlan_get_fill_size,
        .lookup         =       tcf_vlan_search,
        .size           =       sizeof(struct tcf_vlan),
 };
@@ -323,7 +334,7 @@ static __net_init int vlan_init_net(struct net *net)
 {
        struct tc_action_net *tn = net_generic(net, vlan_net_id);
 
-       return tc_action_net_init(tn, &act_vlan_ops);
+       return tc_action_net_init(net, tn, &act_vlan_ops);
 }
 
 static void __net_exit vlan_exit_net(struct list_head *net_list)
index d144233423c5c950feead4eeeaaf665f8d64ddc2..efd3cfb80a2ad775dc8ab3c4900bd73d52c7aaad 100644 (file)
@@ -691,6 +691,8 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
        if (!indr_dev->block)
                return;
 
+       bo.block = &indr_dev->block->flow_block;
+
        indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
                          &bo);
        tcf_block_setup(indr_dev->block, &bo);
@@ -775,6 +777,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
                .command        = command,
                .binder_type    = ei->binder_type,
                .net            = dev_net(dev),
+               .block          = &block->flow_block,
                .block_shared   = tcf_block_shared(block),
                .extack         = extack,
        };
@@ -810,6 +813,7 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
        bo.net = dev_net(dev);
        bo.command = command;
        bo.binder_type = ei->binder_type;
+       bo.block = &block->flow_block;
        bo.block_shared = tcf_block_shared(block);
        bo.extack = extack;
        INIT_LIST_HEAD(&bo.cb_list);
@@ -987,8 +991,8 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
                return ERR_PTR(-ENOMEM);
        }
        mutex_init(&block->lock);
+       flow_block_init(&block->flow_block);
        INIT_LIST_HEAD(&block->chain_list);
-       INIT_LIST_HEAD(&block->cb_list);
        INIT_LIST_HEAD(&block->owner_list);
        INIT_LIST_HEAD(&block->chain0.filter_chain_list);
 
@@ -1514,7 +1518,7 @@ void tcf_block_put(struct tcf_block *block)
 EXPORT_SYMBOL(tcf_block_put);
 
 static int
-tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
+tcf_block_playback_offloads(struct tcf_block *block, flow_setup_cb_t *cb,
                            void *cb_priv, bool add, bool offload_in_use,
                            struct netlink_ext_ack *extack)
 {
@@ -1570,7 +1574,7 @@ static int tcf_block_bind(struct tcf_block *block,
 
                i++;
        }
-       list_splice(&bo->cb_list, &block->cb_list);
+       list_splice(&bo->cb_list, &block->flow_block.cb_list);
 
        return 0;
 
@@ -2152,7 +2156,9 @@ replay:
                tfilter_notify(net, skb, n, tp, block, q, parent, fh,
                               RTM_NEWTFILTER, false, rtnl_held);
                tfilter_put(tp, fh);
-               q->flags &= ~TCQ_F_CAN_BYPASS;
+               /* q pointer is NULL for shared blocks */
+               if (q)
+                       q->flags &= ~TCQ_F_CAN_BYPASS;
        }
 
 errout:
@@ -3156,7 +3162,7 @@ int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
        if (block->nooffloaddevcnt && err_stop)
                return -EOPNOTSUPP;
 
-       list_for_each_entry(block_cb, &block->cb_list, list) {
+       list_for_each_entry(block_cb, &block->flow_block.cb_list, list) {
                err = block_cb->cb(type, type_data, block_cb->cb_priv);
                if (err) {
                        if (err_stop)
index 691f71830134be3c5dbb2921edf6e40c433048cf..3f7a9c02b70c570510fefae26a4b7fcedbabe432 100644 (file)
@@ -651,7 +651,7 @@ skip:
        }
 }
 
-static int cls_bpf_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
+static int cls_bpf_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                             void *cb_priv, struct netlink_ext_ack *extack)
 {
        struct cls_bpf_head *head = rtnl_dereference(tp->root);
index 38d6e85693fc83c1a88ed21a7d31950712642b66..054123742e323baa402798708a8ae98d73f68e5a 100644 (file)
@@ -1800,7 +1800,7 @@ fl_get_next_hw_filter(struct tcf_proto *tp, struct cls_fl_filter *f, bool add)
        return NULL;
 }
 
-static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
+static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                        void *cb_priv, struct netlink_ext_ack *extack)
 {
        struct tcf_block *block = tp->chain->block;
index a30d2f8feb32369da58dee646fb84c88b4ab3b18..455ea2793f9b37f9edb9a11754845c2b6d61dc39 100644 (file)
@@ -282,7 +282,7 @@ skip:
        arg->count++;
 }
 
-static int mall_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
+static int mall_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                          void *cb_priv, struct netlink_ext_ack *extack)
 {
        struct cls_mall_head *head = rtnl_dereference(tp->root);
index be9e46c77e8be66fc5fbbd1d8ba0c19e7234a4b3..8614088edd1be0cad1a9755ce11fac94304a65f0 100644 (file)
@@ -1152,7 +1152,7 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg,
 }
 
 static int u32_reoffload_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,
-                              bool add, tc_setup_cb_t *cb, void *cb_priv,
+                              bool add, flow_setup_cb_t *cb, void *cb_priv,
                               struct netlink_ext_ack *extack)
 {
        struct tc_cls_u32_offload cls_u32 = {};
@@ -1172,7 +1172,7 @@ static int u32_reoffload_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,
 }
 
 static int u32_reoffload_knode(struct tcf_proto *tp, struct tc_u_knode *n,
-                              bool add, tc_setup_cb_t *cb, void *cb_priv,
+                              bool add, flow_setup_cb_t *cb, void *cb_priv,
                               struct netlink_ext_ack *extack)
 {
        struct tc_u_hnode *ht = rtnl_dereference(n->ht_down);
@@ -1213,7 +1213,7 @@ static int u32_reoffload_knode(struct tcf_proto *tp, struct tc_u_knode *n,
        return 0;
 }
 
-static int u32_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
+static int u32_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                         void *cb_priv, struct netlink_ext_ack *extack)
 {
        struct tc_u_common *tp_c = tp->data;
index 04faee7ccbce64354618365b1c304d7c76f6bb06..1047825d9f48d546fe1339a25f3f86979e7ac801 100644 (file)
@@ -1920,6 +1920,8 @@ static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid,
        cl = cops->find(q, portid);
        if (!cl)
                return;
+       if (!cops->tcf_block)
+               return;
        block = cops->tcf_block(q, cl, NULL);
        if (!block)
                return;
index 732e109c305557f4dc365cd65feaacbbb72852eb..810645b5c086101622393d2a5ae44613ff14f1d6 100644 (file)
@@ -181,11 +181,6 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch)
        s64 credits;
        int len;
 
-       if (atomic64_read(&q->port_rate) == -1) {
-               WARN_ONCE(1, "cbs: dequeue() called with unknown port rate.");
-               return NULL;
-       }
-
        if (q->credits < 0) {
                credits = timediff_to_credits(now - q->last, q->idleslope);
 
@@ -303,11 +298,19 @@ static int cbs_enable_offload(struct net_device *dev, struct cbs_sched_data *q,
 static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q)
 {
        struct ethtool_link_ksettings ecmd;
+       int speed = SPEED_10;
        int port_rate = -1;
+       int err;
+
+       err = __ethtool_get_link_ksettings(dev, &ecmd);
+       if (err < 0)
+               goto skip;
+
+       if (ecmd.base.speed != SPEED_UNKNOWN)
+               speed = ecmd.base.speed;
 
-       if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
-           ecmd.base.speed != SPEED_UNKNOWN)
-               port_rate = ecmd.base.speed * 1000 * BYTES_PER_KBIT;
+skip:
+       port_rate = speed * 1000 * BYTES_PER_KBIT;
 
        atomic64_set(&q->port_rate, port_rate);
        netdev_dbg(dev, "cbs: set %s's port_rate to: %lld, linkspeed: %d\n",
index 25ef172c23dfa31d05729c76a58ade3bb4967d5e..30169b3adbbb064c51b6006755d56446570f974c 100644 (file)
@@ -71,10 +71,10 @@ static struct sk_buff *dequeue_func(struct codel_vars *vars, void *ctx)
        struct Qdisc *sch = ctx;
        struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
 
-       if (skb)
+       if (skb) {
                sch->qstats.backlog -= qdisc_pkt_len(skb);
-
-       prefetch(&skb->end); /* we'll need skb_shinfo() */
+               prefetch(&skb->end); /* we'll need skb_shinfo() */
+       }
        return skb;
 }
 
index 11c03cf4aa74b44663c74e0e3284140b0c75d9c4..ac28f6a5d70e0b38ae8ce7858f08e9d15778c22f 100644 (file)
@@ -46,6 +46,8 @@ EXPORT_SYMBOL(default_qdisc_ops);
  * - updates to tree and tree walking are only done under the rtnl mutex.
  */
 
+#define SKB_XOFF_MAGIC ((struct sk_buff *)1UL)
+
 static inline struct sk_buff *__skb_dequeue_bad_txq(struct Qdisc *q)
 {
        const struct netdev_queue *txq = q->dev_queue;
@@ -71,7 +73,7 @@ static inline struct sk_buff *__skb_dequeue_bad_txq(struct Qdisc *q)
                                q->q.qlen--;
                        }
                } else {
-                       skb = NULL;
+                       skb = SKB_XOFF_MAGIC;
                }
        }
 
@@ -253,8 +255,11 @@ validate:
                return skb;
 
        skb = qdisc_dequeue_skb_bad_txq(q);
-       if (unlikely(skb))
+       if (unlikely(skb)) {
+               if (skb == SKB_XOFF_MAGIC)
+                       return NULL;
                goto bulk;
+       }
        skb = q->dequeue(q);
        if (skb) {
 bulk:
@@ -624,8 +629,12 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc,
 
        err = skb_array_produce(q, skb);
 
-       if (unlikely(err))
-               return qdisc_drop_cpu(skb, qdisc, to_free);
+       if (unlikely(err)) {
+               if (qdisc_is_percpu_stats(qdisc))
+                       return qdisc_drop_cpu(skb, qdisc, to_free);
+               else
+                       return qdisc_drop(skb, qdisc, to_free);
+       }
 
        qdisc_update_stats_at_enqueue(qdisc, pkt_len);
        return NET_XMIT_SUCCESS;
@@ -688,11 +697,14 @@ static void pfifo_fast_reset(struct Qdisc *qdisc)
                        kfree_skb(skb);
        }
 
-       for_each_possible_cpu(i) {
-               struct gnet_stats_queue *q = per_cpu_ptr(qdisc->cpu_qstats, i);
+       if (qdisc_is_percpu_stats(qdisc)) {
+               for_each_possible_cpu(i) {
+                       struct gnet_stats_queue *q;
 
-               q->backlog = 0;
-               q->qlen = 0;
+                       q = per_cpu_ptr(qdisc->cpu_qstats, i);
+                       q->backlog = 0;
+                       q->qlen = 0;
+               }
        }
 }
 
index cee6971c1c8249a68dd6b953948fa1fef21fce04..23cd1c873a2cfc24b907a8177e71dd68b0939701 100644 (file)
@@ -531,7 +531,7 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt,
                new_hhf_non_hh_weight = nla_get_u32(tb[TCA_HHF_NON_HH_WEIGHT]);
 
        non_hh_quantum = (u64)new_quantum * new_hhf_non_hh_weight;
-       if (non_hh_quantum > INT_MAX)
+       if (non_hh_quantum == 0 || non_hh_quantum > INT_MAX)
                return -EINVAL;
 
        sch_tree_lock(sch);
index c39db507ba3f42234c14e4e24184909509b9e2e7..8d8bc2ec5cd6281d811fd5d8a5c5211ebb0edd73 100644 (file)
@@ -477,11 +477,6 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
        u32 gate_mask;
        int i;
 
-       if (atomic64_read(&q->picos_per_byte) == -1) {
-               WARN_ONCE(1, "taprio: dequeue() called with unknown picos per byte.");
-               return NULL;
-       }
-
        rcu_read_lock();
        entry = rcu_dereference(q->current_entry);
        /* if there's no entry, it means that the schedule didn't
@@ -958,12 +953,20 @@ static void taprio_set_picos_per_byte(struct net_device *dev,
                                      struct taprio_sched *q)
 {
        struct ethtool_link_ksettings ecmd;
-       int picos_per_byte = -1;
+       int speed = SPEED_10;
+       int picos_per_byte;
+       int err;
 
-       if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
-           ecmd.base.speed != SPEED_UNKNOWN)
-               picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
-                                          ecmd.base.speed * 1000 * 1000);
+       err = __ethtool_get_link_ksettings(dev, &ecmd);
+       if (err < 0)
+               goto skip;
+
+       if (ecmd.base.speed != SPEED_UNKNOWN)
+               speed = ecmd.base.speed;
+
+skip:
+       picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
+                                  speed * 1000 * 1000);
 
        atomic64_set(&q->picos_per_byte, picos_per_byte);
        netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n",
@@ -1195,7 +1198,8 @@ unlock:
        spin_unlock_bh(qdisc_lock(sch));
 
 free_sched:
-       kfree(new_admin);
+       if (new_admin)
+               call_rcu(&new_admin->rcu, taprio_free_sched_cb);
 
        return err;
 }
@@ -1248,6 +1252,10 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt,
         */
        q->clockid = -1;
 
+       spin_lock(&taprio_list_lock);
+       list_add(&q->taprio_list, &taprio_list);
+       spin_unlock(&taprio_list_lock);
+
        if (sch->parent != TC_H_ROOT)
                return -EOPNOTSUPP;
 
@@ -1265,10 +1273,6 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt,
        if (!opt)
                return -EINVAL;
 
-       spin_lock(&taprio_list_lock);
-       list_add(&q->taprio_list, &taprio_list);
-       spin_unlock(&taprio_list_lock);
-
        for (i = 0; i < dev->num_tx_queues; i++) {
                struct netdev_queue *dev_queue;
                struct Qdisc *qdisc;
index 2d47adcb4cbe002f655a937ab89ffc0c603d3015..53746ffeeca355026dfb0e7712d2ec36c47811f1 100644 (file)
@@ -1336,7 +1336,7 @@ static int __net_init sctp_ctrlsock_init(struct net *net)
        return status;
 }
 
-static void __net_init sctp_ctrlsock_exit(struct net *net)
+static void __net_exit sctp_ctrlsock_exit(struct net *net)
 {
        /* Free the control endpoint.  */
        inet_ctl_sock_destroy(net->sctp.ctl_sock);
index a554d6d15d1b6fe490ab62dd4bb1abbc96b923ab..e52b2128e43b8706ddbec3d6b77388e24402c1c9 100644 (file)
@@ -546,8 +546,8 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands,
         */
        if (net->sctp.pf_enable &&
           (transport->state == SCTP_ACTIVE) &&
-          (asoc->pf_retrans < transport->pathmaxrxt) &&
-          (transport->error_count > asoc->pf_retrans)) {
+          (transport->error_count < transport->pathmaxrxt) &&
+          (transport->error_count > transport->pf_retrans)) {
 
                sctp_assoc_control_transport(asoc, transport,
                                             SCTP_TRANSPORT_PF,
index aa80cda3658116b94081f4700c28b8cb03fd2de6..b083d4e66230b1e365fc983a0d82eb6f76d0bedd 100644 (file)
@@ -309,7 +309,7 @@ static int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
        return retval;
 }
 
-static long sctp_get_port_local(struct sock *, union sctp_addr *);
+static int sctp_get_port_local(struct sock *, union sctp_addr *);
 
 /* Verify this is a valid sockaddr. */
 static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
@@ -399,9 +399,8 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
         * detection.
         */
        addr->v4.sin_port = htons(snum);
-       if ((ret = sctp_get_port_local(sk, addr))) {
+       if (sctp_get_port_local(sk, addr))
                return -EADDRINUSE;
-       }
 
        /* Refresh ephemeral port.  */
        if (!bp->port)
@@ -413,11 +412,13 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
        ret = sctp_add_bind_addr(bp, addr, af->sockaddr_len,
                                 SCTP_ADDR_SRC, GFP_ATOMIC);
 
-       /* Copy back into socket for getsockname() use. */
-       if (!ret) {
-               inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);
-               sp->pf->to_sk_saddr(addr, sk);
+       if (ret) {
+               sctp_put_port(sk);
+               return ret;
        }
+       /* Copy back into socket for getsockname() use. */
+       inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);
+       sp->pf->to_sk_saddr(addr, sk);
 
        return ret;
 }
@@ -985,7 +986,7 @@ static int sctp_setsockopt_bindx(struct sock *sk,
                return -EINVAL;
 
        kaddrs = memdup_user(addrs, addrs_size);
-       if (unlikely(IS_ERR(kaddrs)))
+       if (IS_ERR(kaddrs))
                return PTR_ERR(kaddrs);
 
        /* Walk through the addrs buffer and count the number of addresses. */
@@ -1315,7 +1316,7 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
                return -EINVAL;
 
        kaddrs = memdup_user(addrs, addrs_size);
-       if (unlikely(IS_ERR(kaddrs)))
+       if (IS_ERR(kaddrs))
                return PTR_ERR(kaddrs);
 
        /* Allow security module to validate connectx addresses. */
@@ -7173,7 +7174,7 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
                val.spt_pathmaxrxt = trans->pathmaxrxt;
                val.spt_pathpfthld = trans->pf_retrans;
 
-               return 0;
+               goto out;
        }
 
        asoc = sctp_id2assoc(sk, val.spt_assoc_id);
@@ -7191,6 +7192,7 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
                val.spt_pathmaxrxt = sp->pathmaxrxt;
        }
 
+out:
        if (put_user(len, optlen) || copy_to_user(optval, &val, len))
                return -EFAULT;
 
@@ -7998,7 +8000,7 @@ static void sctp_unhash(struct sock *sk)
 static struct sctp_bind_bucket *sctp_bucket_create(
        struct sctp_bind_hashbucket *head, struct net *, unsigned short snum);
 
-static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
+static int sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
 {
        struct sctp_sock *sp = sctp_sk(sk);
        bool reuse = (sk->sk_reuse || sp->reuse);
@@ -8108,7 +8110,7 @@ pp_found:
 
                        if (sctp_bind_addr_conflict(&ep2->base.bind_addr,
                                                    addr, sp2, sp)) {
-                               ret = (long)sk2;
+                               ret = 1;
                                goto fail_unlock;
                        }
                }
@@ -8180,7 +8182,7 @@ static int sctp_get_port(struct sock *sk, unsigned short snum)
        addr.v4.sin_port = htons(snum);
 
        /* Note: sk->sk_num gets filled in if ephemeral port request. */
-       return !!sctp_get_port_local(sk, &addr);
+       return sctp_get_port_local(sk, &addr);
 }
 
 /*
index 25946604af85c09917e63e5c4a8d7d6fa2caebc4..e83cdaa2ab765c1ce20392b5ba2d91573f39ff14 100644 (file)
@@ -316,6 +316,7 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
                nstr_list[i] = htons(str_list[i]);
 
        if (out && !sctp_stream_outq_is_empty(stream, str_nums, nstr_list)) {
+               kfree(nstr_list);
                retval = -EAGAIN;
                goto out;
        }
index 302e355f2ebc39c49ebbe7d617cbc488f66f83c6..5b932583e4076feacb786d315bc4d6181fd9a17b 100644 (file)
@@ -263,7 +263,7 @@ static int smc_bind(struct socket *sock, struct sockaddr *uaddr,
 
        /* Check if socket is already active */
        rc = -EINVAL;
-       if (sk->sk_state != SMC_INIT)
+       if (sk->sk_state != SMC_INIT || smc->connect_nonblock)
                goto out_rel;
 
        smc->clcsock->sk->sk_reuse = sk->sk_reuse;
@@ -1390,7 +1390,8 @@ static int smc_listen(struct socket *sock, int backlog)
        lock_sock(sk);
 
        rc = -EINVAL;
-       if ((sk->sk_state != SMC_INIT) && (sk->sk_state != SMC_LISTEN))
+       if ((sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) ||
+           smc->connect_nonblock)
                goto out;
 
        rc = 0;
@@ -1518,7 +1519,7 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
                goto out;
 
        if (msg->msg_flags & MSG_FASTOPEN) {
-               if (sk->sk_state == SMC_INIT) {
+               if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) {
                        smc_switch_to_fallback(smc);
                        smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
                } else {
@@ -1732,14 +1733,18 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
                }
                break;
        case TCP_NODELAY:
-               if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
+               if (sk->sk_state != SMC_INIT &&
+                   sk->sk_state != SMC_LISTEN &&
+                   sk->sk_state != SMC_CLOSED) {
                        if (val && !smc->use_fallback)
                                mod_delayed_work(system_wq, &smc->conn.tx_work,
                                                 0);
                }
                break;
        case TCP_CORK:
-               if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
+               if (sk->sk_state != SMC_INIT &&
+                   sk->sk_state != SMC_LISTEN &&
+                   sk->sk_state != SMC_CLOSED) {
                        if (!val && !smc->use_fallback)
                                mod_delayed_work(system_wq, &smc->conn.tx_work,
                                                 0);
index f0de323d15d60557255cf5572677dc9828a8953e..6c8f09c1ce512b4740ba384c01f2d5cf530cf844 100644 (file)
@@ -76,13 +76,11 @@ static int smc_tx_wait(struct smc_sock *smc, int flags)
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
        struct smc_connection *conn = &smc->conn;
        struct sock *sk = &smc->sk;
-       bool noblock;
        long timeo;
        int rc = 0;
 
        /* similar to sk_stream_wait_memory */
        timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
-       noblock = timeo ? false : true;
        add_wait_queue(sk_sleep(sk), &wait);
        while (1) {
                sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
@@ -97,8 +95,8 @@ static int smc_tx_wait(struct smc_sock *smc, int flags)
                        break;
                }
                if (!timeo) {
-                       if (noblock)
-                               set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+                       /* ensure EPOLLOUT is subsequently generated */
+                       set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
                        rc = -EAGAIN;
                        break;
                }
index d8679b6027e933a2130fafcecd12e57b9975c8db..a07b516e503a0a8252d0f3876f38df65b812da0d 100644 (file)
@@ -1970,6 +1970,7 @@ call_bind(struct rpc_task *task)
 static void
 call_bind_status(struct rpc_task *task)
 {
+       struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
        int status = -EIO;
 
        if (rpc_task_transmitted(task)) {
@@ -1977,14 +1978,15 @@ call_bind_status(struct rpc_task *task)
                return;
        }
 
-       if (task->tk_status >= 0) {
-               dprint_status(task);
+       dprint_status(task);
+       trace_rpc_bind_status(task);
+       if (task->tk_status >= 0)
+               goto out_next;
+       if (xprt_bound(xprt)) {
                task->tk_status = 0;
-               task->tk_action = call_connect;
-               return;
+               goto out_next;
        }
 
-       trace_rpc_bind_status(task);
        switch (task->tk_status) {
        case -ENOMEM:
                dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid);
@@ -2003,6 +2005,9 @@ call_bind_status(struct rpc_task *task)
                task->tk_rebind_retry--;
                rpc_delay(task, 3*HZ);
                goto retry_timeout;
+       case -ENOBUFS:
+               rpc_delay(task, HZ >> 2);
+               goto retry_timeout;
        case -EAGAIN:
                goto retry_timeout;
        case -ETIMEDOUT:
@@ -2026,7 +2031,6 @@ call_bind_status(struct rpc_task *task)
        case -ENETDOWN:
        case -EHOSTUNREACH:
        case -ENETUNREACH:
-       case -ENOBUFS:
        case -EPIPE:
                dprintk("RPC: %5u remote rpcbind unreachable: %d\n",
                                task->tk_pid, task->tk_status);
@@ -2043,7 +2047,9 @@ call_bind_status(struct rpc_task *task)
 
        rpc_call_rpcerror(task, status);
        return;
-
+out_next:
+       task->tk_action = call_connect;
+       return;
 retry_timeout:
        task->tk_status = 0;
        task->tk_action = call_bind;
@@ -2090,6 +2096,7 @@ call_connect(struct rpc_task *task)
 static void
 call_connect_status(struct rpc_task *task)
 {
+       struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
        struct rpc_clnt *clnt = task->tk_client;
        int status = task->tk_status;
 
@@ -2099,8 +2106,17 @@ call_connect_status(struct rpc_task *task)
        }
 
        dprint_status(task);
-
        trace_rpc_connect_status(task);
+
+       if (task->tk_status == 0) {
+               clnt->cl_stats->netreconn++;
+               goto out_next;
+       }
+       if (xprt_connected(xprt)) {
+               task->tk_status = 0;
+               goto out_next;
+       }
+
        task->tk_status = 0;
        switch (status) {
        case -ECONNREFUSED:
@@ -2117,8 +2133,6 @@ call_connect_status(struct rpc_task *task)
        case -ENETDOWN:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
-       case -EADDRINUSE:
-       case -ENOBUFS:
        case -EPIPE:
                xprt_conditional_disconnect(task->tk_rqstp->rq_xprt,
                                            task->tk_rqstp->rq_connect_cookie);
@@ -2127,17 +2141,20 @@ call_connect_status(struct rpc_task *task)
                /* retry with existing socket, after a delay */
                rpc_delay(task, 3*HZ);
                /* fall through */
+       case -EADDRINUSE:
        case -ENOTCONN:
        case -EAGAIN:
        case -ETIMEDOUT:
                goto out_retry;
-       case 0:
-               clnt->cl_stats->netreconn++;
-               task->tk_action = call_transmit;
-               return;
+       case -ENOBUFS:
+               rpc_delay(task, HZ >> 2);
+               goto out_retry;
        }
        rpc_call_rpcerror(task, status);
        return;
+out_next:
+       task->tk_action = call_transmit;
+       return;
 out_retry:
        /* Check for timeouts before looping back to call_bind */
        task->tk_action = call_bind;
@@ -2365,7 +2382,7 @@ call_status(struct rpc_task *task)
        case -ECONNABORTED:
        case -ENOTCONN:
                rpc_force_rebind(clnt);
-               /* fall through */
+               break;
        case -EADDRINUSE:
                rpc_delay(task, 3*HZ);
                /* fall through */
index 783748dc5e6fbf59959380e024e99e42039d7956..2e71f5455c6cc95d9182b6a3f36b458f5d20a951 100644 (file)
@@ -1408,13 +1408,6 @@ xprt_request_transmit(struct rpc_rqst *req, struct rpc_task *snd_task)
                        status = -EBADMSG;
                        goto out_dequeue;
                }
-               if (task->tk_ops->rpc_call_prepare_transmit) {
-                       task->tk_ops->rpc_call_prepare_transmit(task,
-                                       task->tk_calldata);
-                       status = task->tk_status;
-                       if (status < 0)
-                               goto out_dequeue;
-               }
                if (RPC_SIGNALLED(task)) {
                        status = -ERESTARTSYS;
                        goto out_dequeue;
index b88d48d009130985db69993bc115c8cae80a71a9..0f1eaed1bd1b310833443cfb930e57d85dfa51a9 100644 (file)
@@ -75,6 +75,7 @@ void tipc_set_node_addr(struct net *net, u32 addr)
                tipc_set_node_id(net, node_id);
        }
        tn->trial_addr = addr;
+       tn->addr_trial_end = jiffies;
        pr_info("32-bit node address hash set to %x\n", addr);
 }
 
index 66d3a07bc5711ff404332e2224d139ad71daaaee..c2c5c53cad22e26e156bfe13b70fa369a32ee620 100644 (file)
@@ -106,8 +106,6 @@ struct tipc_stats {
  * @transmitq: queue for sent, non-acked messages
  * @backlogq: queue for messages waiting to be sent
  * @snt_nxt: next sequence number to use for outbound messages
- * @prev_from: sequence number of most previous retransmission request
- * @stale_limit: time when repeated identical retransmits must force link reset
  * @ackers: # of peers that needs to ack each packet before it can be released
  * @acked: # last packet acked by a certain peer. Used for broadcast.
  * @rcv_nxt: next sequence number to expect for inbound messages
@@ -164,9 +162,7 @@ struct tipc_link {
                u16 limit;
        } backlog[5];
        u16 snd_nxt;
-       u16 prev_from;
        u16 window;
-       unsigned long stale_limit;
 
        /* Reception */
        u16 rcv_nxt;
@@ -1044,47 +1040,53 @@ static void tipc_link_advance_backlog(struct tipc_link *l,
  * link_retransmit_failure() - Detect repeated retransmit failures
  * @l: tipc link sender
  * @r: tipc link receiver (= l in case of unicast)
- * @from: seqno of the 1st packet in retransmit request
  * @rc: returned code
  *
  * Return: true if the repeated retransmit failures happens, otherwise
  * false
  */
 static bool link_retransmit_failure(struct tipc_link *l, struct tipc_link *r,
-                                   u16 from, int *rc)
+                                   int *rc)
 {
        struct sk_buff *skb = skb_peek(&l->transmq);
        struct tipc_msg *hdr;
 
        if (!skb)
                return false;
-       hdr = buf_msg(skb);
 
-       /* Detect repeated retransmit failures on same packet */
-       if (r->prev_from != from) {
-               r->prev_from = from;
-               r->stale_limit = jiffies + msecs_to_jiffies(r->tolerance);
-       } else if (time_after(jiffies, r->stale_limit)) {
-               pr_warn("Retransmission failure on link <%s>\n", l->name);
-               link_print(l, "State of link ");
-               pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n",
-                       msg_user(hdr), msg_type(hdr), msg_size(hdr),
-                       msg_errcode(hdr));
-               pr_info("sqno %u, prev: %x, src: %x\n",
-                       msg_seqno(hdr), msg_prevnode(hdr), msg_orignode(hdr));
-
-               trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
-               trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
-               trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
+       if (!TIPC_SKB_CB(skb)->retr_cnt)
+               return false;
 
-               if (link_is_bc_sndlink(l))
-                       *rc = TIPC_LINK_DOWN_EVT;
+       if (!time_after(jiffies, TIPC_SKB_CB(skb)->retr_stamp +
+                       msecs_to_jiffies(r->tolerance)))
+               return false;
+
+       hdr = buf_msg(skb);
+       if (link_is_bc_sndlink(l) && !less(r->acked, msg_seqno(hdr)))
+               return false;
 
+       pr_warn("Retransmission failure on link <%s>\n", l->name);
+       link_print(l, "State of link ");
+       pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n",
+               msg_user(hdr), msg_type(hdr), msg_size(hdr), msg_errcode(hdr));
+       pr_info("sqno %u, prev: %x, dest: %x\n",
+               msg_seqno(hdr), msg_prevnode(hdr), msg_destnode(hdr));
+       pr_info("retr_stamp %d, retr_cnt %d\n",
+               jiffies_to_msecs(TIPC_SKB_CB(skb)->retr_stamp),
+               TIPC_SKB_CB(skb)->retr_cnt);
+
+       trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
+       trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
+       trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
+
+       if (link_is_bc_sndlink(l)) {
+               r->state = LINK_RESET;
+               *rc = TIPC_LINK_DOWN_EVT;
+       } else {
                *rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
-               return true;
        }
 
-       return false;
+       return true;
 }
 
 /* tipc_link_bc_retrans() - retransmit zero or more packets
@@ -1110,7 +1112,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
 
        trace_tipc_link_retrans(r, from, to, &l->transmq);
 
-       if (link_retransmit_failure(l, r, from, &rc))
+       if (link_retransmit_failure(l, r, &rc))
                return rc;
 
        skb_queue_walk(&l->transmq, skb) {
@@ -1119,11 +1121,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
                        continue;
                if (more(msg_seqno(hdr), to))
                        break;
-               if (link_is_bc_sndlink(l)) {
-                       if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
-                               continue;
-                       TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
-               }
+
+               if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
+                       continue;
+               TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
                _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, GFP_ATOMIC);
                if (!_skb)
                        return 0;
@@ -1133,6 +1134,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
                _skb->priority = TC_PRIO_CONTROL;
                __skb_queue_tail(xmitq, _skb);
                l->stats.retransmitted++;
+
+               /* Increase actual retrans counter & mark first time */
+               if (!TIPC_SKB_CB(skb)->retr_cnt++)
+                       TIPC_SKB_CB(skb)->retr_stamp = jiffies;
        }
        return 0;
 }
@@ -1357,12 +1362,10 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap,
        struct tipc_msg *hdr;
        u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
        u16 ack = l->rcv_nxt - 1;
+       bool passed = false;
        u16 seqno, n = 0;
        int rc = 0;
 
-       if (gap && link_retransmit_failure(l, l, acked + 1, &rc))
-               return rc;
-
        skb_queue_walk_safe(&l->transmq, skb, tmp) {
                seqno = buf_seqno(skb);
 
@@ -1372,12 +1375,17 @@ next_gap_ack:
                        __skb_unlink(skb, &l->transmq);
                        kfree_skb(skb);
                } else if (less_eq(seqno, acked + gap)) {
-                       /* retransmit skb */
+                       /* First, check if repeated retrans failures occurs? */
+                       if (!passed && link_retransmit_failure(l, l, &rc))
+                               return rc;
+                       passed = true;
+
+                       /* retransmit skb if unrestricted*/
                        if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
                                continue;
                        TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME;
-
-                       _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC);
+                       _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE,
+                                          GFP_ATOMIC);
                        if (!_skb)
                                continue;
                        hdr = buf_msg(_skb);
@@ -1386,6 +1394,10 @@ next_gap_ack:
                        _skb->priority = TC_PRIO_CONTROL;
                        __skb_queue_tail(xmitq, _skb);
                        l->stats.retransmitted++;
+
+                       /* Increase actual retrans counter & mark first time */
+                       if (!TIPC_SKB_CB(skb)->retr_cnt++)
+                               TIPC_SKB_CB(skb)->retr_stamp = jiffies;
                } else {
                        /* retry with Gap ACK blocks if any */
                        if (!ga || n >= ga->gack_cnt)
@@ -2577,7 +2589,7 @@ int tipc_link_dump(struct tipc_link *l, u16 dqueues, char *buf)
        i += scnprintf(buf + i, sz - i, " %x", l->peer_caps);
        i += scnprintf(buf + i, sz - i, " %u", l->silent_intv_cnt);
        i += scnprintf(buf + i, sz - i, " %u", l->rst_cnt);
-       i += scnprintf(buf + i, sz - i, " %u", l->prev_from);
+       i += scnprintf(buf + i, sz - i, " %u", 0);
        i += scnprintf(buf + i, sz - i, " %u", 0);
        i += scnprintf(buf + i, sz - i, " %u", l->acked);
 
index da509f0eb9ca48d70ef012418e2e3326d9e83563..d7ebc9e955f6a35fe6b6ac058a48c30c6218fbdc 100644 (file)
@@ -102,13 +102,15 @@ struct plist;
 #define TIPC_MEDIA_INFO_OFFSET 5
 
 struct tipc_skb_cb {
-       u32 bytes_read;
-       u32 orig_member;
        struct sk_buff *tail;
        unsigned long nxt_retr;
-       bool validated;
+       unsigned long retr_stamp;
+       u32 bytes_read;
+       u32 orig_member;
        u16 chain_imp;
        u16 ackers;
+       u16 retr_cnt;
+       bool validated;
 };
 
 #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
index 44abc8e9c99024df9932d151fdc32ce4d4aa2820..241ed22744739dc5d2167ce7c4f108c2e1200b01 100644 (file)
@@ -223,7 +223,8 @@ static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr)
                       publ->key);
        }
 
-       kfree_rcu(p, rcu);
+       if (p)
+               kfree_rcu(p, rcu);
 }
 
 /**
index d86030ef1232a33af7e2da036bc5592c4d5c0021..e135d4e11231995c952d4adbe69d7b42a63adc27 100644 (file)
@@ -55,6 +55,7 @@ struct tipc_nl_compat_msg {
        int rep_type;
        int rep_size;
        int req_type;
+       int req_size;
        struct net *net;
        struct sk_buff *rep;
        struct tlv_desc *req;
@@ -257,7 +258,8 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
        int err;
        struct sk_buff *arg;
 
-       if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type))
+       if (msg->req_type && (!msg->req_size ||
+                             !TLV_CHECK_TYPE(msg->req, msg->req_type)))
                return -EINVAL;
 
        msg->rep = tipc_tlv_alloc(msg->rep_size);
@@ -354,7 +356,8 @@ static int tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd,
 {
        int err;
 
-       if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type))
+       if (msg->req_type && (!msg->req_size ||
+                             !TLV_CHECK_TYPE(msg->req, msg->req_type)))
                return -EINVAL;
 
        err = __tipc_nl_compat_doit(cmd, msg);
@@ -1278,8 +1281,8 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
                goto send;
        }
 
-       len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
-       if (!len || !TLV_OK(msg.req, len)) {
+       msg.req_size = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
+       if (msg.req_size && !TLV_OK(msg.req, msg.req_size)) {
                msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
                err = -EOPNOTSUPP;
                goto send;
index dd8537f988c4004a5c50e004f1654db5c4e548b6..83ae41d7e5548077778c805e6c3367cdbf674313 100644 (file)
@@ -485,9 +485,8 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
                tsk_set_unreturnable(tsk, true);
                if (sock->type == SOCK_DGRAM)
                        tsk_set_unreliable(tsk, true);
-               __skb_queue_head_init(&tsk->mc_method.deferredq);
        }
-
+       __skb_queue_head_init(&tsk->mc_method.deferredq);
        trace_tipc_sk_create(sk, NULL, TIPC_DUMP_NONE, " ");
        return 0;
 }
index f345662890a6e0eee7d7df16636f1e2d68609d99..ca8ac96d22a9658c9e492105ff65765b176f93f2 100644 (file)
@@ -476,7 +476,7 @@ static void tipc_topsrv_accept(struct work_struct *work)
        }
 }
 
-/* tipc_toprsv_listener_data_ready - interrupt callback with connection request
+/* tipc_topsrv_listener_data_ready - interrupt callback with connection request
  * The queued job is launched into tipc_topsrv_accept()
  */
 static void tipc_topsrv_listener_data_ready(struct sock *sk)
index 7c0b2b778703f7080c28d4919084390d4da05e7c..43922d86e5109f9b19dab68be4c950e7440ad7e8 100644 (file)
@@ -373,9 +373,9 @@ static int tls_push_data(struct sock *sk,
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_prot_info *prot = &tls_ctx->prot_info;
        struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
-       int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
        int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE);
        struct tls_record_info *record = ctx->open_record;
+       int tls_push_record_flags;
        struct page_frag *pfrag;
        size_t orig_size = size;
        u32 max_open_record_len;
@@ -390,6 +390,9 @@ static int tls_push_data(struct sock *sk,
        if (sk->sk_err)
                return -sk->sk_err;
 
+       flags |= MSG_SENDPAGE_DECRYPTED;
+       tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
+
        timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
        if (tls_is_partially_sent_record(tls_ctx)) {
                rc = tls_push_partial_record(sk, tls_ctx, flags);
@@ -576,7 +579,9 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
                gfp_t sk_allocation = sk->sk_allocation;
 
                sk->sk_allocation = GFP_ATOMIC;
-               tls_push_partial_record(sk, ctx, MSG_DONTWAIT | MSG_NOSIGNAL);
+               tls_push_partial_record(sk, ctx,
+                                       MSG_DONTWAIT | MSG_NOSIGNAL |
+                                       MSG_SENDPAGE_DECRYPTED);
                sk->sk_allocation = sk_allocation;
        }
 }
index 4674e57e66b0533fc5faf5ae930c0aad85eb8b77..43252a801c3f6db298d30926aa15453b42aa1644 100644 (file)
@@ -261,24 +261,9 @@ void tls_ctx_free(struct tls_context *ctx)
        kfree(ctx);
 }
 
-static void tls_sk_proto_close(struct sock *sk, long timeout)
+static void tls_sk_proto_cleanup(struct sock *sk,
+                                struct tls_context *ctx, long timeo)
 {
-       struct tls_context *ctx = tls_get_ctx(sk);
-       long timeo = sock_sndtimeo(sk, 0);
-       void (*sk_proto_close)(struct sock *sk, long timeout);
-       bool free_ctx = false;
-
-       lock_sock(sk);
-       sk_proto_close = ctx->sk_proto_close;
-
-       if (ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD)
-               goto skip_tx_cleanup;
-
-       if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) {
-               free_ctx = true;
-               goto skip_tx_cleanup;
-       }
-
        if (unlikely(sk->sk_write_pending) &&
            !wait_on_pending_writer(sk, &timeo))
                tls_handle_open_record(sk, 0);
@@ -287,7 +272,7 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
        if (ctx->tx_conf == TLS_SW) {
                kfree(ctx->tx.rec_seq);
                kfree(ctx->tx.iv);
-               tls_sw_free_resources_tx(sk);
+               tls_sw_release_resources_tx(sk);
 #ifdef CONFIG_TLS_DEVICE
        } else if (ctx->tx_conf == TLS_HW) {
                tls_device_free_resources_tx(sk);
@@ -295,26 +280,46 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
        }
 
        if (ctx->rx_conf == TLS_SW)
-               tls_sw_free_resources_rx(sk);
+               tls_sw_release_resources_rx(sk);
 
 #ifdef CONFIG_TLS_DEVICE
        if (ctx->rx_conf == TLS_HW)
                tls_device_offload_cleanup_rx(sk);
-
-       if (ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW) {
-#else
-       {
 #endif
-               tls_ctx_free(ctx);
-               ctx = NULL;
-       }
+}
 
-skip_tx_cleanup:
+static void tls_sk_proto_close(struct sock *sk, long timeout)
+{
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       struct tls_context *ctx = tls_get_ctx(sk);
+       long timeo = sock_sndtimeo(sk, 0);
+       bool free_ctx;
+
+       if (ctx->tx_conf == TLS_SW)
+               tls_sw_cancel_work_tx(ctx);
+
+       lock_sock(sk);
+       free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW;
+
+       if (ctx->tx_conf != TLS_BASE || ctx->rx_conf != TLS_BASE)
+               tls_sk_proto_cleanup(sk, ctx, timeo);
+
+       write_lock_bh(&sk->sk_callback_lock);
+       if (free_ctx)
+               icsk->icsk_ulp_data = NULL;
+       sk->sk_prot = ctx->sk_proto;
+       if (sk->sk_write_space == tls_write_space)
+               sk->sk_write_space = ctx->sk_write_space;
+       write_unlock_bh(&sk->sk_callback_lock);
        release_sock(sk);
-       sk_proto_close(sk, timeout);
-       /* free ctx for TLS_HW_RECORD, used by tcp_set_state
-        * for sk->sk_prot->unhash [tls_hw_unhash]
-        */
+       if (ctx->tx_conf == TLS_SW)
+               tls_sw_free_ctx_tx(ctx);
+       if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW)
+               tls_sw_strparser_done(ctx);
+       if (ctx->rx_conf == TLS_SW)
+               tls_sw_free_ctx_rx(ctx);
+       ctx->sk_proto_close(sk, timeout);
+
        if (free_ctx)
                tls_ctx_free(ctx);
 }
@@ -526,6 +531,8 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
                {
 #endif
                        rc = tls_set_sw_offload(sk, ctx, 1);
+                       if (rc)
+                               goto err_crypto_info;
                        conf = TLS_SW;
                }
        } else {
@@ -537,13 +544,13 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
                {
 #endif
                        rc = tls_set_sw_offload(sk, ctx, 0);
+                       if (rc)
+                               goto err_crypto_info;
                        conf = TLS_SW;
                }
+               tls_sw_strparser_arm(sk, ctx);
        }
 
-       if (rc)
-               goto err_crypto_info;
-
        if (tx)
                ctx->tx_conf = conf;
        else
@@ -607,6 +614,7 @@ static struct tls_context *create_ctx(struct sock *sk)
        ctx->setsockopt = sk->sk_prot->setsockopt;
        ctx->getsockopt = sk->sk_prot->getsockopt;
        ctx->sk_proto_close = sk->sk_prot->close;
+       ctx->unhash = sk->sk_prot->unhash;
        return ctx;
 }
 
@@ -764,7 +772,6 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG],
        prot[TLS_HW_RECORD][TLS_HW_RECORD] = *base;
        prot[TLS_HW_RECORD][TLS_HW_RECORD].hash         = tls_hw_hash;
        prot[TLS_HW_RECORD][TLS_HW_RECORD].unhash       = tls_hw_unhash;
-       prot[TLS_HW_RECORD][TLS_HW_RECORD].close        = tls_sk_proto_close;
 }
 
 static int tls_init(struct sock *sk)
@@ -773,7 +780,7 @@ static int tls_init(struct sock *sk)
        int rc = 0;
 
        if (tls_hw_prot(sk))
-               goto out;
+               return 0;
 
        /* The TLS ulp is currently supported only for TCP sockets
         * in ESTABLISHED state.
@@ -784,21 +791,38 @@ static int tls_init(struct sock *sk)
        if (sk->sk_state != TCP_ESTABLISHED)
                return -ENOTSUPP;
 
+       tls_build_proto(sk);
+
        /* allocate tls context */
+       write_lock_bh(&sk->sk_callback_lock);
        ctx = create_ctx(sk);
        if (!ctx) {
                rc = -ENOMEM;
                goto out;
        }
 
-       tls_build_proto(sk);
        ctx->tx_conf = TLS_BASE;
        ctx->rx_conf = TLS_BASE;
+       ctx->sk_proto = sk->sk_prot;
        update_sk_prot(sk, ctx);
 out:
+       write_unlock_bh(&sk->sk_callback_lock);
        return rc;
 }
 
+static void tls_update(struct sock *sk, struct proto *p)
+{
+       struct tls_context *ctx;
+
+       ctx = tls_get_ctx(sk);
+       if (likely(ctx)) {
+               ctx->sk_proto_close = p->close;
+               ctx->sk_proto = p;
+       } else {
+               sk->sk_prot = p;
+       }
+}
+
 void tls_register_device(struct tls_device *device)
 {
        spin_lock_bh(&device_spinlock);
@@ -819,6 +843,7 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
        .name                   = "tls",
        .owner                  = THIS_MODULE,
        .init                   = tls_init,
+       .update                 = tls_update,
 };
 
 static int __init tls_register(void)
index 53b4ad94e74ab0aecb964ce0ed482c9277654d47..91d21b048a9b245804ba800d7e9dbc1b5c07a868 100644 (file)
@@ -2054,7 +2054,16 @@ static void tls_data_ready(struct sock *sk)
        }
 }
 
-void tls_sw_free_resources_tx(struct sock *sk)
+void tls_sw_cancel_work_tx(struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+
+       set_bit(BIT_TX_CLOSING, &ctx->tx_bitmask);
+       set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask);
+       cancel_delayed_work_sync(&ctx->tx_work.work);
+}
+
+void tls_sw_release_resources_tx(struct sock *sk)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
@@ -2065,11 +2074,6 @@ void tls_sw_free_resources_tx(struct sock *sk)
        if (atomic_read(&ctx->encrypt_pending))
                crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
 
-       release_sock(sk);
-       cancel_delayed_work_sync(&ctx->tx_work.work);
-       lock_sock(sk);
-
-       /* Tx whatever records we can transmit and abandon the rest */
        tls_tx_records(sk, -1);
 
        /* Free up un-sent records in tx_list. First, free
@@ -2092,6 +2096,11 @@ void tls_sw_free_resources_tx(struct sock *sk)
 
        crypto_free_aead(ctx->aead_send);
        tls_free_open_rec(sk);
+}
+
+void tls_sw_free_ctx_tx(struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
 
        kfree(ctx);
 }
@@ -2110,25 +2119,40 @@ void tls_sw_release_resources_rx(struct sock *sk)
                skb_queue_purge(&ctx->rx_list);
                crypto_free_aead(ctx->aead_recv);
                strp_stop(&ctx->strp);
-               write_lock_bh(&sk->sk_callback_lock);
-               sk->sk_data_ready = ctx->saved_data_ready;
-               write_unlock_bh(&sk->sk_callback_lock);
-               release_sock(sk);
-               strp_done(&ctx->strp);
-               lock_sock(sk);
+               /* If tls_sw_strparser_arm() was not called (cleanup paths)
+                * we still want to strp_stop(), but sk->sk_data_ready was
+                * never swapped.
+                */
+               if (ctx->saved_data_ready) {
+                       write_lock_bh(&sk->sk_callback_lock);
+                       sk->sk_data_ready = ctx->saved_data_ready;
+                       write_unlock_bh(&sk->sk_callback_lock);
+               }
        }
 }
 
-void tls_sw_free_resources_rx(struct sock *sk)
+void tls_sw_strparser_done(struct tls_context *tls_ctx)
 {
-       struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
 
-       tls_sw_release_resources_rx(sk);
+       strp_done(&ctx->strp);
+}
+
+void tls_sw_free_ctx_rx(struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
 
        kfree(ctx);
 }
 
+void tls_sw_free_resources_rx(struct sock *sk)
+{
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
+
+       tls_sw_release_resources_rx(sk);
+       tls_sw_free_ctx_rx(tls_ctx);
+}
+
 /* The work handler to transmitt the encrypted records in tx_list */
 static void tx_work_handler(struct work_struct *work)
 {
@@ -2137,11 +2161,17 @@ static void tx_work_handler(struct work_struct *work)
                                               struct tx_work, work);
        struct sock *sk = tx_work->sk;
        struct tls_context *tls_ctx = tls_get_ctx(sk);
-       struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+       struct tls_sw_context_tx *ctx;
 
-       if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
+       if (unlikely(!tls_ctx))
                return;
 
+       ctx = tls_sw_ctx_tx(tls_ctx);
+       if (test_bit(BIT_TX_CLOSING, &ctx->tx_bitmask))
+               return;
+
+       if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
+               return;
        lock_sock(sk);
        tls_tx_records(sk, -1);
        release_sock(sk);
@@ -2160,6 +2190,18 @@ void tls_sw_write_space(struct sock *sk, struct tls_context *ctx)
        }
 }
 
+void tls_sw_strparser_arm(struct sock *sk, struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_rx *rx_ctx = tls_sw_ctx_rx(tls_ctx);
+
+       write_lock_bh(&sk->sk_callback_lock);
+       rx_ctx->saved_data_ready = sk->sk_data_ready;
+       sk->sk_data_ready = tls_data_ready;
+       write_unlock_bh(&sk->sk_callback_lock);
+
+       strp_check_rcv(&rx_ctx->strp);
+}
+
 int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
@@ -2357,13 +2399,6 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
                cb.parse_msg = tls_read_size;
 
                strp_init(&sw_ctx_rx->strp, sk, &cb);
-
-               write_lock_bh(&sk->sk_callback_lock);
-               sw_ctx_rx->saved_data_ready = sk->sk_data_ready;
-               sk->sk_data_ready = tls_data_ready;
-               write_unlock_bh(&sk->sk_callback_lock);
-
-               strp_check_rcv(&sw_ctx_rx->strp);
        }
 
        goto out;
index f2084e3f7aa4f2157fc7a76dbdfbb31a46c8edb8..9d864ebeb7b32acaca6c207279b829e09ac6c60b 100644 (file)
@@ -312,6 +312,11 @@ static void hvs_close_connection(struct vmbus_channel *chan)
        lock_sock(sk);
        hvs_do_close_lock_held(vsock_sk(sk), true);
        release_sock(sk);
+
+       /* Release the refcnt for the channel that's opened in
+        * hvs_open_connection().
+        */
+       sock_put(sk);
 }
 
 static void hvs_open_connection(struct vmbus_channel *chan)
@@ -407,6 +412,9 @@ static void hvs_open_connection(struct vmbus_channel *chan)
        }
 
        set_per_channel_state(chan, conn_from_host ? new : sk);
+
+       /* This reference will be dropped by hvs_close_connection(). */
+       sock_hold(conn_from_host ? new : sk);
        vmbus_set_chn_rescind_callback(chan, hvs_close_connection);
 
        /* Set the pending send size to max packet size to always get
index 45d9afcff6d5f060c0f60fecd15a7acb42731fc2..32b3c719fdfce2487321d29a10b03c0cebad17f8 100644 (file)
@@ -1410,10 +1410,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                }
                break;
        case NETDEV_PRE_UP:
-               if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)) &&
-                   !(wdev->iftype == NL80211_IFTYPE_AP_VLAN &&
-                     rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP &&
-                     wdev->use_4addr))
+               if (!cfg80211_iftype_allowed(wdev->wiphy, wdev->iftype,
+                                            wdev->use_4addr, 0))
                        return notifier_from_errno(-EOPNOTSUPP);
 
                if (rfkill_blocked(rdev->rfkill))
index fc83dd179c1a8b64b622a0646840fe70a06c3b2f..fd05ae1437a9f4aaca9a8d2f07f00565cff7817f 100644 (file)
@@ -3484,9 +3484,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                        return err;
        }
 
-       if (!(rdev->wiphy.interface_modes & (1 << type)) &&
-           !(type == NL80211_IFTYPE_AP_VLAN && params.use_4addr &&
-             rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP))
+       if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
                return -EOPNOTSUPP;
 
        err = nl80211_parse_mon_options(rdev, type, info, &params);
index 4831ad745f912dd0e82e0a87b49414a175a28c68..327479ce69f53d5ea2dfe062fd83f25d69fa70b1 100644 (file)
@@ -2788,7 +2788,7 @@ static void reg_process_pending_hints(void)
 
        /* When last_request->processed becomes true this will be rescheduled */
        if (lr && !lr->processed) {
-               reg_process_hint(lr);
+               pr_debug("Pending regulatory request, waiting for it to be processed...\n");
                return;
        }
 
index 1c39d6a2e85011aff8a4991473fdec387c93bdac..e74837824cea14070440c9cc673ecd0349144594 100644 (file)
@@ -233,25 +233,30 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
 
        switch (params->cipher) {
        case WLAN_CIPHER_SUITE_TKIP:
+               /* Extended Key ID can only be used with CCMP/GCMP ciphers */
+               if ((pairwise && key_idx) ||
+                   params->mode != NL80211_KEY_RX_TX)
+                       return -EINVAL;
+               break;
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_CCMP_256:
        case WLAN_CIPHER_SUITE_GCMP:
        case WLAN_CIPHER_SUITE_GCMP_256:
-               /* IEEE802.11-2016 allows only 0 and - when using Extended Key
-                * ID - 1 as index for pairwise keys.
+               /* IEEE802.11-2016 allows only 0 and - when supporting
+                * Extended Key ID - 1 as index for pairwise keys.
                 * @NL80211_KEY_NO_TX is only allowed for pairwise keys when
                 * the driver supports Extended Key ID.
                 * @NL80211_KEY_SET_TX can't be set when installing and
                 * validating a key.
                 */
-               if (params->mode == NL80211_KEY_NO_TX) {
-                       if (!wiphy_ext_feature_isset(&rdev->wiphy,
-                                                    NL80211_EXT_FEATURE_EXT_KEY_ID))
-                               return -EINVAL;
-                       else if (!pairwise || key_idx < 0 || key_idx > 1)
+               if ((params->mode == NL80211_KEY_NO_TX && !pairwise) ||
+                   params->mode == NL80211_KEY_SET_TX)
+                       return -EINVAL;
+               if (wiphy_ext_feature_isset(&rdev->wiphy,
+                                           NL80211_EXT_FEATURE_EXT_KEY_ID)) {
+                       if (pairwise && (key_idx < 0 || key_idx > 1))
                                return -EINVAL;
-               } else if ((pairwise && key_idx) ||
-                          params->mode == NL80211_KEY_SET_TX) {
+               } else if (pairwise && key_idx) {
                        return -EINVAL;
                }
                break;
@@ -1697,7 +1702,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
        for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
                num_interfaces += params->iftype_num[iftype];
                if (params->iftype_num[iftype] > 0 &&
-                   !(wiphy->software_iftypes & BIT(iftype)))
+                   !cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
                        used_iftypes |= BIT(iftype);
        }
 
@@ -1719,7 +1724,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
                        return -ENOMEM;
 
                for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
-                       if (wiphy->software_iftypes & BIT(iftype))
+                       if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
                                continue;
                        for (j = 0; j < c->n_limits; j++) {
                                all_iftypes |= limits[j].types;
@@ -2072,3 +2077,26 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
        return max_vht_nss;
 }
 EXPORT_SYMBOL(ieee80211_get_vht_max_nss);
+
+bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
+                            bool is_4addr, u8 check_swif)
+
+{
+       bool is_vlan = iftype == NL80211_IFTYPE_AP_VLAN;
+
+       switch (check_swif) {
+       case 0:
+               if (is_vlan && is_4addr)
+                       return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
+               return wiphy->interface_modes & BIT(iftype);
+       case 1:
+               if (!(wiphy->software_iftypes & BIT(iftype)) && is_vlan)
+                       return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
+               return wiphy->software_iftypes & BIT(iftype);
+       default:
+               break;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL(cfg80211_iftype_allowed);
index 83de74ca729a39bc22cd83ac3f1cb2e7b184db0f..688aac7a6943a91751e551ea6d09b479a4d30938 100644 (file)
@@ -365,7 +365,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
        umem->pages = kcalloc(umem->npgs, sizeof(*umem->pages), GFP_KERNEL);
        if (!umem->pages) {
                err = -ENOMEM;
-               goto out_account;
+               goto out_pin;
        }
 
        for (i = 0; i < umem->npgs; i++)
@@ -373,6 +373,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
 
        return 0;
 
+out_pin:
+       xdp_umem_unpin_pages(umem);
 out_account:
        xdp_umem_unaccount_pages(umem);
        return err;
index 74868f9d81fb2b2c0fdd98522544eabfad3689fe..2ab4859df55ac08fec69b81a2a8f1cac6585195f 100644 (file)
@@ -145,8 +145,6 @@ static int xfrmi_create(struct net_device *dev)
        if (err < 0)
                goto out;
 
-       strcpy(xi->p.name, dev->name);
-
        dev_hold(dev);
        xfrmi_link(xfrmn, xi);
 
@@ -177,7 +175,6 @@ static void xfrmi_dev_uninit(struct net_device *dev)
        struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
 
        xfrmi_unlink(xfrmn, xi);
-       dev_put(xi->phydev);
        dev_put(dev);
 }
 
@@ -294,7 +291,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
        if (tdev == dev) {
                stats->collisions++;
                net_warn_ratelimited("%s: Local routing loop detected!\n",
-                                    xi->p.name);
+                                    dev->name);
                goto tx_err_dst_release;
        }
 
@@ -364,7 +361,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
                goto tx_err;
        }
 
-       fl.flowi_oif = xi->phydev->ifindex;
+       fl.flowi_oif = xi->p.link;
 
        ret = xfrmi_xmit2(skb, dev, &fl);
        if (ret < 0)
@@ -505,7 +502,7 @@ static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
 
 static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
 {
-       struct net *net = dev_net(xi->dev);
+       struct net *net = xi->net;
        struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
        int err;
 
@@ -550,7 +547,7 @@ static int xfrmi_get_iflink(const struct net_device *dev)
 {
        struct xfrm_if *xi = netdev_priv(dev);
 
-       return xi->phydev->ifindex;
+       return xi->p.link;
 }
 
 
@@ -576,12 +573,14 @@ static void xfrmi_dev_setup(struct net_device *dev)
        dev->needs_free_netdev  = true;
        dev->priv_destructor    = xfrmi_dev_free;
        netif_keep_dst(dev);
+
+       eth_broadcast_addr(dev->broadcast);
 }
 
 static int xfrmi_dev_init(struct net_device *dev)
 {
        struct xfrm_if *xi = netdev_priv(dev);
-       struct net_device *phydev = xi->phydev;
+       struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
        int err;
 
        dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
@@ -596,13 +595,19 @@ static int xfrmi_dev_init(struct net_device *dev)
 
        dev->features |= NETIF_F_LLTX;
 
-       dev->needed_headroom = phydev->needed_headroom;
-       dev->needed_tailroom = phydev->needed_tailroom;
+       if (phydev) {
+               dev->needed_headroom = phydev->needed_headroom;
+               dev->needed_tailroom = phydev->needed_tailroom;
 
-       if (is_zero_ether_addr(dev->dev_addr))
-               eth_hw_addr_inherit(dev, phydev);
-       if (is_zero_ether_addr(dev->broadcast))
-               memcpy(dev->broadcast, phydev->broadcast, dev->addr_len);
+               if (is_zero_ether_addr(dev->dev_addr))
+                       eth_hw_addr_inherit(dev, phydev);
+               if (is_zero_ether_addr(dev->broadcast))
+                       memcpy(dev->broadcast, phydev->broadcast,
+                              dev->addr_len);
+       } else {
+               eth_hw_addr_random(dev);
+               eth_broadcast_addr(dev->broadcast);
+       }
 
        return 0;
 }
@@ -638,12 +643,6 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
        int err;
 
        xfrmi_netlink_parms(data, &p);
-
-       if (!tb[IFLA_IFNAME])
-               return -EINVAL;
-
-       nla_strlcpy(p.name, tb[IFLA_IFNAME], IFNAMSIZ);
-
        xi = xfrmi_locate(net, &p);
        if (xi)
                return -EEXIST;
@@ -652,13 +651,8 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
        xi->p = p;
        xi->net = net;
        xi->dev = dev;
-       xi->phydev = dev_get_by_index(net, p.link);
-       if (!xi->phydev)
-               return -ENODEV;
 
        err = xfrmi_create(dev);
-       if (err < 0)
-               dev_put(xi->phydev);
        return err;
 }
 
@@ -672,11 +666,11 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
                           struct netlink_ext_ack *extack)
 {
        struct xfrm_if *xi = netdev_priv(dev);
-       struct net *net = dev_net(dev);
-
-       xfrmi_netlink_parms(data, &xi->p);
+       struct net *net = xi->net;
+       struct xfrm_if_parms p;
 
-       xi = xfrmi_locate(net, &xi->p);
+       xfrmi_netlink_parms(data, &p);
+       xi = xfrmi_locate(net, &p);
        if (!xi) {
                xi = netdev_priv(dev);
        } else {
@@ -684,7 +678,7 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
                        return -EEXIST;
        }
 
-       return xfrmi_update(xi, &xi->p);
+       return xfrmi_update(xi, &p);
 }
 
 static size_t xfrmi_get_size(const struct net_device *dev)
@@ -715,7 +709,7 @@ static struct net *xfrmi_get_link_net(const struct net_device *dev)
 {
        struct xfrm_if *xi = netdev_priv(dev);
 
-       return dev_net(xi->phydev);
+       return xi->net;
 }
 
 static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
index 8ca637a72697491863bf2f6f606c7a669932847f..21e939235b3908ba3c363e2a570f41acd316173e 100644 (file)
@@ -912,6 +912,7 @@ restart:
                } else if (delta > 0) {
                        p = &parent->rb_right;
                } else {
+                       bool same_prefixlen = node->prefixlen == n->prefixlen;
                        struct xfrm_policy *tmp;
 
                        hlist_for_each_entry(tmp, &n->hhead, bydst) {
@@ -919,9 +920,11 @@ restart:
                                hlist_del_rcu(&tmp->bydst);
                        }
 
+                       node->prefixlen = prefixlen;
+
                        xfrm_policy_inexact_list_reinsert(net, node, family);
 
-                       if (node->prefixlen == n->prefixlen) {
+                       if (same_prefixlen) {
                                kfree_rcu(n, rcu);
                                return;
                        }
@@ -929,7 +932,6 @@ restart:
                        rb_erase(*p, new);
                        kfree_rcu(n, rcu);
                        n = node;
-                       n->prefixlen = prefixlen;
                        goto restart;
                }
        }
@@ -3269,7 +3271,7 @@ decode_session4(struct sk_buff *skb, struct flowi *fl, bool reverse)
        struct flowi4 *fl4 = &fl->u.ip4;
        int oif = 0;
 
-       if (skb_dst(skb))
+       if (skb_dst(skb) && skb_dst(skb)->dev)
                oif = skb_dst(skb)->dev->ifindex;
 
        memset(fl4, 0, sizeof(struct flowi4));
@@ -3387,7 +3389,7 @@ decode_session6(struct sk_buff *skb, struct flowi *fl, bool reverse)
 
        nexthdr = nh[nhoff];
 
-       if (skb_dst(skb))
+       if (skb_dst(skb) && skb_dst(skb)->dev)
                oif = skb_dst(skb)->dev->ifindex;
 
        memset(fl6, 0, sizeof(struct flowi6));
index 85571e90191fc35fad9aca49cda400ae75b9751d..bfeab44f81d077b5ac76bd1bf117ec148d010c79 100644 (file)
@@ -245,7 +245,7 @@ int main(int argc, char *argv[])
 
        if (argc != 2) {
                printf(
-                       "Sintax:  %s fbdev\n"
+                       "Syntax:  %s fbdev\n"
                        "Usually: /dev/fb0, /dev/fb1...\n", argv[0]);
                return -1;
        }
index 96b3b1b49d34b3e8312dd20564c701b0b522b838..eb26421b6429d607a2155fb338a6b7e82b755470 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Simple pci display device.
  *
index 77c742fa4fb1b9c0968d5cbaa5307c89cce5d120..4b0432e095ae03fab58064d87b85dc9387721250 100644 (file)
@@ -190,9 +190,6 @@ echo-cmd = $(if $($(quiet)cmd_$(1)),\
 # printing commands
 cmd = @set -e; $(echo-cmd) $(cmd_$(1))
 
-# Add $(obj)/ for paths that are not absolute
-objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
-
 ###
 # if_changed      - execute command if any prerequisite is newer than
 #                   target, or command line has changed
index 8a5c4d645eb140447de07224a7566643a96386c2..4bbf4fc163a297064f12f8d24531da537fe849fc 100644 (file)
@@ -25,7 +25,7 @@ failure = $(if-success,$(1),n,y)
 
 # $(cc-option,<flag>)
 # Return y if the compiler supports <flag>, n otherwise
-cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
+cc-option = $(success,$(CC) -Werror $(CLANG_FLAGS) $(1) -E -x c /dev/null -o /dev/null)
 
 # $(ld-option,<flag>)
 # Return y if the linker supports <flag>, n otherwise
index 0d434d0afc0bc81262afebdd069a1ccb30da9787..2f66ed388d1c33962126c015530147b2f677cef8 100644 (file)
@@ -52,6 +52,13 @@ ifndef obj
 $(warning kbuild: Makefile.build is included improperly)
 endif
 
+ifeq ($(MAKECMDGOALS)$(need-modorder),)
+ifneq ($(obj-m),)
+$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.)
+$(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.)
+endif
+endif
+
 # ===========================================================================
 
 ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
@@ -487,7 +494,9 @@ targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
 
 PHONY += $(subdir-ym)
 $(subdir-ym):
-       $(Q)$(MAKE) $(build)=$@ need-builtin=$(if $(findstring $@,$(subdir-obj-y)),1)
+       $(Q)$(MAKE) $(build)=$@ \
+       need-builtin=$(if $(filter $@/built-in.a, $(subdir-obj-y)),1) \
+       need-modorder=$(if $(need-modorder),$(if $(filter $@/modules.order, $(modorder)),1))
 
 # Add FORCE to the prequisites of a target to force it to be always rebuilt.
 # ---------------------------------------------------------------------------
index 5241d0751eb0d4b0c78ae3e3427ed4ffc7c9821c..41c50f9461e51f720e00c0dac5480198aaaaadf8 100644 (file)
@@ -45,7 +45,6 @@ subdir-ym     := $(sort $(subdir-y) $(subdir-m))
 multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m))))
 multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))), $(m))))
 multi-used   := $(multi-used-y) $(multi-used-m)
-single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m)))
 
 # $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to
 # tell kbuild to descend
@@ -91,7 +90,6 @@ lib-y         := $(addprefix $(obj)/,$(lib-y))
 subdir-obj-y   := $(addprefix $(obj)/,$(subdir-obj-y))
 real-obj-y     := $(addprefix $(obj)/,$(real-obj-y))
 real-obj-m     := $(addprefix $(obj)/,$(real-obj-m))
-single-used-m  := $(addprefix $(obj)/,$(single-used-m))
 multi-used-m   := $(addprefix $(obj)/,$(multi-used-m))
 subdir-ym      := $(addprefix $(obj)/,$(subdir-ym))
 
index 6b19c1a4eae530e1b00c305575d27173677dada4..26e6574ecd08d4e0e189a35524aff1c704fb0e24 100644 (file)
 # symbols in the final module linking stage
 # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
 # This is solely useful to speed up test compiles
-PHONY := _modpost
-_modpost: __modpost
+
+PHONY := __modpost
+__modpost:
 
 include include/config/auto.conf
 include scripts/Kbuild.include
 
+kernelsymfile := $(objtree)/Module.symvers
+modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
+
+MODPOST = scripts/mod/modpost                                          \
+       $(if $(CONFIG_MODVERSIONS),-m)                                  \
+       $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a)                        \
+       $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile)                   \
+       $(if $(KBUILD_EXTMOD),-I $(modulesymfile))                      \
+       $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \
+       $(if $(KBUILD_EXTMOD),-o $(modulesymfile))                      \
+       $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E)                  \
+       $(if $(KBUILD_MODPOST_WARN),-w)
+
+ifdef MODPOST_VMLINUX
+
+__modpost: vmlinux.o
+
+quiet_cmd_modpost = MODPOST $@
+      cmd_modpost = $(MODPOST) $@
+
+PHONY += vmlinux.o
+vmlinux.o:
+       $(call cmd,modpost)
+
+else
+
 # When building external modules load the Kbuild file to retrieve EXTRA_SYMBOLS info
 ifneq ($(KBUILD_EXTMOD),)
 
@@ -58,50 +85,25 @@ endif
 
 include scripts/Makefile.lib
 
-kernelsymfile := $(objtree)/Module.symvers
-modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
-
-modorder := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order
-
-# Step 1), find all modules listed in modules.order
-ifdef CONFIG_MODULES
-modules := $(sort $(shell cat $(modorder)))
-endif
+# find all modules listed in modules.order
+modules := $(sort $(shell cat $(MODORDER)))
 
 # Stop after building .o files if NOFINAL is set. Makes compile tests quicker
-_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
-
-# Step 2), invoke modpost
-#  Includes step 3,4
-modpost = scripts/mod/modpost                    \
- $(if $(CONFIG_MODVERSIONS),-m)                  \
- $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,)       \
- $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile)   \
- $(if $(KBUILD_EXTMOD),-I $(modulesymfile))      \
- $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
- $(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
- $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E)  \
- $(if $(KBUILD_MODPOST_WARN),-w)
-
-MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
+__modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
+       @:
 
-# We can go over command line length here, so be careful.
-quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules
-      cmd_modpost = sed 's/ko$$/o/' $(modorder) | $(modpost) $(MODPOST_OPT) -s -T -
-
-PHONY += __modpost
-__modpost: $(modules:.ko=.o) FORCE
-       $(call cmd,modpost) $(wildcard vmlinux)
+MODPOST += $(subst -i,-n,$(filter -i,$(MAKEFLAGS))) -s -T - $(wildcard vmlinux)
 
-quiet_cmd_kernel-mod = MODPOST $@
-      cmd_kernel-mod = $(modpost) $@
+# We can go over command line length here, so be careful.
+quiet_cmd_modpost = MODPOST $(words $(modules)) modules
+      cmd_modpost = sed 's/ko$$/o/' $(MODORDER) | $(MODPOST)
 
-vmlinux.o: FORCE
-       $(call cmd,kernel-mod)
+PHONY += modules-modpost
+modules-modpost:
+       $(call cmd,modpost)
 
 # Declare generated files as targets for modpost
-$(modules:.ko=.mod.c): __modpost ;
-
+$(modules:.ko=.mod.c): modules-modpost
 
 # Step 5), compile all *.mod.c files
 
@@ -145,10 +147,10 @@ FORCE:
 # optimization, we don't need to read them if the target does not
 # exist, we will rebuild anyway in that case.
 
-cmd_files := $(wildcard $(foreach f,$(sort $(targets)),$(dir $(f)).$(notdir $(f)).cmd))
+existing-targets := $(wildcard $(sort $(targets)))
+
+-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
 
-ifneq ($(cmd_files),)
-  include $(cmd_files)
 endif
 
 .PHONY: $(PHONY)
index 988120e0fd67a073ed750a2469b92ff7f2d2662d..0f78d94abc351145b9607c17909e3ce14634e2e9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 // Check if refcount_t type and API should be used
 // instead of atomic_t type when dealing with refcounters
 //
index 7915823b92a5eedc94b2d0a2da8400a7ce5c2b35..c458696ef3a79039102ff9ca5a155a083975236b 100755 (executable)
@@ -21,9 +21,9 @@ _LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$'
 _VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
 
 # A kernel build generally has over 2000 entries in its compile_commands.json
-# database. If this code finds 500 or fewer, then warn the user that they might
+# database. If this code finds 300 or fewer, then warn the user that they might
 # not have all the .cmd files, and they might need to compile the kernel.
-_LOW_COUNT_THRESHOLD = 500
+_LOW_COUNT_THRESHOLD = 300
 
 
 def parse_arguments():
index 47f6f3ea07717e435e3ea6210f3b23b23d2f4eb4..bbaf293869956f509206b01154c47af19019e764 100755 (executable)
@@ -23,6 +23,12 @@ TMPFILE=$OUTFILE.tmp
 
 trap 'rm -f $OUTFILE $TMPFILE' EXIT
 
+# SPDX-License-Identifier with GPL variants must have "WITH Linux-syscall-note"
+if [ -n "$(sed -n -e "/SPDX-License-Identifier:.*GPL-/{/WITH Linux-syscall-note/!p}" $INFILE)" ]; then
+       echo "error: $INFILE: missing \"WITH Linux-syscall-note\" for SPDX-License-Identifier" >&2
+       exit 1
+fi
+
 sed -E -e '
        s/([[:space:](])(__user|__force|__iomem)[[:space:]]/\1/g
        s/__attribute_const__([[:space:]]|$)/\1/g
index 1134892599da98c84be4e69f358363609f940fab..3569d2dec37cebfc1e3eabd615d99ae706350454 100644 (file)
@@ -848,6 +848,7 @@ int conf_write(const char *name)
        const char *str;
        char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
        char *env;
+       int i;
        bool need_newline = false;
 
        if (!name)
@@ -930,6 +931,9 @@ next:
        }
        fclose(out);
 
+       for_all_symbols(i, sym)
+               sym->flags &= ~SYMBOL_WRITTEN;
+
        if (*tmpname) {
                if (is_same(name, tmpname)) {
                        conf_message("No change to %s", name);
index a7124f895b2454179827ccdc7850bdb48aae1085..915775eb2921b56c01d6c06cc6cb9daa786376a7 100755 (executable)
@@ -210,7 +210,7 @@ info LD vmlinux.o
 modpost_link vmlinux.o
 
 # modpost vmlinux.o to check for section mismatches
-${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
+${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
 
 info MODINFO modules.builtin.modinfo
 ${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
index f230e65329a293a6cec6f32fc6aad412e728fdf9..3b638c0e1a4fd8aa169901bc86954699a637e81a 100755 (executable)
@@ -83,6 +83,17 @@ sub check_missing(%)
        foreach my $prog (sort keys %missing) {
                my $is_optional = $missing{$prog};
 
+               # At least on some LTS distros like CentOS 7, texlive doesn't
+               # provide all packages we need. When such distros are
+               # detected, we have to disable PDF output.
+               #
+               # So, we need to ignore the packages that distros would
+               # need for LaTeX to work
+               if ($is_optional == 2 && !$pdf) {
+                       $optional--;
+                       next;
+               }
+
                if ($is_optional) {
                        print "Warning: better to also install \"$prog\".\n";
                } else {
@@ -333,10 +344,13 @@ sub give_debian_hints()
 
        if ($pdf) {
                check_missing_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
-                                  "fonts-dejavu", 1);
+                                  "fonts-dejavu", 2);
+
+               check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
+                                  "fonts-noto-cjk", 2);
        }
 
-       check_program("dvipng", 1) if ($pdf);
+       check_program("dvipng", 2) if ($pdf);
        check_missing(\%map);
 
        return if (!$need && !$optional);
@@ -363,6 +377,7 @@ sub give_redhat_hints()
        my @fedora_tex_pkgs = (
                "texlive-collection-fontsrecommended",
                "texlive-collection-latex",
+               "texlive-xecjk",
                "dejavu-sans-fonts",
                "dejavu-serif-fonts",
                "dejavu-sans-mono-fonts",
@@ -371,22 +386,45 @@ sub give_redhat_hints()
        #
        # Checks valid for RHEL/CentOS version 7.x.
        #
-       if (! $system_release =~ /Fedora/) {
+       my $old = 0;
+       my $rel;
+       $rel = $1 if ($system_release =~ /release\s+(\d+)/);
+
+       if (!($system_release =~ /Fedora/)) {
                $map{"virtualenv"} = "python-virtualenv";
-       }
 
-       my $release;
+               if ($rel && $rel < 8) {
+                       $old = 1;
+                       $pdf = 0;
+
+                       printf("Note: texlive packages on RHEL/CENTOS <= 7 are incomplete. Can't support PDF output\n");
+                       printf("If you want to build PDF, please read:\n");
+                       printf("\thttps://www.systutorials.com/241660/how-to-install-tex-live-on-centos-7-linux/\n");
+               }
+       } else {
+               if ($rel && $rel < 26) {
+                       $old = 1;
+               }
+       }
+       if (!$rel) {
+               printf("Couldn't identify release number\n");
+               $old = 1;
+               $pdf = 0;
+       }
 
-       $release = $1 if ($system_release =~ /Fedora\s+release\s+(\d+)/);
+       if ($pdf) {
+               check_missing_file("/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
+                                  "google-noto-sans-cjk-ttc-fonts", 2);
+       }
 
-       check_rpm_missing(\@fedora26_opt_pkgs, 1) if ($pdf && $release >= 26);
-       check_rpm_missing(\@fedora_tex_pkgs, 1) if ($pdf);
-       check_missing_tex(1) if ($pdf);
+       check_rpm_missing(\@fedora26_opt_pkgs, 2) if ($pdf && !$old);
+       check_rpm_missing(\@fedora_tex_pkgs, 2) if ($pdf);
+       check_missing_tex(2) if ($pdf);
        check_missing(\%map);
 
        return if (!$need && !$optional);
 
-       if ($release >= 18) {
+       if (!$old) {
                # dnf, for Fedora 18+
                printf("You should run:\n\n\tsudo dnf install -y $install\n");
        } else {
@@ -425,8 +463,15 @@ sub give_opensuse_hints()
                "texlive-zapfding",
        );
 
-       check_rpm_missing(\@suse_tex_pkgs, 1) if ($pdf);
-       check_missing_tex(1) if ($pdf);
+       $map{"latexmk"} = "texlive-latexmk-bin";
+
+       # FIXME: add support for installing CJK fonts
+       #
+       # I tried hard, but was unable to find a way to install
+       # "Noto Sans CJK SC" on openSUSE
+
+       check_rpm_missing(\@suse_tex_pkgs, 2) if ($pdf);
+       check_missing_tex(2) if ($pdf);
        check_missing(\%map);
 
        return if (!$need && !$optional);
@@ -450,7 +495,14 @@ sub give_mageia_hints()
                "texlive-fontsextra",
        );
 
-       check_rpm_missing(\@tex_pkgs, 1) if ($pdf);
+       $map{"latexmk"} = "texlive-collection-basic";
+
+       if ($pdf) {
+               check_missing_file("/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
+                                  "google-noto-sans-cjk-ttc-fonts", 2);
+       }
+
+       check_rpm_missing(\@tex_pkgs, 2) if ($pdf);
        check_missing(\%map);
 
        return if (!$need && !$optional);
@@ -473,7 +525,13 @@ sub give_arch_linux_hints()
                "texlive-latexextra",
                "ttf-dejavu",
        );
-       check_pacman_missing(\@archlinux_tex_pkgs, 1) if ($pdf);
+       check_pacman_missing(\@archlinux_tex_pkgs, 2) if ($pdf);
+
+       if ($pdf) {
+               check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
+                                  "noto-fonts-cjk", 2);
+       }
+
        check_missing(\%map);
 
        return if (!$need && !$optional);
@@ -492,15 +550,31 @@ sub give_gentoo_hints()
        );
 
        check_missing_file("/usr/share/fonts/dejavu/DejaVuSans.ttf",
-                          "media-fonts/dejavu", 1) if ($pdf);
+                          "media-fonts/dejavu", 2) if ($pdf);
+
+       if ($pdf) {
+               check_missing_file("/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf",
+                                  "media-fonts/noto-cjk", 2);
+       }
 
        check_missing(\%map);
 
        return if (!$need && !$optional);
 
        printf("You should run:\n\n");
-       printf("\tsudo su -c 'echo \"media-gfx/imagemagick svg png\" > /etc/portage/package.use/imagemagick'\n");
-       printf("\tsudo su -c 'echo \"media-gfx/graphviz cairo pdf\" > /etc/portage/package.use/graphviz'\n");
+
+       my $imagemagick = "media-gfx/imagemagick svg png";
+       my $cairo = "media-gfx/graphviz cairo pdf";
+       my $portage_imagemagick = "/etc/portage/package.use/imagemagick";
+       my $portage_cairo = "/etc/portage/package.use/graphviz";
+
+       if (qx(cat $portage_imagemagick) ne "$imagemagick\n") {
+               printf("\tsudo su -c 'echo \"$imagemagick\" > $portage_imagemagick'\n")
+       }
+       if (qx(cat $portage_cairo) ne  "$cairo\n") {
+               printf("\tsudo su -c 'echo \"$cairo\" > $portage_cairo'\n");
+       }
+
        printf("\tsudo emerge --ask $install\n");
 
 }
@@ -560,7 +634,7 @@ sub check_distros()
        my %map = (
                "sphinx-build" => "sphinx"
        );
-       check_missing_tex(1) if ($pdf);
+       check_missing_tex(2) if ($pdf);
        check_missing(\%map);
        print "I don't know distro $system_release.\n";
        print "So, I can't provide you a hint with the install procedure.\n";
@@ -589,11 +663,13 @@ sub check_needs()
        check_program("make", 0);
        check_program("gcc", 0);
        check_python_module("sphinx_rtd_theme", 1) if (!$virtualenv);
-       check_program("xelatex", 1) if ($pdf);
        check_program("dot", 1);
        check_program("convert", 1);
-       check_program("rsvg-convert", 1) if ($pdf);
-       check_program("latexmk", 1) if ($pdf);
+
+       # Extra PDF files - should use 2 for is_optional
+       check_program("xelatex", 2) if ($pdf);
+       check_program("rsvg-convert", 2) if ($pdf);
+       check_program("latexmk", 2) if ($pdf);
 
        check_distros();
 
index a1ffe2eb4d5f5f5eb87f4f544f8b4014070f2989..af4c979b38eedb80411654f140a11f6312861dc2 100644 (file)
@@ -61,6 +61,7 @@ choice
        config GCC_PLUGIN_STRUCTLEAK_BYREF
                bool "zero-init structs passed by reference (strong)"
                depends on GCC_PLUGINS
+               depends on !(KASAN && KASAN_STACK=1)
                select GCC_PLUGIN_STRUCTLEAK
                help
                  Zero-initialize any structures on the stack that may
@@ -70,9 +71,15 @@ choice
                  exposures, like CVE-2017-1000410:
                  https://git.kernel.org/linus/06e7e776ca4d3654
 
+                 As a side-effect, this keeps a lot of variables on the
+                 stack that can otherwise be optimized out, so combining
+                 this with CONFIG_KASAN_STACK can lead to a stack overflow
+                 and is disallowed.
+
        config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
                bool "zero-init anything passed by reference (very strong)"
                depends on GCC_PLUGINS
+               depends on !(KASAN && KASAN_STACK=1)
                select GCC_PLUGIN_STRUCTLEAK
                help
                  Zero-initialize any stack variables that may be passed
index 7325f382dbf43b5660d0f3938e0ce18b737bed6e..957b9e3e14924dff2c3ad5d8e647d77f9eff6860 100644 (file)
@@ -595,7 +595,7 @@ struct key *request_key_and_link(struct key_type *type,
 
        key = check_cached_key(&ctx);
        if (key)
-               return key;
+               goto error_free;
 
        /* search all the process keyrings for a key */
        rcu_read_lock();
index e73ec040e2509494d3d123ad8c47419b747a33f7..ecba39c93fd91f887026c3f9c8f6bc3270fc9225 100644 (file)
@@ -66,6 +66,9 @@ static void request_key_auth_describe(const struct key *key,
 {
        struct request_key_auth *rka = dereference_key_rcu(key);
 
+       if (!rka)
+               return;
+
        seq_puts(m, "key:");
        seq_puts(m, key->description);
        if (key_is_positive(key))
@@ -83,6 +86,9 @@ static long request_key_auth_read(const struct key *key,
        size_t datalen;
        long ret;
 
+       if (!rka)
+               return -EKEYREVOKED;
+
        datalen = rka->callout_len;
        ret = datalen;
 
index 9a94672e7adccff05901782c47a2473185e05831..ade69913106540e4e1918b88654a8914f3bbe29d 100644 (file)
@@ -1228,24 +1228,11 @@ hashalg_fail:
 
 static int __init init_digests(void)
 {
-       u8 digest[TPM_MAX_DIGEST_SIZE];
-       int ret;
-       int i;
-
-       ret = tpm_get_random(chip, digest, TPM_MAX_DIGEST_SIZE);
-       if (ret < 0)
-               return ret;
-       if (ret < TPM_MAX_DIGEST_SIZE)
-               return -EFAULT;
-
        digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests),
                          GFP_KERNEL);
        if (!digests)
                return -ENOMEM;
 
-       for (i = 0; i < chip->nr_allocated_banks; i++)
-               memcpy(digests[i].digest, digest, TPM_MAX_DIGEST_SIZE);
-
        return 0;
 }
 
index 624ccc6ac744512380ddbf8727f1e1aae5633a78..f8efaa9f647c1d994311d082e526eb5692b4af5c 100644 (file)
@@ -272,6 +272,8 @@ static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
        return v;
 }
 
+static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap);
+
 /*
  * Initialize a policy database structure.
  */
@@ -319,8 +321,10 @@ static int policydb_init(struct policydb *p)
 out:
        hashtab_destroy(p->filename_trans);
        hashtab_destroy(p->range_tr);
-       for (i = 0; i < SYM_NUM; i++)
+       for (i = 0; i < SYM_NUM; i++) {
+               hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
                hashtab_destroy(p->symtab[i].table);
+       }
        return rc;
 }
 
index e63a90ff27285fdd885240d03ea720dd9972d063..1f0a6eaa2d6a139188b88803aa43c8c9eb445792 100644 (file)
@@ -286,6 +286,11 @@ static int sidtab_reverse_lookup(struct sidtab *s, struct context *context,
                ++count;
        }
 
+       /* bail out if we already reached max entries */
+       rc = -EOVERFLOW;
+       if (count >= SIDTAB_MAX)
+               goto out_unlock;
+
        /* insert context into new entry */
        rc = -ENOMEM;
        dst = sidtab_do_lookup(s, count, 1);
index 7b977b753a0331c9a8cddbc4d4537dbe248c5ac1..7985dd8198b6c4ae066d38041aeb3d45c6947ab8 100644 (file)
@@ -122,17 +122,12 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx,
                                                      vendor_id);
 
        ret = device_add(&codec->dev);
-       if (ret)
-               goto err_free_codec;
+       if (ret) {
+               put_device(&codec->dev);
+               return ret;
+       }
 
        return 0;
-err_free_codec:
-       of_node_put(codec->dev.of_node);
-       put_device(&codec->dev);
-       kfree(codec);
-       ac97_ctrl->codecs[idx] = NULL;
-
-       return ret;
 }
 
 unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv,
index 99b8821587053da0336e58586ca2ec55bff5f0e3..41905afada63fee667d34478301217e05b98d3c5 100644 (file)
@@ -574,10 +574,7 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
                stream->metadata_set = false;
                stream->next_track = false;
 
-               if (stream->direction == SND_COMPRESS_PLAYBACK)
-                       stream->runtime->state = SNDRV_PCM_STATE_SETUP;
-               else
-                       stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+               stream->runtime->state = SNDRV_PCM_STATE_SETUP;
        } else {
                return -EPERM;
        }
@@ -693,8 +690,17 @@ static int snd_compr_start(struct snd_compr_stream *stream)
 {
        int retval;
 
-       if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+       switch (stream->runtime->state) {
+       case SNDRV_PCM_STATE_SETUP:
+               if (stream->direction != SND_COMPRESS_CAPTURE)
+                       return -EPERM;
+               break;
+       case SNDRV_PCM_STATE_PREPARED:
+               break;
+       default:
                return -EPERM;
+       }
+
        retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
        if (!retval)
                stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
@@ -705,9 +711,15 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
 {
        int retval;
 
-       if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
-                       stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+       switch (stream->runtime->state) {
+       case SNDRV_PCM_STATE_OPEN:
+       case SNDRV_PCM_STATE_SETUP:
+       case SNDRV_PCM_STATE_PREPARED:
                return -EPERM;
+       default:
+               break;
+       }
+
        retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
        if (!retval) {
                snd_compr_drain_notify(stream);
@@ -795,9 +807,17 @@ static int snd_compr_drain(struct snd_compr_stream *stream)
 {
        int retval;
 
-       if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
-                       stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+       switch (stream->runtime->state) {
+       case SNDRV_PCM_STATE_OPEN:
+       case SNDRV_PCM_STATE_SETUP:
+       case SNDRV_PCM_STATE_PREPARED:
+       case SNDRV_PCM_STATE_PAUSED:
                return -EPERM;
+       case SNDRV_PCM_STATE_XRUN:
+               return -EPIPE;
+       default:
+               break;
+       }
 
        retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
        if (retval) {
@@ -817,6 +837,10 @@ static int snd_compr_next_track(struct snd_compr_stream *stream)
        if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
                return -EPERM;
 
+       /* next track doesn't have any meaning for capture streams */
+       if (stream->direction == SND_COMPRESS_CAPTURE)
+               return -EPERM;
+
        /* you can signal next track if this is intended to be a gapless stream
         * and current track metadata is set
         */
@@ -834,9 +858,23 @@ static int snd_compr_next_track(struct snd_compr_stream *stream)
 static int snd_compr_partial_drain(struct snd_compr_stream *stream)
 {
        int retval;
-       if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
-                       stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+
+       switch (stream->runtime->state) {
+       case SNDRV_PCM_STATE_OPEN:
+       case SNDRV_PCM_STATE_SETUP:
+       case SNDRV_PCM_STATE_PREPARED:
+       case SNDRV_PCM_STATE_PAUSED:
+               return -EPERM;
+       case SNDRV_PCM_STATE_XRUN:
+               return -EPIPE;
+       default:
+               break;
+       }
+
+       /* partial drain doesn't have any meaning for capture streams */
+       if (stream->direction == SND_COMPRESS_CAPTURE)
                return -EPERM;
+
        /* stream can be drained only when next track has been signalled */
        if (stream->next_track == false)
                return -EPERM;
index 860543a4c840207cda8e4a8c3ec873868b27b8ed..703857aab00fc17e6ca667fdcaf27e94200bc84f 100644 (file)
@@ -77,7 +77,7 @@ void snd_pcm_group_init(struct snd_pcm_group *group)
        spin_lock_init(&group->lock);
        mutex_init(&group->mutex);
        INIT_LIST_HEAD(&group->substreams);
-       refcount_set(&group->refs, 0);
+       refcount_set(&group->refs, 1);
 }
 
 /* define group lock helpers */
@@ -1096,8 +1096,7 @@ static void snd_pcm_group_unref(struct snd_pcm_group *group,
 
        if (!group)
                return;
-       do_free = refcount_dec_and_test(&group->refs) &&
-               list_empty(&group->substreams);
+       do_free = refcount_dec_and_test(&group->refs);
        snd_pcm_group_unlock(group, substream->pcm->nonatomic);
        if (do_free)
                kfree(group);
@@ -1874,6 +1873,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
                if (!to_check)
                        break; /* all drained */
                init_waitqueue_entry(&wait, current);
+               set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&to_check->sleep, &wait);
                snd_pcm_stream_unlock_irq(substream);
                if (runtime->no_period_wakeup)
@@ -1886,7 +1886,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
                        }
                        tout = msecs_to_jiffies(tout * 1000);
                }
-               tout = schedule_timeout_interruptible(tout);
+               tout = schedule_timeout(tout);
 
                snd_pcm_stream_lock_irq(substream);
                group = snd_pcm_stream_group_ref(substream);
@@ -2020,6 +2020,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        snd_pcm_group_lock_irq(target_group, nonatomic);
        snd_pcm_stream_lock(substream1);
        snd_pcm_group_assign(substream1, target_group);
+       refcount_inc(&target_group->refs);
        snd_pcm_stream_unlock(substream1);
        snd_pcm_group_unlock_irq(target_group, nonatomic);
  _end:
@@ -2056,13 +2057,14 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
        snd_pcm_group_lock_irq(group, nonatomic);
 
        relink_to_local(substream);
+       refcount_dec(&group->refs);
 
        /* detach the last stream, too */
        if (list_is_singular(&group->substreams)) {
                relink_to_local(list_first_entry(&group->substreams,
                                                 struct snd_pcm_substream,
                                                 link_list));
-               do_free = !refcount_read(&group->refs);
+               do_free = refcount_dec_and_test(&group->refs);
        }
 
        snd_pcm_group_unlock_irq(group, nonatomic);
index 7737b2670064dcd1b8c13af1b8b69a0ab5cd7997..6d9592f0ae1d53c42b3d7d59bfdc462f39a34f77 100644 (file)
@@ -1835,8 +1835,7 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
        if (cptr->type == USER_CLIENT) {
                info->input_pool = cptr->data.user.fifo_pool_size;
                info->input_free = info->input_pool;
-               if (cptr->data.user.fifo)
-                       info->input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool);
+               info->input_free = snd_seq_fifo_unused_cells(cptr->data.user.fifo);
        } else {
                info->input_pool = 0;
                info->input_free = 0;
index ea69261f269aa4be262cffe736d876c6136b2d78..eaaa8b5830bb6471616c2c4e0458ab469e6c4c85 100644 (file)
@@ -263,3 +263,20 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
 
        return 0;
 }
+
+/* get the number of unused cells safely */
+int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f)
+{
+       unsigned long flags;
+       int cells;
+
+       if (!f)
+               return 0;
+
+       snd_use_lock_use(&f->use_lock);
+       spin_lock_irqsave(&f->lock, flags);
+       cells = snd_seq_unused_cells(f->pool);
+       spin_unlock_irqrestore(&f->lock, flags);
+       snd_use_lock_free(&f->use_lock);
+       return cells;
+}
index edc68743943d7249bfc46c2a874c5d4602362644..b56a7b897c9c313f9b91be1069c1a84da2866132 100644 (file)
@@ -53,5 +53,7 @@ int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, poll_table
 /* resize pool in fifo */
 int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize);
 
+/* get the number of unused cells safely */
+int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f);
 
 #endif
index 9ea39348cdf5623db8c1a8a73fd9a26ecadee095..7c6d1c277d4d9e52a107c8079ff9f5a3254b4ac9 100644 (file)
@@ -248,7 +248,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
                unsigned int channels = params_channels(hw_params);
 
                mutex_lock(&oxfw->mutex);
-               err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
+               err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream,
                                                     rate, channels);
                if (err >= 0)
                        ++oxfw->substreams_count;
index 0d35359d25cd8643e5c5ab23fd00af6add754d73..0ecafd0c672271d08d844fe09c78c63fd5fccddf 100644 (file)
@@ -37,7 +37,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
        packets_per_page = PAGE_SIZE / packet_size;
        if (WARN_ON(!packets_per_page)) {
                err = -EINVAL;
-               goto error;
+               goto err_packets;
        }
        pages = DIV_ROUND_UP(count, packets_per_page);
 
index 1192c7561d62c61faa6be93178d6766d313a931c..3c2db3816029810eac81193a6d86554a10cb56cb 100644 (file)
@@ -136,10 +136,12 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
        if (!acomp)
                return -ENODEV;
        if (!acomp->ops) {
-               request_module("i915");
-               /* 60s timeout */
-               wait_for_completion_timeout(&bind_complete,
-                                           msecs_to_jiffies(60 * 1000));
+               if (!IS_ENABLED(CONFIG_MODULES) ||
+                   !request_module("i915")) {
+                       /* 60s timeout */
+                       wait_for_completion_timeout(&bind_complete,
+                                                  msecs_to_jiffies(60 * 1000));
+               }
        }
        if (!acomp->ops) {
                dev_info(bus->dev, "couldn't bind with audio component\n");
index 92390d457567effa041306600d1bc6c5962cad05..18e6546b44675c7f7deee917f3066b828896cb88 100644 (file)
@@ -824,6 +824,8 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
        while (id >= 0) {
                const struct hda_fixup *fix = codec->fixup_list + id;
 
+               if (++depth > 10)
+                       break;
                if (fix->chained_before)
                        apply_fixup(codec, fix->chain_id, action, depth + 1);
 
@@ -863,8 +865,6 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
                }
                if (!fix->chained || fix->chained_before)
                        break;
-               if (++depth > 10)
-                       break;
                id = fix->chain_id;
        }
 }
index e30e86ca6b72d5d1dd3ef34446315892c4119538..51f10ed9bc43205c8de07545f48588e050207d69 100644 (file)
@@ -2942,7 +2942,7 @@ static int hda_codec_runtime_resume(struct device *dev)
 static int hda_codec_force_resume(struct device *dev)
 {
        struct hda_codec *codec = dev_to_hda_codec(dev);
-       bool forced_resume = !codec->relaxed_resume;
+       bool forced_resume = !codec->relaxed_resume && codec->jacktbl.used;
        int ret;
 
        /* The get/put pair below enforces the runtime resume even if the
index c8d1b4316245f3ac02ca0b25bbe6f63b66eceb02..48d863736b3c32ed7da2d29ab73da0b741b08fdc 100644 (file)
@@ -598,11 +598,9 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        }
        runtime->private_data = azx_dev;
 
-       if (chip->gts_present)
-               azx_pcm_hw.info = azx_pcm_hw.info |
-                       SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
-
        runtime->hw = azx_pcm_hw;
+       if (chip->gts_present)
+               runtime->hw.info |= SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
        runtime->hw.channels_min = hinfo->channels_min;
        runtime->hw.channels_max = hinfo->channels_max;
        runtime->hw.formats = hinfo->formats;
@@ -615,6 +613,13 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
                                     20,
                                     178000000);
 
+       /* by some reason, the playback stream stalls on PulseAudio with
+        * tsched=1 when a capture stream triggers.  Until we figure out the
+        * real cause, disable tsched mode by telling the PCM info flag.
+        */
+       if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND)
+               runtime->hw.info |= SNDRV_PCM_INFO_BATCH;
+
        if (chip->align_buffer_size)
                /* constrain buffer sizes to be multiple of 128
                   bytes. This is more efficient in terms of memory
index baa15374fbcb4a38301fa7d5a5197a04ecb66e1b..f2a6df5e6bcb72cf222e40efda3bc2adabe66146 100644 (file)
@@ -31,7 +31,7 @@
 /* 14 unused */
 #define AZX_DCAPS_CTX_WORKAROUND (1 << 15)     /* X-Fi workaround */
 #define AZX_DCAPS_POSFIX_LPIB  (1 << 16)       /* Use LPIB as default */
-/* 17 unused */
+#define AZX_DCAPS_AMD_WORKAROUND (1 << 17)     /* AMD-specific workaround */
 #define AZX_DCAPS_NO_64BIT     (1 << 18)       /* No 64bit address */
 #define AZX_DCAPS_SYNC_WRITE   (1 << 19)       /* sync each cmd write */
 #define AZX_DCAPS_OLD_SSYNC    (1 << 20)       /* Old SSYNC reg for ICH */
index 485edaba0037e5d6a477d2eb0e8b62f75fe06858..10d502328b76eee5e480a777f691e29fd2884d23 100644 (file)
@@ -6009,7 +6009,8 @@ int snd_hda_gen_init(struct hda_codec *codec)
        if (spec->init_hook)
                spec->init_hook(codec);
 
-       snd_hda_apply_verbs(codec);
+       if (!spec->skip_verbs)
+               snd_hda_apply_verbs(codec);
 
        init_multi_out(codec);
        init_extra_out(codec);
@@ -6051,6 +6052,24 @@ void snd_hda_gen_free(struct hda_codec *codec)
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_free);
 
+/**
+ * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
+ * @codec: the HDA codec
+ *
+ * This can be put as patch_ops reboot_notify function.
+ */
+void snd_hda_gen_reboot_notify(struct hda_codec *codec)
+{
+       /* Make the codec enter D3 to avoid spurious noises from the internal
+        * speaker during (and after) reboot
+        */
+       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
+       snd_hda_codec_write(codec, codec->core.afg, 0,
+                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+       msleep(10);
+}
+EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
+
 #ifdef CONFIG_PM
 /**
  * snd_hda_gen_check_power_status - check the loopback power save state
@@ -6078,6 +6097,7 @@ static const struct hda_codec_ops generic_patch_ops = {
        .init = snd_hda_gen_init,
        .free = snd_hda_gen_free,
        .unsol_event = snd_hda_jack_unsol_event,
+       .reboot_notify = snd_hda_gen_reboot_notify,
 #ifdef CONFIG_PM
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
@@ -6100,7 +6120,7 @@ static int snd_hda_parse_generic_codec(struct hda_codec *codec)
 
        err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
        if (err < 0)
-               return err;
+               goto error;
 
        err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
        if (err < 0)
index 35a670a71c423097e8d65e19b283fe4118aea35f..fb9f1a90238bfb67d2a8079bf11b3dc012f86294 100644 (file)
@@ -243,6 +243,7 @@ struct hda_gen_spec {
        unsigned int indep_hp_enabled:1; /* independent HP enabled */
        unsigned int have_aamix_ctl:1;
        unsigned int hp_mic_jack_modes:1;
+       unsigned int skip_verbs:1; /* don't apply verbs at snd_hda_gen_init() */
 
        /* additional mute flags (only effective with auto_mute_via_amp=1) */
        u64 mute_bits;
@@ -332,6 +333,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                                  struct auto_pin_cfg *cfg);
 int snd_hda_gen_build_controls(struct hda_codec *codec);
 int snd_hda_gen_build_pcms(struct hda_codec *codec);
+void snd_hda_gen_reboot_notify(struct hda_codec *codec);
 
 /* standard jack event callbacks */
 void snd_hda_gen_hp_automute(struct hda_codec *codec,
index cb8b0945547cdf2c0382fdc7e0bdb794401150b8..99fc0917339bbef2e0911b7119ddf89072923999 100644 (file)
@@ -64,6 +64,7 @@ enum {
        POS_FIX_VIACOMBO,
        POS_FIX_COMBO,
        POS_FIX_SKL,
+       POS_FIX_FIFO,
 };
 
 /* Defines for ATI HD Audio support in SB450 south bridge */
@@ -135,7 +136,7 @@ module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 module_param_array(position_fix, int, NULL, 0444);
 MODULE_PARM_DESC(position_fix, "DMA pointer read method."
-                "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+).");
+                "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+, 6 = FIFO).");
 module_param_array(bdl_pos_adj, int, NULL, 0644);
 MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
 module_param_array(probe_mask, int, NULL, 0444);
@@ -313,11 +314,10 @@ enum {
 
 #define AZX_DCAPS_INTEL_SKYLAKE \
        (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
+        AZX_DCAPS_SYNC_WRITE |\
         AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
 
-#define AZX_DCAPS_INTEL_BROXTON \
-       (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
-        AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
+#define AZX_DCAPS_INTEL_BROXTON                AZX_DCAPS_INTEL_SKYLAKE
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -333,6 +333,11 @@ enum {
 #define AZX_DCAPS_PRESET_ATI_HDMI_NS \
        (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF)
 
+/* quirks for AMD SB */
+#define AZX_DCAPS_PRESET_AMD_SB \
+       (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_AMD_WORKAROUND |\
+        AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME)
+
 /* quirks for Nvidia */
 #define AZX_DCAPS_PRESET_NVIDIA \
        (AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\
@@ -842,6 +847,49 @@ static unsigned int azx_via_get_position(struct azx *chip,
        return bound_pos + mod_dma_pos;
 }
 
+#define AMD_FIFO_SIZE  32
+
+/* get the current DMA position with FIFO size correction */
+static unsigned int azx_get_pos_fifo(struct azx *chip, struct azx_dev *azx_dev)
+{
+       struct snd_pcm_substream *substream = azx_dev->core.substream;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       unsigned int pos, delay;
+
+       pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
+       if (!runtime)
+               return pos;
+
+       runtime->delay = AMD_FIFO_SIZE;
+       delay = frames_to_bytes(runtime, AMD_FIFO_SIZE);
+       if (azx_dev->insufficient) {
+               if (pos < delay) {
+                       delay = pos;
+                       runtime->delay = bytes_to_frames(runtime, pos);
+               } else {
+                       azx_dev->insufficient = 0;
+               }
+       }
+
+       /* correct the DMA position for capture stream */
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+               if (pos < delay)
+                       pos += azx_dev->core.bufsize;
+               pos -= delay;
+       }
+
+       return pos;
+}
+
+static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev,
+                                  unsigned int pos)
+{
+       struct snd_pcm_substream *substream = azx_dev->core.substream;
+
+       /* just read back the calculated value in the above */
+       return substream->runtime->delay;
+}
+
 static unsigned int azx_skl_get_dpib_pos(struct azx *chip,
                                         struct azx_dev *azx_dev)
 {
@@ -1418,6 +1466,7 @@ static int check_position_fix(struct azx *chip, int fix)
        case POS_FIX_VIACOMBO:
        case POS_FIX_COMBO:
        case POS_FIX_SKL:
+       case POS_FIX_FIFO:
                return fix;
        }
 
@@ -1434,6 +1483,10 @@ static int check_position_fix(struct azx *chip, int fix)
                dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n");
                return POS_FIX_VIACOMBO;
        }
+       if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) {
+               dev_dbg(chip->card->dev, "Using FIFO position fix\n");
+               return POS_FIX_FIFO;
+       }
        if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
                dev_dbg(chip->card->dev, "Using LPIB position fix\n");
                return POS_FIX_LPIB;
@@ -1454,6 +1507,7 @@ static void assign_position_fix(struct azx *chip, int fix)
                [POS_FIX_VIACOMBO] = azx_via_get_position,
                [POS_FIX_COMBO] = azx_get_pos_lpib,
                [POS_FIX_SKL] = azx_get_pos_skl,
+               [POS_FIX_FIFO] = azx_get_pos_fifo,
        };
 
        chip->get_position[0] = chip->get_position[1] = callbacks[fix];
@@ -1468,6 +1522,9 @@ static void assign_position_fix(struct azx *chip, int fix)
                        azx_get_delay_from_lpib;
        }
 
+       if (fix == POS_FIX_FIFO)
+               chip->get_delay[0] = chip->get_delay[1] =
+                       azx_get_delay_from_fifo;
 }
 
 /*
@@ -2448,6 +2505,12 @@ static const struct pci_device_id azx_ids[] = {
        /* AMD Hudson */
        { PCI_DEVICE(0x1022, 0x780d),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
+       /* AMD, X370 & co */
+       { PCI_DEVICE(0x1022, 0x1457),
+         .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
+       /* AMD, X570 & co */
+       { PCI_DEVICE(0x1022, 0x1487),
+         .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
        /* AMD Stoney */
        { PCI_DEVICE(0x1022, 0x157a),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
index 0d51823d7270eaf2629eabb15290e14d4839dec2..6d1fb7c11f17ed93b5ca4f2f12e295c3970b6ec4 100644 (file)
@@ -1175,6 +1175,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
        SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
        SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ),
        SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_SBZ),
+       SND_PCI_QUIRK(0x1102, 0x0027, "Sound Blaster Z", QUIRK_SBZ),
        SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", QUIRK_SBZ),
        SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
        SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
index 4f8d0845ee1efef11539478f56ced3ab436226c8..968d3caab6ac3e157f5eb4bee9f0990f30840d16 100644 (file)
@@ -163,23 +163,10 @@ static void cx_auto_reboot_notify(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
 
-       switch (codec->core.vendor_id) {
-       case 0x14f12008: /* CX8200 */
-       case 0x14f150f2: /* CX20722 */
-       case 0x14f150f4: /* CX20724 */
-               break;
-       default:
-               return;
-       }
-
        /* Turn the problematic codec into D3 to avoid spurious noises
           from the internal speaker during (and after) reboot */
        cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
-
-       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
-       snd_hda_codec_write(codec, codec->core.afg, 0,
-                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-       msleep(10);
+       snd_hda_gen_reboot_notify(codec);
 }
 
 static void cx_auto_free(struct hda_codec *codec)
@@ -624,18 +611,20 @@ static void cxt_fixup_hp_gate_mic_jack(struct hda_codec *codec,
 
 /* update LED status via GPIO */
 static void cxt_update_gpio_led(struct hda_codec *codec, unsigned int mask,
-                               bool enabled)
+                               bool led_on)
 {
        struct conexant_spec *spec = codec->spec;
        unsigned int oldval = spec->gpio_led;
 
        if (spec->mute_led_polarity)
-               enabled = !enabled;
+               led_on = !led_on;
 
-       if (enabled)
-               spec->gpio_led &= ~mask;
-       else
+       if (led_on)
                spec->gpio_led |= mask;
+       else
+               spec->gpio_led &= ~mask;
+       codec_dbg(codec, "mask:%d enabled:%d gpio_led:%d\n",
+                       mask, led_on, spec->gpio_led);
        if (spec->gpio_led != oldval)
                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
                                    spec->gpio_led);
@@ -646,8 +635,8 @@ static void cxt_fixup_gpio_mute_hook(void *private_data, int enabled)
 {
        struct hda_codec *codec = private_data;
        struct conexant_spec *spec = codec->spec;
-
-       cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, enabled);
+       /* muted -> LED on */
+       cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, !enabled);
 }
 
 /* turn on/off mic-mute LED via GPIO per capture hook */
@@ -669,7 +658,6 @@ static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
                { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03 },
                {}
        };
-       codec_info(codec, "action: %d gpio_led: %d\n", action, spec->gpio_led);
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                spec->gen.vmaster_mute.hook = cxt_fixup_gpio_mute_hook;
@@ -1083,6 +1071,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
  */
 
 static const struct hda_device_id snd_hda_id_conexant[] = {
+       HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto),
        HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto),
        HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto),
        HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto),
index de224cbea7a077b000ba95b9eed6eb1571a1510f..c1ddfd2fac522c8c5f663495ad3ad750f77b8120 100644 (file)
@@ -837,9 +837,11 @@ static int alc_init(struct hda_codec *codec)
        if (spec->init_hook)
                spec->init_hook(codec);
 
+       spec->gen.skip_verbs = 1; /* applied in below */
        snd_hda_gen_init(codec);
        alc_fix_pll(codec);
        alc_auto_init_amp(codec, spec->init_amp);
+       snd_hda_apply_verbs(codec); /* apply verbs here after own init */
 
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
 
@@ -869,15 +871,6 @@ static void alc_reboot_notify(struct hda_codec *codec)
                alc_shutup(codec);
 }
 
-/* power down codec to D3 at reboot/shutdown; set as reboot_notify ops */
-static void alc_d3_at_reboot(struct hda_codec *codec)
-{
-       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
-       snd_hda_codec_write(codec, codec->core.afg, 0,
-                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-       msleep(10);
-}
-
 #define alc_free       snd_hda_gen_free
 
 #ifdef CONFIG_PM
@@ -5152,7 +5145,7 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
        struct alc_spec *spec = codec->spec;
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-               spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */
+               spec->reboot_notify = snd_hda_gen_reboot_notify; /* reduce noise */
                spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
                codec->power_save_node = 0; /* avoid click noises */
                snd_hda_apply_pincfgs(codec, pincfgs);
@@ -5806,6 +5799,7 @@ enum {
        ALC286_FIXUP_ACER_AIO_HEADSET_MIC,
        ALC256_FIXUP_ASUS_MIC_NO_PRESENCE,
        ALC299_FIXUP_PREDATOR_SPK,
+       ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -6846,6 +6840,16 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                }
        },
+       [ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x14, 0x411111f0 }, /* disable confusing internal speaker */
+                       { 0x19, 0x04a11150 }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6987,6 +6991,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+       SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+       SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -7003,6 +7009,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
        SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
@@ -7080,6 +7087,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x312a, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
        SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
        SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
+       SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
        SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
@@ -8954,6 +8962,7 @@ static int patch_alc680(struct hda_codec *codec)
 static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0215, "ALC215", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0222, "ALC222", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
index a4ade6bb5bebea57f499f3d113eff5eec14ada1d..bc4dfafdfcd12757f76e4f78ee12b3ebb89acd62 100644 (file)
@@ -31,8 +31,8 @@ struct i2s_stream_instance {
        u16 num_pages;
        u16 channels;
        u32 xfer_resolution;
-       struct page *pg;
        u64 bytescount;
+       dma_addr_t dma_addr;
        void __iomem *acp3x_base;
 };
 
@@ -211,9 +211,8 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
 static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 {
        u16 page_idx;
-       u64 addr;
        u32 low, high, val, acp_fifo_addr;
-       struct page *pg = rtd->pg;
+       dma_addr_t addr = rtd->dma_addr;
 
        /* 8 scratch registers used to map one 64 bit address */
        if (direction == SNDRV_PCM_STREAM_PLAYBACK)
@@ -229,7 +228,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 
        for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
                /* Load the low address of page int ACP SRAM through SRBM */
-               addr = page_to_phys(pg);
                low = lower_32_bits(addr);
                high = upper_32_bits(addr);
 
@@ -239,7 +237,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
                                + 4);
                /* Move to next physically contiguos page */
                val += 8;
-               pg++;
+               addr += PAGE_SIZE;
        }
 
        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -341,7 +339,6 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
 {
        int status;
        u64 size;
-       struct page *pg;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct i2s_stream_instance *rtd = runtime->private_data;
 
@@ -354,9 +351,8 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
                return status;
 
        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
-       pg = virt_to_page(substream->dma_buffer.area);
-       if (pg) {
-               rtd->pg = pg;
+       if (substream->dma_buffer.area) {
+               rtd->dma_addr = substream->dma_buffer.addr;
                rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
                config_acp3x_dma(rtd, substream->stream);
                status = 0;
@@ -385,9 +381,11 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
 
 static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
+                                                                   DRV_NAME);
+       struct device *parent = component->dev->parent;
        snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
-                                             rtd->pcm->card->dev,
-                                             MIN_BUFFER, MAX_BUFFER);
+                                             parent, MIN_BUFFER, MAX_BUFFER);
        return 0;
 }
 
index 6203f54d9f25831553ab670b81586e9c65ba14f0..5b049fcdba2013ee0398653bbf1f1ef8710620b9 100644 (file)
@@ -47,6 +47,7 @@ struct cs42xx8_priv {
        unsigned long sysclk;
        u32 tx_channels;
        struct gpio_desc *gpiod_reset;
+       u32 rate[2];
 };
 
 /* -127.5dB to 0dB with step of 0.5dB */
@@ -176,21 +177,27 @@ static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = {
 };
 
 struct cs42xx8_ratios {
-       unsigned int ratio;
-       unsigned char speed;
-       unsigned char mclk;
+       unsigned int mfreq;
+       unsigned int min_mclk;
+       unsigned int max_mclk;
+       unsigned int ratio[3];
 };
 
+/*
+ * According to reference mannual, define the cs42xx8_ratio struct
+ * MFreq2 | MFreq1 | MFreq0 |     Description     | SSM | DSM | QSM |
+ * 0      | 0      | 0      |1.029MHz to 12.8MHz  | 256 | 128 |  64 |
+ * 0      | 0      | 1      |1.536MHz to 19.2MHz  | 384 | 192 |  96 |
+ * 0      | 1      | 0      |2.048MHz to 25.6MHz  | 512 | 256 | 128 |
+ * 0      | 1      | 1      |3.072MHz to 38.4MHz  | 768 | 384 | 192 |
+ * 1      | x      | x      |4.096MHz to 51.2MHz  |1024 | 512 | 256 |
+ */
 static const struct cs42xx8_ratios cs42xx8_ratios[] = {
-       { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) },
-       { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) },
-       { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) },
-       { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) },
-       { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) },
-       { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) },
-       { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) },
-       { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) },
-       { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) }
+       { 0, 1029000, 12800000, {256, 128, 64} },
+       { 2, 1536000, 19200000, {384, 192, 96} },
+       { 4, 2048000, 25600000, {512, 256, 128} },
+       { 6, 3072000, 38400000, {768, 384, 192} },
+       { 8, 4096000, 51200000, {1024, 512, 256} },
 };
 
 static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai,
@@ -257,14 +264,68 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_component *component = dai->component;
        struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-       u32 ratio = cs42xx8->sysclk / params_rate(params);
-       u32 i, fm, val, mask;
+       u32 ratio[2];
+       u32 rate[2];
+       u32 fm[2];
+       u32 i, val, mask;
+       bool condition1, condition2;
 
        if (tx)
                cs42xx8->tx_channels = params_channels(params);
 
+       rate[tx]  = params_rate(params);
+       rate[!tx] = cs42xx8->rate[!tx];
+
+       ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0;
+       ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0;
+
+       /* Get functional mode for tx and rx according to rate */
+       for (i = 0; i < 2; i++) {
+               if (cs42xx8->slave_mode) {
+                       fm[i] = CS42XX8_FM_AUTO;
+               } else {
+                       if (rate[i] < 50000) {
+                               fm[i] = CS42XX8_FM_SINGLE;
+                       } else if (rate[i] > 50000 && rate[i] < 100000) {
+                               fm[i] = CS42XX8_FM_DOUBLE;
+                       } else if (rate[i] > 100000 && rate[i] < 200000) {
+                               fm[i] = CS42XX8_FM_QUAD;
+                       } else {
+                               dev_err(component->dev,
+                                       "unsupported sample rate\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
        for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
-               if (cs42xx8_ratios[i].ratio == ratio)
+               /* Is the ratio[tx] valid ? */
+               condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ?
+                       (cs42xx8_ratios[i].ratio[0] == ratio[tx] ||
+                       cs42xx8_ratios[i].ratio[1] == ratio[tx] ||
+                       cs42xx8_ratios[i].ratio[2] == ratio[tx]) :
+                       (cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) &&
+                       cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk &&
+                       cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk;
+
+               if (!ratio[tx])
+                       condition1 = true;
+
+               /* Is the ratio[!tx] valid ? */
+               condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ?
+                       (cs42xx8_ratios[i].ratio[0] == ratio[!tx] ||
+                       cs42xx8_ratios[i].ratio[1] == ratio[!tx] ||
+                       cs42xx8_ratios[i].ratio[2] == ratio[!tx]) :
+                       (cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx]));
+
+               if (!ratio[!tx])
+                       condition2 = true;
+
+               /*
+                * Both ratio[tx] and ratio[!tx] is valid, then we get
+                * a proper MFreq.
+                */
+               if (condition1 && condition2)
                        break;
        }
 
@@ -273,15 +334,31 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       mask = CS42XX8_FUNCMOD_MFREQ_MASK;
-       val = cs42xx8_ratios[i].mclk;
+       cs42xx8->rate[tx] = params_rate(params);
 
-       fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed;
+       mask = CS42XX8_FUNCMOD_MFREQ_MASK;
+       val = cs42xx8_ratios[i].mfreq;
 
        regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
                           CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask,
-                          CS42XX8_FUNCMOD_xC_FM(tx, fm) | val);
+                          CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val);
+
+       return 0;
+}
+
+static int cs42xx8_hw_free(struct snd_pcm_substream *substream,
+                          struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
+       bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
+       /* Clear stored rate */
+       cs42xx8->rate[tx] = 0;
+
+       regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
+                          CS42XX8_FUNCMOD_xC_FM_MASK(tx),
+                          CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO));
        return 0;
 }
 
@@ -302,6 +379,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = {
        .set_fmt        = cs42xx8_set_dai_fmt,
        .set_sysclk     = cs42xx8_set_dai_sysclk,
        .hw_params      = cs42xx8_hw_params,
+       .hw_free        = cs42xx8_hw_free,
        .digital_mute   = cs42xx8_digital_mute,
 };
 
index 6f0e28f903bfb1963de5248bbd7d63a2534dcb2c..16313b973eaa41b26694bd154626b0329575d31c 100644 (file)
 #include <sound/soc-dapm.h>
 
 struct max98357a_priv {
-       struct delayed_work enable_sdmode_work;
        struct gpio_desc *sdmode;
        unsigned int sdmode_delay;
 };
 
-static void max98357a_enable_sdmode_work(struct work_struct *work)
-{
-       struct max98357a_priv *max98357a =
-       container_of(work, struct max98357a_priv,
-                       enable_sdmode_work.work);
-
-       gpiod_set_value(max98357a->sdmode, 1);
-}
-
 static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
                int cmd, struct snd_soc_dai *dai)
 {
@@ -46,14 +36,12 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               queue_delayed_work(system_power_efficient_wq,
-                               &max98357a->enable_sdmode_work,
-                               msecs_to_jiffies(max98357a->sdmode_delay));
+               mdelay(max98357a->sdmode_delay);
+               gpiod_set_value(max98357a->sdmode, 1);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               cancel_delayed_work_sync(&max98357a->enable_sdmode_work);
                gpiod_set_value(max98357a->sdmode, 0);
                break;
        }
@@ -112,30 +100,25 @@ static int max98357a_platform_probe(struct platform_device *pdev)
        int ret;
 
        max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL);
-
        if (!max98357a)
                return -ENOMEM;
 
        max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev,
                                "sdmode", GPIOD_OUT_LOW);
-
        if (IS_ERR(max98357a->sdmode))
                return PTR_ERR(max98357a->sdmode);
 
        ret = device_property_read_u32(&pdev->dev, "sdmode-delay",
                                        &max98357a->sdmode_delay);
-
        if (ret) {
                max98357a->sdmode_delay = 0;
                dev_dbg(&pdev->dev,
-                       "no optional property 'sdmode-delay' found, default: no delay\n");
+                       "no optional property 'sdmode-delay' found, "
+                       "default: no delay\n");
        }
 
        dev_set_drvdata(&pdev->dev, max98357a);
 
-       INIT_DELAYED_WORK(&max98357a->enable_sdmode_work,
-                               max98357a_enable_sdmode_work);
-
        return devm_snd_soc_register_component(&pdev->dev,
                        &max98357a_component_driver,
                        &max98357a_dai_driver, 1);
index 528695cd6a1ca7fef5e2812d86fbe283f677b34e..8c601a3ebc27e123693dff0a3bf682cf0ce47be2 100644 (file)
@@ -267,6 +267,12 @@ static int max98373_dai_hw_params(struct snd_pcm_substream *substream,
        case 48000:
                sampling_rate = MAX98373_PCM_SR_SET1_SR_48000;
                break;
+       case 88200:
+               sampling_rate = MAX98373_PCM_SR_SET1_SR_88200;
+               break;
+       case 96000:
+               sampling_rate = MAX98373_PCM_SR_SET1_SR_96000;
+               break;
        default:
                dev_err(component->dev, "rate %d not supported\n",
                        params_rate(params));
index f6a37aa02f2665ea67dda2dcc4441763765b9f76..a59e51355a84ddba7ef8fc24695f4401459d56d3 100644 (file)
 #define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0)
 #define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0)
 #define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0)
+#define MAX98373_PCM_SR_SET1_SR_88200 (0x9 << 0)
+#define MAX98373_PCM_SR_SET1_SR_96000 (0xA << 0)
 
 /* MAX98373_R2028_PCM_SR_SETUP_2 */
 #define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4)
index cdc8314882bc8a8ced49109e55449522d87285d9..abcdeb92220147ec38a3e70d2aff2be27a015bfc 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PCM3060 I2C driver
 //
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
 
 #include <linux/i2c.h>
 #include <linux/module.h>
@@ -56,5 +56,5 @@ static struct i2c_driver pcm3060_i2c_driver = {
 module_i2c_driver(pcm3060_i2c_driver);
 
 MODULE_DESCRIPTION("PCM3060 I2C driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
 MODULE_LICENSE("GPL v2");
index f6f19fa80932b4920dcf6bf69bab60bd48429ead..3b79734b832bd36926359a230c2031a824b9d66b 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PCM3060 SPI driver
 //
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
 
 #include <linux/module.h>
 #include <linux/spi/spi.h>
@@ -55,5 +55,5 @@ static struct spi_driver pcm3060_spi_driver = {
 module_spi_driver(pcm3060_spi_driver);
 
 MODULE_DESCRIPTION("PCM3060 SPI driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
 MODULE_LICENSE("GPL v2");
index 32b26f1c22829d5ccb68537b50566ed797fec745..b2358069cf9b12269b0b8cb78050b8af2f1a6fa8 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PCM3060 codec driver
 //
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
 
 #include <linux/module.h>
 #include <sound/pcm_params.h>
@@ -342,5 +342,5 @@ int pcm3060_probe(struct device *dev)
 EXPORT_SYMBOL(pcm3060_probe);
 
 MODULE_DESCRIPTION("PCM3060 codec driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
 MODULE_LICENSE("GPL v2");
index 75931c9a9d85027b34d848de9758efb131fcd690..18d51e5dac2cb5f2b7a71f21229282edb52e14e3 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * PCM3060 codec driver
  *
- * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+ * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
  */
 
 #ifndef _SND_SOC_PCM3060_H
index 5605b660f4bfd4059ca7de8b85899dc78b498f43..0a6ff13d76e136fd6b3e130899ee75b81e09fa16 100644 (file)
@@ -39,7 +39,7 @@ static const struct reg_sequence init_list[] = {
        { RT1011_POWER_9, 0xa840 },
 
        { RT1011_ADC_SET_5, 0x0a20 },
-       { RT1011_DAC_SET_2, 0xa232 },
+       { RT1011_DAC_SET_2, 0xa032 },
        { RT1011_ADC_SET_1, 0x2925 },
 
        { RT1011_SPK_PRO_DC_DET_1, 0xb00c },
@@ -1917,7 +1917,7 @@ static int rt1011_set_bias_level(struct snd_soc_component *component,
                snd_soc_component_write(component,
                        RT1011_SYSTEM_RESET_2, 0x0000);
                snd_soc_component_write(component,
-                       RT1011_SYSTEM_RESET_3, 0x0000);
+                       RT1011_SYSTEM_RESET_3, 0x0001);
                snd_soc_component_write(component,
                        RT1011_SYSTEM_RESET_1, 0x003f);
                snd_soc_component_write(component,
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 30a4e8399ec38eef1de4ac8e26118c59f77894d9..288df245b2f07e16d42329a8da6cdb50b0a8fcd5 100644 (file)
@@ -63,6 +63,7 @@ static int graph_get_dai_id(struct device_node *ep)
        struct device_node *endpoint;
        struct of_endpoint info;
        int i, id;
+       const u32 *reg;
        int ret;
 
        /* use driver specified DAI ID if exist */
@@ -83,8 +84,9 @@ static int graph_get_dai_id(struct device_node *ep)
                        return info.id;
 
                node = of_get_parent(ep);
+               reg = of_get_property(node, "reg", NULL);
                of_node_put(node);
-               if (of_get_property(node, "reg", NULL))
+               if (reg)
                        return info.port;
        }
        node = of_graph_get_port_parent(ep);
@@ -208,10 +210,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        dev_dbg(dev, "link_of DPCM (%pOF)\n", ep);
 
-       of_node_put(ports);
-       of_node_put(port);
-       of_node_put(node);
-
        if (li->cpu) {
                int is_single_links = 0;
 
@@ -229,17 +227,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
                ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links);
                if (ret)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_parse_clk_cpu(dev, ep, dai_link, dai);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_set_dailink_name(dev, dai_link,
                                                   "fe.%s",
                                                   cpus->dai_name);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                /* card->num_links includes Codec */
                asoc_simple_canonicalize_cpu(dai_link, is_single_links);
@@ -263,17 +261,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
                ret = asoc_simple_parse_codec(ep, dai_link);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_parse_clk_codec(dev, ep, dai_link, dai);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_set_dailink_name(dev, dai_link,
                                                   "be.%s",
                                                   codecs->dai_name);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                /* check "prefix" from top node */
                snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
@@ -293,19 +291,23 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        ret = asoc_simple_parse_tdm(ep, dai);
        if (ret)
-               return ret;
+               goto out_put_node;
 
        ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep,
                                       NULL, &dai_link->dai_fmt);
        if (ret < 0)
-               return ret;
+               goto out_put_node;
 
        dai_link->dpcm_playback         = 1;
        dai_link->dpcm_capture          = 1;
        dai_link->ops                   = &graph_ops;
        dai_link->init                  = asoc_simple_dai_init;
 
-       return 0;
+out_put_node:
+       of_node_put(ports);
+       of_node_put(port);
+       of_node_put(node);
+       return ret;
 }
 
 static int graph_dai_link_of(struct asoc_simple_priv *priv,
index ac8678fe55ffc3a5e2dbf0322850f7d817728e27..556b1a789629d221a972d161b3c7efa6d8813717 100644 (file)
@@ -349,6 +349,13 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link)
        /* Assumes platform == cpu */
        if (!dai_link->platforms->of_node)
                dai_link->platforms->of_node = dai_link->cpus->of_node;
+
+       /*
+        * DPCM BE can be no platform.
+        * Alloced memory will be waste, but not leak.
+        */
+       if (!dai_link->platforms->of_node)
+               dai_link->num_platforms = 0;
 }
 EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform);
 
index e5cde0d5e63c991b37878c88787fed8262484bb1..ef849151ba563fd549f0b48e47eb7c5ddbecde95 100644 (file)
@@ -124,8 +124,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        li->link++;
 
-       of_node_put(node);
-
        /* For single DAI link & old style of DT node */
        if (is_top)
                prefix = PREFIX;
@@ -147,17 +145,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
                ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links);
                if (ret)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_set_dailink_name(dev, dai_link,
                                                   "fe.%s",
                                                   cpus->dai_name);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                asoc_simple_canonicalize_cpu(dai_link, is_single_links);
        } else {
@@ -180,17 +178,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
                ret = asoc_simple_parse_codec(np, dai_link);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_set_dailink_name(dev, dai_link,
                                                   "be.%s",
                                                   codecs->dai_name);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                /* check "prefix" from top node */
                snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
@@ -208,19 +206,21 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        ret = asoc_simple_parse_tdm(np, dai);
        if (ret)
-               return ret;
+               goto out_put_node;
 
        ret = asoc_simple_parse_daifmt(dev, node, codec,
                                       prefix, &dai_link->dai_fmt);
        if (ret < 0)
-               return ret;
+               goto out_put_node;
 
        dai_link->dpcm_playback         = 1;
        dai_link->dpcm_capture          = 1;
        dai_link->ops                   = &simple_ops;
        dai_link->init                  = asoc_simple_dai_init;
 
-       return 0;
+out_put_node:
+       of_node_put(node);
+       return ret;
 }
 
 static int simple_dai_link_of(struct asoc_simple_priv *priv,
@@ -364,8 +364,6 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
                        goto error;
                }
 
-               of_node_put(codec);
-
                /* get convert-xxx property */
                memset(&adata, 0, sizeof(adata));
                for_each_child_of_node(node, np)
@@ -387,11 +385,13 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
                                ret = func_noml(priv, np, codec, li, is_top);
 
                        if (ret < 0) {
+                               of_node_put(codec);
                                of_node_put(np);
                                goto error;
                        }
                }
 
+               of_node_put(codec);
                node = of_get_next_child(top, node);
        } while (!is_top && node);
 
index fac09be3cadea272bc1e25fbd9b667f10c188eb1..46612331f5ea7aa21bbf9e70b9945113cab67e5d 100644 (file)
@@ -437,6 +437,14 @@ static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = {
 
 /* Please keep this list alphabetically sorted */
 static const struct dmi_system_id byt_cht_es8316_quirk_table[] = {
+       {       /* Irbis NB41 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "NB41"),
+               },
+               .driver_data = (void *)(BYT_CHT_ES8316_INTMIC_IN2_MAP
+                                       | BYT_CHT_ES8316_JD_INVERTED),
+       },
        {       /* Teclast X98 Plus II */
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
index 229e395868684ebe6efe6aac220e2e489da3673c..4a5adae1d785d60ca5e6b679cae3debf3f85b388 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
+ * soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index b94b482ac34f8a1249799f222179be72e8f129ac..1cc801ba92ebbbcfa52f2c34648f0cd9706f2b4f 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * soc-apci-intel-byt-match.c - tables and support for BYT ACPI enumeration.
+ * soc-acpi-intel-byt-match.c - tables and support for BYT ACPI enumeration.
  *
  * Copyright (c) 2017, Intel Corporation.
  */
index b7f11f6be1cf063045716a4cec33a2b17881185f..d0fb43c2b9f68639a6319f40b912501d71f4c004 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * soc-apci-intel-cht-match.c - tables and support for CHT ACPI enumeration.
+ * soc-acpi-intel-cht-match.c - tables and support for CHT ACPI enumeration.
  *
  * Copyright (c) 2017, Intel Corporation.
  */
index c36c0aa4f683250a18085d8adeb28779ec86099d..771b0ef21051e5c1fa68fa3e958fabf2bbd03a42 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
+ * soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index 616eb09e78a01abf2e83e2615882eaaa0621f4e1..60dea358fa041bbc7c66e428718a1d6a1e8141df 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-glk-match.c - tables and support for GLK ACPI enumeration.
+ * soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index 68ae43f7b4b2880468198eab3d0c90719b95122d..cc972d2ac6915672114cbf11111fc58104256d15 100644 (file)
@@ -2,7 +2,7 @@
 // Copyright (c) 2018, Intel Corporation.
 
 /*
- * soc-apci-intel-hda-match.c - tables and support for HDA+ACPI enumeration.
+ * soc-acpi-intel-hda-match.c - tables and support for HDA+ACPI enumeration.
  *
  */
 
index d27853e7a3696fc52dc40caccec729e49a8384c6..34eb0baaa951787c0c338233a7254d9ad408be09 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * soc-apci-intel-hsw-bdw-match.c - tables and support for ACPI enumeration.
+ * soc-acpi-intel-hsw-bdw-match.c - tables and support for ACPI enumeration.
  *
  * Copyright (c) 2017, Intel Corporation.
  */
index 0b430b9b3673681cdf25c2f85ee07b9954e2eda4..38977669b576539035a4edbafcd34924eed3dd64 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-icl-match.c - tables and support for ICL ACPI enumeration.
+ * soc-acpi-intel-icl-match.c - tables and support for ICL ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index 4b331058e8070af6f86f5ff6f37a64c5273ac1a4..e200baa11011871c7ab8f6b2b5c816d54cf8f25c 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-kbl-match.c - tables and support for KBL ACPI enumeration.
+ * soc-acpi-intel-kbl-match.c - tables and support for KBL ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index 0c9c0edd35b34d93949863f171555ebbda095534..42fa40a8d9326784fe66fb3324aca00cbabfdfd7 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-skl-match.c - tables and support for SKL ACPI enumeration.
+ * soc-acpi-intel-skl-match.c - tables and support for SKL ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index f60a71990f662acd40ea1e5cd22bc43464a4eba7..ac75838bbfabe9ec24974571a6761e5fa63ed5d7 100644 (file)
@@ -150,17 +150,17 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card)
 
        link = data->dai_link;
 
-       dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
-       if (!dlc)
-               return ERR_PTR(-ENOMEM);
+       for_each_child_of_node(node, np) {
+               dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
+               if (!dlc)
+                       return ERR_PTR(-ENOMEM);
 
-       link->cpus      = &dlc[0];
-       link->platforms = &dlc[1];
+               link->cpus      = &dlc[0];
+               link->platforms = &dlc[1];
 
-       link->num_cpus          = 1;
-       link->num_platforms     = 1;
+               link->num_cpus          = 1;
+               link->num_platforms     = 1;
 
-       for_each_child_of_node(node, np) {
                cpu = of_get_child_by_name(np, "cpu");
                codec = of_get_child_by_name(np, "codec");
 
index 0a34d0eb8dba919e81a5e18cbb8b0c43884161a7..88ebaf6e1880a3aafea7f1dd7a7614aef3e700ee 100644 (file)
@@ -326,7 +326,6 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
                val |= I2S_CHN_4;
                break;
        case 2:
-       case 1:
                val |= I2S_CHN_2;
                break;
        default:
@@ -459,7 +458,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
        },
        .capture = {
                .stream_name = "Capture",
-               .channels_min = 1,
+               .channels_min = 2,
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_8000_192000,
                .formats = (SNDRV_PCM_FMTBIT_S8 |
@@ -659,7 +658,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
        }
 
        if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
-               if (val >= 1 && val <= 8)
+               if (val >= 2 && val <= 8)
                        soc_dai->capture.channels_max = val;
        }
 
index c5fc24675a330531e5cbc27ca4e34c3ab729354e..782e534d4c0dd0c3d35024bda96320a562672027 100644 (file)
@@ -61,6 +61,37 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
        SOC_DAPM_PIN_SWITCH("Speaker"),
 };
 
+static int rk_jack_event(struct notifier_block *nb, unsigned long event,
+                        void *data)
+{
+       struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
+       struct snd_soc_dapm_context *dapm = &jack->card->dapm;
+
+       if (event & SND_JACK_MICROPHONE)
+               snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
+       else
+               snd_soc_dapm_disable_pin(dapm, "MICBIAS");
+
+       snd_soc_dapm_sync(dapm);
+
+       return 0;
+}
+
+static struct notifier_block rk_jack_nb = {
+       .notifier_call = rk_jack_event,
+};
+
+static int rk_init(struct snd_soc_pcm_runtime *runtime)
+{
+       /*
+        * The jack has already been created in the rk_98090_headset_init()
+        * function.
+        */
+       snd_soc_jack_notifier_register(&headset_jack, &rk_jack_nb);
+
+       return 0;
+}
+
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
@@ -119,6 +150,7 @@ SND_SOC_DAILINK_DEFS(hifi,
 static struct snd_soc_dai_link rk_dailink = {
        .name = "max98090",
        .stream_name = "Audio",
+       .init = rk_init,
        .ops = &rk_aif1_ops,
        /* set max98090 as slave */
        .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
index dfb6e460e7eb625879885ac0bcf71201c0a6b6b5..f0f5fa9c27d32a464e85a6aebd7fa3b8ad79bfb9 100644 (file)
@@ -284,9 +284,8 @@ static int odroid_audio_probe(struct platform_device *pdev)
        }
 
        of_node_put(cpu);
-       of_node_put(codec);
        if (ret < 0)
-               return ret;
+               goto err_put_node;
 
        ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link);
        if (ret < 0)
@@ -309,7 +308,6 @@ static int odroid_audio_probe(struct platform_device *pdev)
                ret = PTR_ERR(priv->clk_i2s_bus);
                goto err_put_sclk;
        }
-       of_node_put(cpu_dai);
 
        ret = devm_snd_soc_register_card(dev, card);
        if (ret < 0) {
@@ -317,6 +315,8 @@ static int odroid_audio_probe(struct platform_device *pdev)
                goto err_put_clk_i2s;
        }
 
+       of_node_put(cpu_dai);
+       of_node_put(codec);
        return 0;
 
 err_put_clk_i2s:
@@ -326,6 +326,8 @@ err_put_sclk:
 err_put_cpu_dai:
        of_node_put(cpu_dai);
        snd_soc_of_put_dai_link_codecs(codec_link);
+err_put_node:
+       of_node_put(codec);
        return ret;
 }
 
index fd6eaae6c0ed37e38da9fd8a66c5a621047cc20d..44f899b970c2a399bb3cf9b97ce4a93d9264f140 100644 (file)
@@ -1515,8 +1515,11 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
                }
        }
 
-       if (dai_link->dai_fmt)
-               snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
+       if (dai_link->dai_fmt) {
+               ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
+               if (ret)
+                       return ret;
+       }
 
        ret = soc_post_component_init(rtd, dai_link->name);
        if (ret)
index f013b24c050a17376ff7fe8237624adef1c5406e..2790c00735f3abaa4582fd95854b7134780ae869 100644 (file)
@@ -1157,8 +1157,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,
                list_add_tail(&widget->work_list, list);
 
        if (custom_stop_condition && custom_stop_condition(widget, dir)) {
-               widget->endpoints[dir] = 1;
-               return widget->endpoints[dir];
+               list = NULL;
+               custom_stop_condition = NULL;
        }
 
        if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) {
@@ -1195,8 +1195,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,
  *
  * Optionally, can be supplied with a function acting as a stopping condition.
  * This function takes the dapm widget currently being examined and the walk
- * direction as an arguments, it should return true if the walk should be
- * stopped and false otherwise.
+ * direction as an arguments, it should return true if widgets from that point
+ * in the graph onwards should not be added to the widget list.
  */
 static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
        struct list_head *list,
@@ -3706,6 +3706,8 @@ request_failed:
                dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
                        w->name, ret);
 
+       kfree_const(w->sname);
+       kfree(w);
        return ERR_PTR(ret);
 }
 
index f2b392998f20dea89b89a3062b948d584f670ae8..ffd8d43945374c65328e9d787bfe78e3ec2b124d 100644 (file)
@@ -101,8 +101,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
                /*
                 * This interrupt is not shared so no need to return IRQ_NONE.
                 */
-               dev_err_ratelimited(sdev->dev,
-                                   "error: nothing to do in IRQ thread\n");
+               dev_dbg_ratelimited(sdev->dev,
+                                   "nothing to do in IPC IRQ thread\n");
        }
 
        /* re-enable IPC interrupt */
index 50244b82600c017a9fe63f3dcb94edff4285ba86..2ecba91f5219d609f214b6697cd72e7758f21ec2 100644 (file)
@@ -224,8 +224,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
                /*
                 * This interrupt is not shared so no need to return IRQ_NONE.
                 */
-               dev_err_ratelimited(sdev->dev,
-                                   "error: nothing to do in IRQ thread\n");
+               dev_dbg_ratelimited(sdev->dev,
+                                   "nothing to do in IPC IRQ thread\n");
        }
 
        /* re-enable IPC interrupt */
index 9b2232908b6528a6adc10bf82bb9682d4e7c004c..7fa5c61169db00f103e7658020e60610534c4c84 100644 (file)
@@ -1002,8 +1002,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
        .field_rxchanmap        = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
        .field_txchansel        = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
        .field_rxchansel        = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
-       .get_sr                 = sun8i_i2s_get_sr_wss,
-       .get_wss                = sun8i_i2s_get_sr_wss,
+       .get_sr                 = sun4i_i2s_get_sr,
+       .get_wss                = sun4i_i2s_get_wss,
 };
 
 static int sun4i_i2s_init_regmap_fields(struct device *dev,
index ac59b509ead51de648b09cf8819131e1d13be9d2..bc7bf15ed7a44544b875dc35a4ce4ca73b406c03 100644 (file)
@@ -195,7 +195,7 @@ static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
 {
        u32 bit;
 
-       for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) {
+       for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AMUTE) {
                if (enable)
                        mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
                else
@@ -223,6 +223,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
        if (mcasp_is_synchronous(mcasp)) {
                mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
                mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+               mcasp_set_clk_pdir(mcasp, true);
        }
 
        /* Activate serializer(s) */
@@ -1256,6 +1257,28 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params,
+                                           struct snd_pcm_hw_rule *rule)
+{
+       struct davinci_mcasp_ruledata *rd = rule->private;
+       struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_mask nfmt;
+       int i, slot_width;
+
+       snd_mask_none(&nfmt);
+       slot_width = rd->mcasp->slot_width;
+
+       for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+               if (snd_mask_test(fmt, i)) {
+                       if (snd_pcm_format_width(i) <= slot_width) {
+                               snd_mask_set(&nfmt, i);
+                       }
+               }
+       }
+
+       return snd_mask_refine(fmt, &nfmt);
+}
+
 static const unsigned int davinci_mcasp_dai_rates[] = {
        8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
        88200, 96000, 176400, 192000,
@@ -1377,7 +1400,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
        struct davinci_mcasp_ruledata *ruledata =
                                        &mcasp->ruledata[substream->stream];
        u32 max_channels = 0;
-       int i, dir;
+       int i, dir, ret;
        int tdm_slots = mcasp->tdm_slots;
 
        /* Do not allow more then one stream per direction */
@@ -1406,6 +1429,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
                        max_channels++;
        }
        ruledata->serializers = max_channels;
+       ruledata->mcasp = mcasp;
        max_channels *= tdm_slots;
        /*
         * If the already active stream has less channels than the calculated
@@ -1431,20 +1455,22 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
                                   0, SNDRV_PCM_HW_PARAM_CHANNELS,
                                   &mcasp->chconstr[substream->stream]);
 
-       if (mcasp->slot_width)
-               snd_pcm_hw_constraint_minmax(substream->runtime,
-                                            SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-                                            8, mcasp->slot_width);
+       if (mcasp->slot_width) {
+               /* Only allow formats require <= slot_width bits on the bus */
+               ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                         SNDRV_PCM_HW_PARAM_FORMAT,
+                                         davinci_mcasp_hw_rule_slot_width,
+                                         ruledata,
+                                         SNDRV_PCM_HW_PARAM_FORMAT, -1);
+               if (ret)
+                       return ret;
+       }
 
        /*
         * If we rely on implicit BCLK divider setting we should
         * set constraints based on what we can provide.
         */
        if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
-               int ret;
-
-               ruledata->mcasp = mcasp;
-
                ret = snd_pcm_hw_rule_add(substream->runtime, 0,
                                          SNDRV_PCM_HW_PARAM_RATE,
                                          davinci_mcasp_hw_rule_rate,
index b730d97c4de6aca7c44ecedd2ee33fe1ada913b5..90d118cd91641cf9f0471324a02b8a3ac40e17a2 100644 (file)
@@ -275,7 +275,8 @@ retry:
                                goto retry;
                        }
                        spin_unlock(&sound_loader_lock);
-                       return -EBUSY;
+                       r = -EBUSY;
+                       goto fail;
                }
        }
 
index 71d5f540334a23ea2904cb41e67d066c588ee932..4c12cc5b53fda0dd5085cfec00c08cc28d86f53d 100644 (file)
@@ -72,7 +72,7 @@ int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe)
        struct usb_host_endpoint *ep;
 
        ep = usb_pipe_endpoint(dev, pipe);
-       if (usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
+       if (!ep || usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
                return -EINVAL;
        return 0;
 }
index 14fc1e1d5d132486db21a6874ea1b6e82f011b04..c406497c5919be31f4722a22a60ab65192706c5c 100644 (file)
@@ -600,14 +600,13 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
                ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
                                    hiface_pcm_out_urb_handler);
                if (ret < 0)
-                       return ret;
+                       goto error;
        }
 
        ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
        if (ret < 0) {
-               kfree(rt);
                dev_err(&chip->dev->dev, "Cannot create pcm instance\n");
-               return ret;
+               goto error;
        }
 
        pcm->private_data = rt;
@@ -620,4 +619,10 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
 
        chip->pcm = rt;
        return 0;
+
+error:
+       for (i = 0; i < PCM_N_URBS; i++)
+               kfree(rt->out_urbs[i].buffer);
+       kfree(rt);
+       return ret;
 }
index 2c03e0f6bf72d661226b73ddee90c087db8f4b6f..f70211e6b174fdc18553a222630c58643a7fed34 100644 (file)
@@ -550,6 +550,15 @@ int line6_init_pcm(struct usb_line6 *line6,
        line6pcm->volume_monitor = 255;
        line6pcm->line6 = line6;
 
+       spin_lock_init(&line6pcm->out.lock);
+       spin_lock_init(&line6pcm->in.lock);
+       line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
+
+       line6->line6pcm = line6pcm;
+
+       pcm->private_data = line6pcm;
+       pcm->private_free = line6_cleanup_pcm;
+
        line6pcm->max_packet_size_in =
                usb_maxpacket(line6->usbdev,
                        usb_rcvisocpipe(line6->usbdev, ep_read), 0);
@@ -562,15 +571,6 @@ int line6_init_pcm(struct usb_line6 *line6,
                return -EINVAL;
        }
 
-       spin_lock_init(&line6pcm->out.lock);
-       spin_lock_init(&line6pcm->in.lock);
-       line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
-
-       line6->line6pcm = line6pcm;
-
-       pcm->private_data = line6pcm;
-       pcm->private_free = line6_cleanup_pcm;
-
        err = line6_create_audio_out_urbs(line6pcm);
        if (err < 0)
                return err;
index f0662bd4e50fbf865d253ac2d516fdd173d10dad..27bf61c177c02e34315b1ae89c09d98422bc6f14 100644 (file)
@@ -368,7 +368,7 @@ static const struct line6_properties podhd_properties_table[] = {
                .name = "POD HD500",
                .capabilities   = LINE6_CAP_PCM
                                | LINE6_CAP_HWMON,
-               .altsetting = 1,
+               .altsetting = 0,
                .ep_ctrl_r = 0x81,
                .ep_ctrl_w = 0x01,
                .ep_audio_r = 0x86,
index 0d24c72c155fb36dcd53446aa6977239ad97af36..ed158f04de80f9c0a0b4c1bfbde24b1895bce543 100644 (file)
@@ -244,5 +244,5 @@ static struct usb_driver variax_driver = {
 
 module_usb_driver(variax_driver);
 
-MODULE_DESCRIPTION("Vairax Workbench USB driver");
+MODULE_DESCRIPTION("Variax Workbench USB driver");
 MODULE_LICENSE("GPL");
index 7498b5191b68e4cf0368599998160ec0eb17f29d..eceab19766dbc745e20c9cb09a82320c43c8a72a 100644 (file)
@@ -68,6 +68,7 @@ struct mixer_build {
        unsigned char *buffer;
        unsigned int buflen;
        DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS);
+       DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS);
        struct usb_audio_term oterm;
        const struct usbmix_name_map *map;
        const struct usbmix_selector_map *selector_map;
@@ -738,12 +739,13 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
                                       struct uac_mixer_unit_descriptor *desc)
 {
        int mu_channels;
-       void *c;
 
        if (desc->bLength < sizeof(*desc))
                return -EINVAL;
        if (!desc->bNrInPins)
                return -EINVAL;
+       if (desc->bLength < sizeof(*desc) + desc->bNrInPins)
+               return -EINVAL;
 
        switch (state->mixer->protocol) {
        case UAC_VERSION_1:
@@ -759,13 +761,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
                break;
        }
 
-       if (!mu_channels)
-               return 0;
-
-       c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
-       if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength)
-               return 0; /* no bmControls -> skip */
-
        return mu_channels;
 }
 
@@ -773,16 +768,25 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
  * parse the source unit recursively until it reaches to a terminal
  * or a branched unit.
  */
-static int check_input_term(struct mixer_build *state, int id,
+static int __check_input_term(struct mixer_build *state, int id,
                            struct usb_audio_term *term)
 {
        int protocol = state->mixer->protocol;
        int err;
        void *p1;
+       unsigned char *hdr;
 
        memset(term, 0, sizeof(*term));
-       while ((p1 = find_audio_control_unit(state, id)) != NULL) {
-               unsigned char *hdr = p1;
+       for (;;) {
+               /* a loop in the terminal chain? */
+               if (test_and_set_bit(id, state->termbitmap))
+                       return -EINVAL;
+
+               p1 = find_audio_control_unit(state, id);
+               if (!p1)
+                       break;
+
+               hdr = p1;
                term->id = id;
 
                if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
@@ -800,7 +804,7 @@ static int check_input_term(struct mixer_build *state, int id,
 
                                        /* call recursively to verify that the
                                         * referenced clock entity is valid */
-                                       err = check_input_term(state, d->bCSourceID, term);
+                                       err = __check_input_term(state, d->bCSourceID, term);
                                        if (err < 0)
                                                return err;
 
@@ -834,7 +838,7 @@ static int check_input_term(struct mixer_build *state, int id,
                        case UAC2_CLOCK_SELECTOR: {
                                struct uac_selector_unit_descriptor *d = p1;
                                /* call recursively to retrieve the channel info */
-                               err = check_input_term(state, d->baSourceID[0], term);
+                               err = __check_input_term(state, d->baSourceID[0], term);
                                if (err < 0)
                                        return err;
                                term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
@@ -897,7 +901,7 @@ static int check_input_term(struct mixer_build *state, int id,
 
                                /* call recursively to verify that the
                                 * referenced clock entity is valid */
-                               err = check_input_term(state, d->bCSourceID, term);
+                               err = __check_input_term(state, d->bCSourceID, term);
                                if (err < 0)
                                        return err;
 
@@ -948,7 +952,7 @@ static int check_input_term(struct mixer_build *state, int id,
                        case UAC3_CLOCK_SELECTOR: {
                                struct uac_selector_unit_descriptor *d = p1;
                                /* call recursively to retrieve the channel info */
-                               err = check_input_term(state, d->baSourceID[0], term);
+                               err = __check_input_term(state, d->baSourceID[0], term);
                                if (err < 0)
                                        return err;
                                term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
@@ -964,7 +968,7 @@ static int check_input_term(struct mixer_build *state, int id,
                                        return -EINVAL;
 
                                /* call recursively to retrieve the channel info */
-                               err = check_input_term(state, d->baSourceID[0], term);
+                               err = __check_input_term(state, d->baSourceID[0], term);
                                if (err < 0)
                                        return err;
 
@@ -982,6 +986,15 @@ static int check_input_term(struct mixer_build *state, int id,
        return -ENODEV;
 }
 
+
+static int check_input_term(struct mixer_build *state, int id,
+                           struct usb_audio_term *term)
+{
+       memset(term, 0, sizeof(*term));
+       memset(state->termbitmap, 0, sizeof(state->termbitmap));
+       return __check_input_term(state, id, term);
+}
+
 /*
  * Feature Unit
  */
@@ -1988,6 +2001,31 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
  * Mixer Unit
  */
 
+/* check whether the given in/out overflows bmMixerControls matrix */
+static bool mixer_bitmap_overflow(struct uac_mixer_unit_descriptor *desc,
+                                 int protocol, int num_ins, int num_outs)
+{
+       u8 *hdr = (u8 *)desc;
+       u8 *c = uac_mixer_unit_bmControls(desc, protocol);
+       size_t rest; /* remaining bytes after bmMixerControls */
+
+       switch (protocol) {
+       case UAC_VERSION_1:
+       default:
+               rest = 1; /* iMixer */
+               break;
+       case UAC_VERSION_2:
+               rest = 2; /* bmControls + iMixer */
+               break;
+       case UAC_VERSION_3:
+               rest = 6; /* bmControls + wMixerDescrStr */
+               break;
+       }
+
+       /* overflow? */
+       return c + (num_ins * num_outs + 7) / 8 + rest > hdr + hdr[0];
+}
+
 /*
  * build a mixer unit control
  *
@@ -2116,6 +2154,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
                if (err < 0)
                        return err;
                num_ins += iterm.channels;
+               if (mixer_bitmap_overflow(desc, state->mixer->protocol,
+                                         num_ins, num_outs))
+                       break;
                for (; ich < num_ins; ich++) {
                        int och, ich_has_controls = 0;
 
index 199fa157a411e4731fa56e477f0953b2c8fd68ea..27dcb3743690f7c29764fb978823f0f37ad9c977 100644 (file)
@@ -1155,17 +1155,17 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 {
        struct usb_mixer_interface *mixer;
        struct usb_mixer_elem_info *cval;
-       int unitid = 12; /* SamleRate ExtensionUnit ID */
+       int unitid = 12; /* SampleRate ExtensionUnit ID */
 
        list_for_each_entry(mixer, &chip->mixer_list, list) {
-               cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
-               if (cval) {
+               if (mixer->id_elems[unitid]) {
+                       cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
                        snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
                                                    cval->control << 8,
                                                    samplerate_id);
                        snd_usb_mixer_notify_id(mixer, unitid);
+                       break;
                }
-               break;
        }
 }
 
index 75b96929f76c5ee73cfb159a7f0ef557326f43fd..e4bbf79de956e1d8958d02ead1c907c5bd7ea2bc 100644 (file)
@@ -339,6 +339,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                ep = 0x81;
                ifnum = 2;
                goto add_sync_ep_from_ifnum;
+       case USB_ID(0x1397, 0x0001): /* Behringer UFX1604 */
        case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
                ep = 0x81;
                ifnum = 1;
index 7ee9d17d0143a1e17670871980034bfda28c3112..e852c7fd61097e566215fd87f8a298351057de04 100644 (file)
@@ -1043,6 +1043,7 @@ found_clock:
 
                pd = kzalloc(sizeof(*pd), GFP_KERNEL);
                if (!pd) {
+                       kfree(fp->chmap);
                        kfree(fp->rate_table);
                        kfree(fp);
                        return NULL;
index 4602464ebdfbfccd9296593ed5dd8b15f55305ff..a4217c1a5d01178c53346ea3f48ed3415aa956fd 100644 (file)
@@ -214,6 +214,18 @@ struct kvm_vcpu_events {
 #define KVM_REG_ARM_FW_REG(r)          (KVM_REG_ARM | KVM_REG_SIZE_U64 | \
                                         KVM_REG_ARM_FW | ((r) & 0xffff))
 #define KVM_REG_ARM_PSCI_VERSION       KVM_REG_ARM_FW_REG(0)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1    KVM_REG_ARM_FW_REG(1)
+       /* Higher values mean better protection. */
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL          0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL              1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED       2
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2    KVM_REG_ARM_FW_REG(2)
+       /* Higher values mean better protection. */
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL          0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN            1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL              2
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED       3
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED    (1U << 4)
 
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR      0
index d819a3e8b552b47bd3019eeef6c39ccc4500a6c9..9a507716ae2fe723624d7c7de3c1b88501d5f9a3 100644 (file)
@@ -229,6 +229,16 @@ struct kvm_vcpu_events {
 #define KVM_REG_ARM_FW_REG(r)          (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
                                         KVM_REG_ARM_FW | ((r) & 0xffff))
 #define KVM_REG_ARM_PSCI_VERSION       KVM_REG_ARM_FW_REG(0)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1    KVM_REG_ARM_FW_REG(1)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL          0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL              1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED       2
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2    KVM_REG_ARM_FW_REG(2)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL          0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN            1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL              2
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED       3
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED            (1U << 4)
 
 /* SVE registers */
 #define KVM_REG_ARM64_SVE              (0x15 << KVM_REG_ARM_COPROC_SHIFT)
index f33105bc5ca612eaa5cea7125bfc0c7a771f13f9..8601d824a9c69417247d8c19c043d71a3f71b724 100644 (file)
@@ -4,12 +4,8 @@
 #define MAP_DENYWRITE  0x0800
 #define MAP_EXECUTABLE 0x1000
 #define MAP_GROWSDOWN  0x0100
-#define MAP_HUGETLB    0x40000
 #define MAP_LOCKED     0x80
-#define MAP_NONBLOCK   0x10000
 #define MAP_NORESERVE   0x40
-#define MAP_POPULATE   0x8000
-#define MAP_STACK      0x20000
 #include <uapi/asm-generic/mman-common.h>
 /* MAP_32BIT is undefined on powerpc, fix it for perf */
 #define MAP_32BIT      0
index 38920eed8cbf11a754270cff08fad9831172b365..7b94dccc843d5de23af1a651b384ed35d1ee9e82 100644 (file)
@@ -4,12 +4,8 @@
 #define MAP_DENYWRITE  0x0800
 #define MAP_EXECUTABLE 0x1000
 #define MAP_GROWSDOWN  0x0200
-#define MAP_HUGETLB    0x40000
 #define MAP_LOCKED      0x100
-#define MAP_NONBLOCK   0x10000
 #define MAP_NORESERVE   0x40
-#define MAP_POPULATE   0x8000
-#define MAP_STACK      0x20000
 #include <uapi/asm-generic/mman-common.h>
 /* MAP_32BIT is undefined on sparc, fix it for perf */
 #define MAP_32BIT      0
index d6ab5b4d15e543800a7a7524517b495fa6305074..503d3f42da1676791d2c4f4a70bfad35743daf4c 100644 (file)
@@ -378,10 +378,11 @@ struct kvm_sync_regs {
        struct kvm_vcpu_events events;
 };
 
-#define KVM_X86_QUIRK_LINT0_REENABLED  (1 << 0)
-#define KVM_X86_QUIRK_CD_NW_CLEARED    (1 << 1)
-#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE  (1 << 2)
-#define KVM_X86_QUIRK_OUT_7E_INC_RIP   (1 << 3)
+#define KVM_X86_QUIRK_LINT0_REENABLED     (1 << 0)
+#define KVM_X86_QUIRK_CD_NW_CLEARED       (1 << 1)
+#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE     (1 << 2)
+#define KVM_X86_QUIRK_OUT_7E_INC_RIP      (1 << 3)
+#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
 
 #define KVM_STATE_NESTED_FORMAT_VMX    0
 #define KVM_STATE_NESTED_FORMAT_SVM    1       /* unused */
@@ -432,4 +433,17 @@ struct kvm_nested_state {
        } data;
 };
 
+/* for KVM_CAP_PMU_EVENT_FILTER */
+struct kvm_pmu_event_filter {
+       __u32 action;
+       __u32 nevents;
+       __u32 fixed_counter_bitmap;
+       __u32 flags;
+       __u32 pad[4];
+       __u64 events[0];
+};
+
+#define KVM_PMU_EVENT_ALLOW 0
+#define KVM_PMU_EVENT_DENY 1
+
 #endif /* _ASM_X86_KVM_H */
index d213ec5c3766db0dd5176c951b13e5f3c1514cfb..f0b0c90dd398246eb2882050d69c6b53ccca11af 100644 (file)
 
 #define VMX_ABORT_SAVE_GUEST_MSR_FAIL        1
 #define VMX_ABORT_LOAD_HOST_PDPTE_FAIL       2
-#define VMX_ABORT_VMCS_CORRUPTED             3
 #define VMX_ABORT_LOAD_HOST_MSR_FAIL         4
 
 #endif /* _UAPIVMX_H */
index 5215e0870bcbaf84e97db8c241260989ed74318f..6a71324be6283eccb0d816a72dd61f66b4527de6 100644 (file)
@@ -204,7 +204,11 @@ int do_pin_fd(int fd, const char *name)
        if (err)
                return err;
 
-       return bpf_obj_pin(fd, name);
+       err = bpf_obj_pin(fd, name);
+       if (err)
+               p_err("can't pin the object (%s): %s", name, strerror(errno));
+
+       return err;
 }
 
 int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
@@ -237,7 +241,7 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
 
        fd = get_fd_by_id(id);
        if (fd < 0) {
-               p_err("can't get prog by id (%u): %s", id, strerror(errno));
+               p_err("can't open object by id (%u): %s", id, strerror(errno));
                return -1;
        }
 
index 66f04a4846a587e8e48bf3a599082ee48c452c19..43fdbbfe41bb24eef44e91c984c4dd30f41a6798 100644 (file)
@@ -363,7 +363,9 @@ static int do_show(int argc, char **argv)
                if (fd < 0)
                        return -1;
 
-               return show_prog(fd);
+               err = show_prog(fd);
+               close(fd);
+               return err;
        }
 
        if (argc)
index c38686c4465646d495745cfa769a4b6d693829dd..2f2a3c7df3de89d3fdbabfae6bb43ef43fbf006f 100755 (executable)
@@ -13,7 +13,7 @@
 #      the script prints the string "Disabled" to stdout.
 #
 # Each Distro is expected to implement this script in a distro specific
-# fashion. For instance on Distros that ship with Network Manager enabled,
+# fashion. For instance, on Distros that ship with Network Manager enabled,
 # this script can be based on the Network Manager APIs for retrieving DHCP
 # information.
 
index d7e06fe0270eefb29343b82ce4971765c2a981d5..e9ef4ca6a6557e11f809f17a93103d42af7a0e39 100644 (file)
@@ -700,7 +700,7 @@ static void kvp_get_ipconfig_info(char *if_name,
 
 
        /*
-        * Gather the DNS  state.
+        * Gather the DNS state.
         * Since there is no standard way to get this information
         * across various distributions of interest; we just invoke
         * an external script that needs to be ported across distros
@@ -809,7 +809,7 @@ kvp_get_ip_info(int family, char *if_name, int op,
        int sn_offset = 0;
        int error = 0;
        char *buffer;
-       struct hv_kvp_ipaddr_value *ip_buffer;
+       struct hv_kvp_ipaddr_value *ip_buffer = NULL;
        char cidr_mask[5]; /* /xyz */
        int weight;
        int i;
@@ -1051,7 +1051,7 @@ static int parse_ip_val_buffer(char *in_buf, int *offset,
        char *start;
 
        /*
-        * in_buf has sequence of characters that are seperated by
+        * in_buf has sequence of characters that are separated by
         * the character ';'. The last sequence does not have the
         * terminating ";" character.
         */
@@ -1386,6 +1386,8 @@ int main(int argc, char *argv[])
                        daemonize = 0;
                        break;
                case 'h':
+                       print_usage(argv);
+                       exit(0);
                default:
                        print_usage(argv);
                        exit(EXIT_FAILURE);
@@ -1490,7 +1492,7 @@ int main(int argc, char *argv[])
                case KVP_OP_GET_IP_INFO:
                        kvp_ip_val = &hv_msg->body.kvp_ip_val;
 
-                       error =  kvp_mac_to_ip(kvp_ip_val);
+                       error = kvp_mac_to_ip(kvp_ip_val);
 
                        if (error)
                                hv_msg->error = error;
index 7ed9f85ef9085103e3d31f86390317fa62102bc9..d10fe35b7f259d4928816626d72d7986fde6dcba 100755 (executable)
@@ -12,7 +12,7 @@
 # be used to configure the interface.
 #
 # Each Distro is expected to implement this script in a distro specific
-# fashion. For instance on Distros that ship with Network Manager enabled,
+# fashion. For instance, on Distros that ship with Network Manager enabled,
 # this script can be based on the Network Manager APIs for configuring the
 # interface.
 #
index efe1e34dd91b40c0a117432b38122087e22f76c8..92902a88f671de94db15303b3e3dda45bbba4894 100644 (file)
@@ -42,7 +42,7 @@ static int vss_do_freeze(char *dir, unsigned int cmd)
         * If a partition is mounted more than once, only the first
         * FREEZE/THAW can succeed and the later ones will get
         * EBUSY/EINVAL respectively: there could be 2 cases:
-        * 1) a user may mount the same partition to differnt directories
+        * 1) a user may mount the same partition to different directories
         *  by mistake or on purpose;
         * 2) The subvolume of btrfs appears to have the same partition
         * mounted more than once.
@@ -218,6 +218,8 @@ int main(int argc, char *argv[])
                        daemonize = 0;
                        break;
                case 'h':
+                       print_usage(argv);
+                       exit(0);
                default:
                        print_usage(argv);
                        exit(EXIT_FAILURE);
index 55e7374bade0d5c581fbee36e3183b77b057858d..099f2c44dbed26e9b6fb8fa9e242fe8ed24ce825 100644 (file)
@@ -4,10 +4,10 @@
 import os
 from optparse import OptionParser
 
+help_msg = "print verbose messages. Try -vv, -vvv for  more verbose messages"
 parser = OptionParser()
-parser.add_option("-v", "--verbose", dest="verbose",
-                  help="print verbose messages. Try -vv, -vvv for \
-                       more verbose messages", action="count")
+parser.add_option(
+       "-v", "--verbose", dest="verbose", help=help_msg, action="count")
 
 (options, args) = parser.parse_args()
 
@@ -21,27 +21,28 @@ if not os.path.isdir(vmbus_sys_path):
        exit(-1)
 
 vmbus_dev_dict = {
-       '{0e0b6031-5213-4934-818b-38d90ced39db}' : '[Operating system shutdown]',
-       '{9527e630-d0ae-497b-adce-e80ab0175caf}' : '[Time Synchronization]',
-       '{57164f39-9115-4e78-ab55-382f3bd5422d}' : '[Heartbeat]',
-       '{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}' : '[Data Exchange]',
-       '{35fa2e29-ea23-4236-96ae-3a6ebacba440}' : '[Backup (volume checkpoint)]',
-       '{34d14be3-dee4-41c8-9ae7-6b174977c192}' : '[Guest services]',
-       '{525074dc-8985-46e2-8057-a307dc18a502}' : '[Dynamic Memory]',
-       '{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}' : 'Synthetic mouse',
-       '{f912ad6d-2b17-48ea-bd65-f927a61c7684}' : 'Synthetic keyboard',
-       '{da0a7802-e377-4aac-8e77-0558eb1073f8}' : 'Synthetic framebuffer adapter',
-       '{f8615163-df3e-46c5-913f-f2d2f965ed0e}' : 'Synthetic network adapter',
-       '{32412632-86cb-44a2-9b5c-50d1417354f5}' : 'Synthetic IDE Controller',
-       '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller',
-       '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter',
-       '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter',
-       '{44c4f61d-4444-4400-9d52-802e27ede19f}' : 'PCI Express pass-through',
-       '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]',
-       '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]',
-       '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]',
+       '{0e0b6031-5213-4934-818b-38d90ced39db}': '[Operating system shutdown]',
+       '{9527e630-d0ae-497b-adce-e80ab0175caf}': '[Time Synchronization]',
+       '{57164f39-9115-4e78-ab55-382f3bd5422d}': '[Heartbeat]',
+       '{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}': '[Data Exchange]',
+       '{35fa2e29-ea23-4236-96ae-3a6ebacba440}': '[Backup (volume checkpoint)]',
+       '{34d14be3-dee4-41c8-9ae7-6b174977c192}': '[Guest services]',
+       '{525074dc-8985-46e2-8057-a307dc18a502}': '[Dynamic Memory]',
+       '{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}': 'Synthetic mouse',
+       '{f912ad6d-2b17-48ea-bd65-f927a61c7684}': 'Synthetic keyboard',
+       '{da0a7802-e377-4aac-8e77-0558eb1073f8}': 'Synthetic framebuffer adapter',
+       '{f8615163-df3e-46c5-913f-f2d2f965ed0e}': 'Synthetic network adapter',
+       '{32412632-86cb-44a2-9b5c-50d1417354f5}': 'Synthetic IDE Controller',
+       '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}': 'Synthetic SCSI Controller',
+       '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}': 'Synthetic fiber channel adapter',
+       '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}': 'Synthetic RDMA adapter',
+       '{44c4f61d-4444-4400-9d52-802e27ede19f}': 'PCI Express pass-through',
+       '{276aacf4-ac15-426c-98dd-7521ad3f01fe}': '[Reserved system device]',
+       '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}': '[Reserved system device]',
+       '{3375baf4-9e15-4b30-b765-67acb10d607b}': '[Reserved system device]',
 }
 
+
 def get_vmbus_dev_attr(dev_name, attr):
        try:
                f = open('%s/%s/%s' % (vmbus_sys_path, dev_name, attr), 'r')
@@ -52,6 +53,7 @@ def get_vmbus_dev_attr(dev_name, attr):
 
        return lines
 
+
 class VMBus_Dev:
        pass
 
@@ -66,12 +68,13 @@ for f in os.listdir(vmbus_sys_path):
 
        chn_vp_mapping = get_vmbus_dev_attr(f, 'channel_vp_mapping')
        chn_vp_mapping = [c.strip() for c in chn_vp_mapping]
-       chn_vp_mapping = sorted(chn_vp_mapping,
-               key = lambda c : int(c.split(':')[0]))
+       chn_vp_mapping = sorted(
+               chn_vp_mapping, key=lambda c: int(c.split(':')[0]))
 
-       chn_vp_mapping = ['\tRel_ID=%s, target_cpu=%s' %
-                               (c.split(':')[0], c.split(':')[1])
-                                       for c in chn_vp_mapping]
+       chn_vp_mapping = [
+               '\tRel_ID=%s, target_cpu=%s' %
+               (c.split(':')[0], c.split(':')[1]) for c in chn_vp_mapping
+       ]
        d = VMBus_Dev()
        d.sysfs_path = '%s/%s' % (vmbus_sys_path, f)
        d.vmbus_id = vmbus_id
@@ -85,7 +88,7 @@ for f in os.listdir(vmbus_sys_path):
        vmbus_dev_list.append(d)
 
 
-vmbus_dev_list  = sorted(vmbus_dev_list, key = lambda d : int(d.vmbus_id))
+vmbus_dev_list = sorted(vmbus_dev_list, key=lambda d: int(d.vmbus_id))
 
 format0 = '%2s: %s'
 format1 = '%2s: Class_ID = %s - %s\n%s'
@@ -95,9 +98,15 @@ for d in vmbus_dev_list:
        if verbose == 0:
                print(('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc))
        elif verbose == 1:
-               print (('VMBUS ID ' + format1) %        \
-                       (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping))
+               print(
+                       ('VMBUS ID ' + format1) %
+                       (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping)
+               )
        else:
-               print (('VMBUS ID ' + format2) % \
-                       (d.vmbus_id, d.class_id, d.dev_desc, \
-                       d.device_id, d.sysfs_path, d.chn_vp_mapping))
+               print(
+                       ('VMBUS ID ' + format2) %
+                       (
+                               d.vmbus_id, d.class_id, d.dev_desc,
+                               d.device_id, d.sysfs_path, d.chn_vp_mapping
+                       )
+               )
index abd238d0f7a48d718728cacde7853c60846bc539..63b1f506ea678200d9433002e207ee9cf7996ad9 100644 (file)
 #define MAP_TYPE       0x0f            /* Mask for type of mapping */
 #define MAP_FIXED      0x10            /* Interpret addr exactly */
 #define MAP_ANONYMOUS  0x20            /* don't use a file */
-#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
-# define MAP_UNINITIALIZED 0x4000000   /* For anonymous mmap, memory could be uninitialized */
-#else
-# define MAP_UNINITIALIZED 0x0         /* Don't support this flag */
-#endif
 
-/* 0x0100 - 0x80000 flags are defined in asm-generic/mman.h */
+/* 0x0100 - 0x4000 flags are defined in asm-generic/mman.h */
+#define MAP_POPULATE           0x008000        /* populate (prefault) pagetables */
+#define MAP_NONBLOCK           0x010000        /* do not block on IO */
+#define MAP_STACK              0x020000        /* give out an address that is best suited for process/thread stacks */
+#define MAP_HUGETLB            0x040000        /* create a huge page mapping */
+#define MAP_SYNC               0x080000 /* perform synchronous page faults for the mapping */
 #define MAP_FIXED_NOREPLACE    0x100000        /* MAP_FIXED which doesn't unmap underlying mapping */
 
+#define MAP_UNINITIALIZED 0x4000000    /* For anonymous mmap, memory could be
+                                        * uninitialized */
+
 /*
  * Flags for mlock
  */
index 36c197fc44a0d5df08110715f11cb8b3eb6caff7..406f7718f9ad074fdbe7f457e82ecb403e4d8995 100644 (file)
@@ -9,13 +9,11 @@
 #define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
 #define MAP_LOCKED     0x2000          /* pages are locked */
 #define MAP_NORESERVE  0x4000          /* don't check for reservations */
-#define MAP_POPULATE   0x8000          /* populate (prefault) pagetables */
-#define MAP_NONBLOCK   0x10000         /* do not block on IO */
-#define MAP_STACK      0x20000         /* give out an address that is best suited for process/thread stacks */
-#define MAP_HUGETLB    0x40000         /* create a huge page mapping */
-#define MAP_SYNC       0x80000         /* perform synchronous page faults for the mapping */
 
-/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
+/*
+ * Bits [26:31] are reserved, see asm-generic/hugetlb_encode.h
+ * for MAP_HUGETLB usage
+ */
 
 #define MCL_CURRENT    1               /* lock all current mappings */
 #define MCL_FUTURE     2               /* lock all future mappings */
index a87904daf1034449980afb86b952a538f84b9da9..1be0e798e36218c1d1bbbf9b46b42b7deb9c9e57 100644 (file)
@@ -844,9 +844,15 @@ __SYSCALL(__NR_fsconfig, sys_fsconfig)
 __SYSCALL(__NR_fsmount, sys_fsmount)
 #define __NR_fspick 433
 __SYSCALL(__NR_fspick, sys_fspick)
+#define __NR_pidfd_open 434
+__SYSCALL(__NR_pidfd_open, sys_pidfd_open)
+#ifdef __ARCH_WANT_SYS_CLONE3
+#define __NR_clone3 435
+__SYSCALL(__NR_clone3, sys_clone3)
+#endif
 
 #undef __NR_syscalls
-#define __NR_syscalls 434
+#define __NR_syscalls 436
 
 /*
  * 32 bit systems traditionally used different
index 661d73f9a919996f88bec2c37e1e5543b8159373..8a5b2f8f8eb98b0f1f170960239327d420971354 100644 (file)
@@ -50,6 +50,7 @@ typedef unsigned int drm_handle_t;
 
 #else /* One of the BSDs */
 
+#include <stdint.h>
 #include <sys/ioccom.h>
 #include <sys/types.h>
 typedef int8_t   __s8;
index 3a73f5316766c4216416929f774e4c56f9f92024..328d05e77d9f6c6b3783dc67ba7316545bb9c0c3 100644 (file)
@@ -136,6 +136,8 @@ enum drm_i915_gem_engine_class {
 struct i915_engine_class_instance {
        __u16 engine_class; /* see enum drm_i915_gem_engine_class */
        __u16 engine_instance;
+#define I915_ENGINE_CLASS_INVALID_NONE -1
+#define I915_ENGINE_CLASS_INVALID_VIRTUAL -2
 };
 
 /**
@@ -355,6 +357,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_PERF_ADD_CONFIG       0x37
 #define DRM_I915_PERF_REMOVE_CONFIG    0x38
 #define DRM_I915_QUERY                 0x39
+#define DRM_I915_GEM_VM_CREATE         0x3a
+#define DRM_I915_GEM_VM_DESTROY                0x3b
 /* Must be kept compact -- no holes */
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
@@ -415,6 +419,8 @@ typedef struct _drm_i915_sarea {
 #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)
 #define DRM_IOCTL_I915_QUERY                   DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
+#define DRM_IOCTL_I915_GEM_VM_CREATE   DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
+#define DRM_IOCTL_I915_GEM_VM_DESTROY  DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -598,6 +604,12 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_MMAP_GTT_COHERENT   52
 
+/*
+ * Query whether DRM_I915_GEM_EXECBUFFER2 supports coordination of parallel
+ * execution through use of explicit fence support.
+ * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
+ */
+#define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
 /* Must be kept compact -- no holes and well documented */
 
 typedef struct drm_i915_getparam {
@@ -1120,7 +1132,16 @@ struct drm_i915_gem_execbuffer2 {
  */
 #define I915_EXEC_FENCE_ARRAY   (1<<19)
 
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
+/*
+ * Setting I915_EXEC_FENCE_SUBMIT implies that lower_32_bits(rsvd2) represent
+ * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
+ * the batch.
+ *
+ * Returns -EINVAL if the sync_file fd cannot be found.
+ */
+#define I915_EXEC_FENCE_SUBMIT         (1 << 20)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
 
 #define I915_EXEC_CONTEXT_ID_MASK      (0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
@@ -1464,8 +1485,9 @@ struct drm_i915_gem_context_create_ext {
        __u32 ctx_id; /* output: id of new context*/
        __u32 flags;
 #define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS       (1u << 0)
+#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE      (1u << 1)
 #define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \
-       (-(I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS << 1))
+       (-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1))
        __u64 extensions;
 };
 
@@ -1507,6 +1529,41 @@ struct drm_i915_gem_context_param {
  * On creation, all new contexts are marked as recoverable.
  */
 #define I915_CONTEXT_PARAM_RECOVERABLE 0x8
+
+       /*
+        * The id of the associated virtual memory address space (ppGTT) of
+        * this context. Can be retrieved and passed to another context
+        * (on the same fd) for both to use the same ppGTT and so share
+        * address layouts, and avoid reloading the page tables on context
+        * switches between themselves.
+        *
+        * See DRM_I915_GEM_VM_CREATE and DRM_I915_GEM_VM_DESTROY.
+        */
+#define I915_CONTEXT_PARAM_VM          0x9
+
+/*
+ * I915_CONTEXT_PARAM_ENGINES:
+ *
+ * Bind this context to operate on this subset of available engines. Henceforth,
+ * the I915_EXEC_RING selector for DRM_IOCTL_I915_GEM_EXECBUFFER2 operates as
+ * an index into this array of engines; I915_EXEC_DEFAULT selecting engine[0]
+ * and upwards. Slots 0...N are filled in using the specified (class, instance).
+ * Use
+ *     engine_class: I915_ENGINE_CLASS_INVALID,
+ *     engine_instance: I915_ENGINE_CLASS_INVALID_NONE
+ * to specify a gap in the array that can be filled in later, e.g. by a
+ * virtual engine used for load balancing.
+ *
+ * Setting the number of engines bound to the context to 0, by passing a zero
+ * sized argument, will revert back to default settings.
+ *
+ * See struct i915_context_param_engines.
+ *
+ * Extensions:
+ *   i915_context_engines_load_balance (I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE)
+ *   i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
+ */
+#define I915_CONTEXT_PARAM_ENGINES     0xa
 /* Must be kept compact -- no holes and well documented */
 
        __u64 value;
@@ -1540,9 +1597,10 @@ struct drm_i915_gem_context_param_sseu {
        struct i915_engine_class_instance engine;
 
        /*
-        * Unused for now. Must be cleared to zero.
+        * Unknown flags must be cleared to zero.
         */
        __u32 flags;
+#define I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX (1u << 0)
 
        /*
         * Mask of slices to enable for the context. Valid values are a subset
@@ -1570,12 +1628,115 @@ struct drm_i915_gem_context_param_sseu {
        __u32 rsvd;
 };
 
+/*
+ * i915_context_engines_load_balance:
+ *
+ * Enable load balancing across this set of engines.
+ *
+ * Into the I915_EXEC_DEFAULT slot [0], a virtual engine is created that when
+ * used will proxy the execbuffer request onto one of the set of engines
+ * in such a way as to distribute the load evenly across the set.
+ *
+ * The set of engines must be compatible (e.g. the same HW class) as they
+ * will share the same logical GPU context and ring.
+ *
+ * To intermix rendering with the virtual engine and direct rendering onto
+ * the backing engines (bypassing the load balancing proxy), the context must
+ * be defined to use a single timeline for all engines.
+ */
+struct i915_context_engines_load_balance {
+       struct i915_user_extension base;
+
+       __u16 engine_index;
+       __u16 num_siblings;
+       __u32 flags; /* all undefined flags must be zero */
+
+       __u64 mbz64; /* reserved for future use; must be zero */
+
+       struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(name__, N__) struct { \
+       struct i915_user_extension base; \
+       __u16 engine_index; \
+       __u16 num_siblings; \
+       __u32 flags; \
+       __u64 mbz64; \
+       struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
+/*
+ * i915_context_engines_bond:
+ *
+ * Constructed bonded pairs for execution within a virtual engine.
+ *
+ * All engines are equal, but some are more equal than others. Given
+ * the distribution of resources in the HW, it may be preferable to run
+ * a request on a given subset of engines in parallel to a request on a
+ * specific engine. We enable this selection of engines within a virtual
+ * engine by specifying bonding pairs, for any given master engine we will
+ * only execute on one of the corresponding siblings within the virtual engine.
+ *
+ * To execute a request in parallel on the master engine and a sibling requires
+ * coordination with a I915_EXEC_FENCE_SUBMIT.
+ */
+struct i915_context_engines_bond {
+       struct i915_user_extension base;
+
+       struct i915_engine_class_instance master;
+
+       __u16 virtual_index; /* index of virtual engine in ctx->engines[] */
+       __u16 num_bonds;
+
+       __u64 flags; /* all undefined flags must be zero */
+       __u64 mbz64[4]; /* reserved for future use; must be zero */
+
+       struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_ENGINES_BOND(name__, N__) struct { \
+       struct i915_user_extension base; \
+       struct i915_engine_class_instance master; \
+       __u16 virtual_index; \
+       __u16 num_bonds; \
+       __u64 flags; \
+       __u64 mbz64[4]; \
+       struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
+struct i915_context_param_engines {
+       __u64 extensions; /* linked chain of extension blocks, 0 terminates */
+#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0 /* see i915_context_engines_load_balance */
+#define I915_CONTEXT_ENGINES_EXT_BOND 1 /* see i915_context_engines_bond */
+       struct i915_engine_class_instance engines[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__, N__) struct { \
+       __u64 extensions; \
+       struct i915_engine_class_instance engines[N__]; \
+} __attribute__((packed)) name__
+
 struct drm_i915_gem_context_create_ext_setparam {
 #define I915_CONTEXT_CREATE_EXT_SETPARAM 0
        struct i915_user_extension base;
        struct drm_i915_gem_context_param param;
 };
 
+struct drm_i915_gem_context_create_ext_clone {
+#define I915_CONTEXT_CREATE_EXT_CLONE 1
+       struct i915_user_extension base;
+       __u32 clone_id;
+       __u32 flags;
+#define I915_CONTEXT_CLONE_ENGINES     (1u << 0)
+#define I915_CONTEXT_CLONE_FLAGS       (1u << 1)
+#define I915_CONTEXT_CLONE_SCHEDATTR   (1u << 2)
+#define I915_CONTEXT_CLONE_SSEU                (1u << 3)
+#define I915_CONTEXT_CLONE_TIMELINE    (1u << 4)
+#define I915_CONTEXT_CLONE_VM          (1u << 5)
+#define I915_CONTEXT_CLONE_UNKNOWN -(I915_CONTEXT_CLONE_VM << 1)
+       __u64 rsvd;
+};
+
 struct drm_i915_gem_context_destroy {
        __u32 ctx_id;
        __u32 pad;
@@ -1821,6 +1982,7 @@ struct drm_i915_perf_oa_config {
 struct drm_i915_query_item {
        __u64 query_id;
 #define DRM_I915_QUERY_TOPOLOGY_INFO    1
+#define DRM_I915_QUERY_ENGINE_INFO     2
 /* Must be kept compact -- no holes and well documented */
 
        /*
@@ -1919,6 +2081,47 @@ struct drm_i915_query_topology_info {
        __u8 data[];
 };
 
+/**
+ * struct drm_i915_engine_info
+ *
+ * Describes one engine and it's capabilities as known to the driver.
+ */
+struct drm_i915_engine_info {
+       /** Engine class and instance. */
+       struct i915_engine_class_instance engine;
+
+       /** Reserved field. */
+       __u32 rsvd0;
+
+       /** Engine flags. */
+       __u64 flags;
+
+       /** Capabilities of this engine. */
+       __u64 capabilities;
+#define I915_VIDEO_CLASS_CAPABILITY_HEVC               (1 << 0)
+#define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC    (1 << 1)
+
+       /** Reserved fields. */
+       __u64 rsvd1[4];
+};
+
+/**
+ * struct drm_i915_query_engine_info
+ *
+ * Engine info query enumerates all engines known to the driver by filling in
+ * an array of struct drm_i915_engine_info structures.
+ */
+struct drm_i915_query_engine_info {
+       /** Number of struct drm_i915_engine_info structs following. */
+       __u32 num_engines;
+
+       /** MBZ */
+       __u32 rsvd[3];
+
+       /** Marker for drm_i915_engine_info structures. */
+       struct drm_i915_engine_info engines[];
+};
+
 #if defined(__cplusplus)
 }
 #endif
index 4e455018da65f76126719936d8b0672331a3b51e..a5aa7d3ac6a116a7a8d3c08d840c37a70e42e7a4 100644 (file)
@@ -1466,8 +1466,8 @@ union bpf_attr {
  *             If no cookie has been set yet, generate a new cookie. Once
  *             generated, the socket cookie remains stable for the life of the
  *             socket. This helper can be useful for monitoring per socket
- *             networking traffic statistics as it provides a unique socket
- *             identifier per namespace.
+ *             networking traffic statistics as it provides a global socket
+ *             identifier that can be assumed unique.
  *     Return
  *             A 8-byte long non-decreasing number on success, or 0 if the
  *             socket field is missing inside *skb*.
@@ -1571,8 +1571,11 @@ union bpf_attr {
  *             but this is only implemented for native XDP (with driver
  *             support) as of this writing).
  *
- *             All values for *flags* are reserved for future usage, and must
- *             be left at zero.
+ *             The lower two bits of *flags* are used as the return code if
+ *             the map lookup fails. This is so that the return value can be
+ *             one of the XDP program return codes up to XDP_TX, as chosen by
+ *             the caller. Any higher bits in the *flags* argument must be
+ *             unset.
  *
  *             When used to redirect packets to net devices, this helper
  *             provides a high performance increase over **bpf_redirect**\ ().
index 7d113a9602f06801b948ebeaff2fa4bbbbed2ce5..4a8c02cafa9a1220cda77bc2dcf923bac9ab1fce 100644 (file)
@@ -695,6 +695,7 @@ enum {
        IFLA_VF_IB_NODE_GUID,   /* VF Infiniband node GUID */
        IFLA_VF_IB_PORT_GUID,   /* VF Infiniband port GUID */
        IFLA_VF_VLAN_LIST,      /* nested list of vlans, option for QinQ */
+       IFLA_VF_BROADCAST,      /* VF broadcast */
        __IFLA_VF_MAX,
 };
 
@@ -705,6 +706,10 @@ struct ifla_vf_mac {
        __u8 mac[32]; /* MAX_ADDR_LEN */
 };
 
+struct ifla_vf_broadcast {
+       __u8 broadcast[32];
+};
+
 struct ifla_vf_vlan {
        __u32 vf;
        __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
index c2152f3dd02d41a559f8d62221ea34313ca93277..5e3f12d5359e731290e499c0733e9b6fb496158e 100644 (file)
@@ -116,7 +116,7 @@ struct kvm_irq_level {
         * ACPI gsi notion of irq.
         * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
         * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
-        * For ARM: See Documentation/virtual/kvm/api.txt
+        * For ARM: See Documentation/virt/kvm/api.txt
         */
        union {
                __u32 irq;
@@ -995,6 +995,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_ARM_SVE 170
 #define KVM_CAP_ARM_PTRAUTH_ADDRESS 171
 #define KVM_CAP_ARM_PTRAUTH_GENERIC 172
+#define KVM_CAP_PMU_EVENT_FILTER 173
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1085,7 +1086,7 @@ struct kvm_xen_hvm_config {
  *
  * KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
  * the irqfd to operate in resampling mode for level triggered interrupt
- * emulation.  See Documentation/virtual/kvm/api.txt.
+ * emulation.  See Documentation/virt/kvm/api.txt.
  */
 #define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
 
@@ -1329,6 +1330,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_RMMU_INFO    _IOW(KVMIO,  0xb0, struct kvm_ppc_rmmu_info)
 /* Available with KVM_CAP_PPC_GET_CPU_CHAR */
 #define KVM_PPC_GET_CPU_CHAR     _IOR(KVMIO,  0xb1, struct kvm_ppc_cpu_char)
+/* Available with KVM_CAP_PMU_EVENT_FILTER */
+#define KVM_SET_PMU_EVENT_FILTER  _IOW(KVMIO,  0xb2, struct kvm_pmu_event_filter)
 
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE        _IOWR(KVMIO,  0xe0, struct kvm_create_device)
index ed4ee170bee2a5e7dc0c3cde35e1c5549799c427..b3105ac1381a8d8651f7f2fbe6b700bd745ead01 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef _UAPI_LINUX_SCHED_H
 #define _UAPI_LINUX_SCHED_H
 
+#include <linux/types.h>
+
 /*
  * cloning flags:
  */
 #define CLONE_NEWNET           0x40000000      /* New network namespace */
 #define CLONE_IO               0x80000000      /* Clone io context */
 
+/*
+ * Arguments for the clone3 syscall
+ */
+struct clone_args {
+       __aligned_u64 flags;
+       __aligned_u64 pidfd;
+       __aligned_u64 child_tid;
+       __aligned_u64 parent_tid;
+       __aligned_u64 exit_signal;
+       __aligned_u64 stack;
+       __aligned_u64 stack_size;
+       __aligned_u64 tls;
+};
+
 /*
  * Scheduling policies
  */
 #define SCHED_FLAG_RESET_ON_FORK       0x01
 #define SCHED_FLAG_RECLAIM             0x02
 #define SCHED_FLAG_DL_OVERRUN          0x04
+#define SCHED_FLAG_KEEP_POLICY         0x08
+#define SCHED_FLAG_KEEP_PARAMS         0x10
+#define SCHED_FLAG_UTIL_CLAMP_MIN      0x20
+#define SCHED_FLAG_UTIL_CLAMP_MAX      0x40
+
+#define SCHED_FLAG_KEEP_ALL    (SCHED_FLAG_KEEP_POLICY | \
+                                SCHED_FLAG_KEEP_PARAMS)
+
+#define SCHED_FLAG_UTIL_CLAMP  (SCHED_FLAG_UTIL_CLAMP_MIN | \
+                                SCHED_FLAG_UTIL_CLAMP_MAX)
 
 #define SCHED_FLAG_ALL (SCHED_FLAG_RESET_ON_FORK       | \
                         SCHED_FLAG_RECLAIM             | \
-                        SCHED_FLAG_DL_OVERRUN)
+                        SCHED_FLAG_DL_OVERRUN          | \
+                        SCHED_FLAG_KEEP_ALL            | \
+                        SCHED_FLAG_UTIL_CLAMP)
 
 #endif /* _UAPI_LINUX_SCHED_H */
index 964e87217be4eaf9b73354fe31cd259915e1d29b..78efe870c2b7c85c9814ac90c04e137618bfd866 100644 (file)
@@ -76,6 +76,26 @@ struct usbdevfs_connectinfo {
        unsigned char slow;
 };
 
+struct usbdevfs_conninfo_ex {
+       __u32 size;             /* Size of the structure from the kernel's */
+                               /* point of view. Can be used by userspace */
+                               /* to determine how much data can be       */
+                               /* used/trusted.                           */
+       __u32 busnum;           /* USB bus number, as enumerated by the    */
+                               /* kernel, the device is connected to.     */
+       __u32 devnum;           /* Device address on the bus.              */
+       __u32 speed;            /* USB_SPEED_* constants from ch9.h        */
+       __u8 num_ports;         /* Number of ports the device is connected */
+                               /* to on the way to the root hub. It may   */
+                               /* be bigger than size of 'ports' array so */
+                               /* userspace can detect overflows.         */
+       __u8 ports[7];          /* List of ports on the way from the root  */
+                               /* hub to the device. Current limit in     */
+                               /* USB specification is 7 tiers (root hub, */
+                               /* 5 intermediate hubs, device), which     */
+                               /* gives at most 6 port entries.           */
+};
+
 #define USBDEVFS_URB_SHORT_NOT_OK      0x01
 #define USBDEVFS_URB_ISO_ASAP          0x02
 #define USBDEVFS_URB_BULK_CONTINUATION 0x04
@@ -137,6 +157,7 @@ struct usbdevfs_hub_portinfo {
 #define USBDEVFS_CAP_REAP_AFTER_DISCONNECT     0x10
 #define USBDEVFS_CAP_MMAP                      0x20
 #define USBDEVFS_CAP_DROP_PRIVILEGES           0x40
+#define USBDEVFS_CAP_CONNINFO_EX               0x80
 
 /* USBDEVFS_DISCONNECT_CLAIM flags & struct */
 
@@ -197,5 +218,10 @@ struct usbdevfs_streams {
 #define USBDEVFS_FREE_STREAMS      _IOR('U', 29, struct usbdevfs_streams)
 #define USBDEVFS_DROP_PRIVILEGES   _IOW('U', 30, __u32)
 #define USBDEVFS_GET_SPEED         _IO('U', 31)
+/*
+ * Returns struct usbdevfs_conninfo_ex; length is variable to allow
+ * extending size of the data returned.
+ */
+#define USBDEVFS_CONNINFO_EX(len)  _IOC(_IOC_READ, 'U', 32, len)
 
 #endif /* _UAPI_LINUX_USBDEVICE_FS_H */
index 467224feb43b0fa56b5720aa0ff693ad42ce6b32..d821107f55f90ff5c823d4ff1c19432268132a84 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 /* Copyright (c) 2018 Facebook */
 
+#include <endian.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -419,9 +420,9 @@ done:
 
 static bool btf_check_endianness(const GElf_Ehdr *ehdr)
 {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#if __BYTE_ORDER == __LITTLE_ENDIAN
        return ehdr->e_ident[EI_DATA] == ELFDATA2LSB;
-#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#elif __BYTE_ORDER == __BIG_ENDIAN
        return ehdr->e_ident[EI_DATA] == ELFDATA2MSB;
 #else
 # error "Unrecognized __BYTE_ORDER__"
index 03748a7421466c66ad9649561eda2cde29dc9f70..bae8879cdf58ae659ae8bfa71da0cf3f3877b294 100644 (file)
 
 #include <stdbool.h>
 #include <stddef.h>
+#ifdef __GLIBC__
+#include <bits/wordsize.h>
+#else
+#include <bits/reg.h>
+#endif
 #include "libbpf_internal.h"
 
 static inline size_t hash_bits(size_t h, int bits)
index 794dd5064ae8a01d9628c3baade0605a24fa4f44..2b57d7ea78363a7c36da5540d67ff985a5e40963 100644 (file)
@@ -20,6 +20,7 @@
 #include <inttypes.h>
 #include <string.h>
 #include <unistd.h>
+#include <endian.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <asm/unistd.h>
@@ -181,7 +182,6 @@ struct bpf_program {
        bpf_program_clear_priv_t clear_priv;
 
        enum bpf_attach_type expected_attach_type;
-       int btf_fd;
        void *func_info;
        __u32 func_info_rec_size;
        __u32 func_info_cnt;
@@ -312,7 +312,6 @@ void bpf_program__unload(struct bpf_program *prog)
        prog->instances.nr = -1;
        zfree(&prog->instances.fds);
 
-       zclose(prog->btf_fd);
        zfree(&prog->func_info);
        zfree(&prog->line_info);
 }
@@ -391,7 +390,6 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx,
        prog->instances.fds = NULL;
        prog->instances.nr = -1;
        prog->type = BPF_PROG_TYPE_UNSPEC;
-       prog->btf_fd = -1;
 
        return 0;
 errout:
@@ -612,10 +610,10 @@ errout:
 
 static int bpf_object__check_endianness(struct bpf_object *obj)
 {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#if __BYTE_ORDER == __LITTLE_ENDIAN
        if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
                return 0;
-#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#elif __BYTE_ORDER == __BIG_ENDIAN
        if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
                return 0;
 #else
@@ -1377,8 +1375,13 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj)
                if (!has_datasec && kind == BTF_KIND_VAR) {
                        /* replace VAR with INT */
                        t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0);
-                       t->size = sizeof(int);
-                       *(int *)(t+1) = BTF_INT_ENC(0, 0, 32);
+                       /*
+                        * using size = 1 is the safest choice, 4 will be too
+                        * big and cause kernel BTF validation failure if
+                        * original variable took less than 4 bytes
+                        */
+                       t->size = 1;
+                       *(int *)(t+1) = BTF_INT_ENC(0, 0, 8);
                } else if (!has_datasec && kind == BTF_KIND_DATASEC) {
                        /* replace DATASEC with STRUCT */
                        struct btf_var_secinfo *v = (void *)(t + 1);
@@ -1500,6 +1503,12 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
                           BTF_ELF_SEC, err);
                btf__free(obj->btf);
                obj->btf = NULL;
+               /* btf_ext can't exist without btf, so free it as well */
+               if (obj->btf_ext) {
+                       btf_ext__free(obj->btf_ext);
+                       obj->btf_ext = NULL;
+               }
+
                if (bpf_object__is_btf_mandatory(obj))
                        return err;
        }
@@ -2276,9 +2285,6 @@ bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj,
                prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext);
        }
 
-       if (!insn_offset)
-               prog->btf_fd = btf__fd(obj->btf);
-
        return 0;
 }
 
@@ -2451,7 +2457,7 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        char *cp, errmsg[STRERR_BUFSIZE];
        int log_buf_size = BPF_LOG_BUF_SIZE;
        char *log_buf;
-       int ret;
+       int btf_fd, ret;
 
        if (!insns || !insns_cnt)
                return -EINVAL;
@@ -2466,7 +2472,12 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        load_attr.license = license;
        load_attr.kern_version = kern_version;
        load_attr.prog_ifindex = prog->prog_ifindex;
-       load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0;
+       /* if .BTF.ext was loaded, kernel supports associated BTF for prog */
+       if (prog->obj->btf_ext)
+               btf_fd = bpf_object__btf_fd(prog->obj);
+       else
+               btf_fd = -1;
+       load_attr.prog_btf_fd = btf_fd >= 0 ? btf_fd : 0;
        load_attr.func_info = prog->func_info;
        load_attr.func_info_rec_size = prog->func_info_rec_size;
        load_attr.func_info_cnt = prog->func_info_cnt;
@@ -4507,13 +4518,13 @@ struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt,
                                     const struct perf_buffer_opts *opts)
 {
        struct perf_buffer_params p = {};
-       struct perf_event_attr attr = {
-               .config = PERF_COUNT_SW_BPF_OUTPUT,
-               .type = PERF_TYPE_SOFTWARE,
-               .sample_type = PERF_SAMPLE_RAW,
-               .sample_period = 1,
-               .wakeup_events = 1,
-       };
+       struct perf_event_attr attr = { 0, };
+
+       attr.config = PERF_COUNT_SW_BPF_OUTPUT,
+       attr.type = PERF_TYPE_SOFTWARE;
+       attr.sample_type = PERF_SAMPLE_RAW;
+       attr.sample_period = 1;
+       attr.wakeup_events = 1;
 
        p.attr = &attr;
        p.sample_cb = opts ? opts->sample_cb : NULL;
@@ -4988,13 +4999,15 @@ int libbpf_num_possible_cpus(void)
        static const char *fcpu = "/sys/devices/system/cpu/possible";
        int len = 0, n = 0, il = 0, ir = 0;
        unsigned int start = 0, end = 0;
+       int tmp_cpus = 0;
        static int cpus;
        char buf[128];
        int error = 0;
        int fd = -1;
 
-       if (cpus > 0)
-               return cpus;
+       tmp_cpus = READ_ONCE(cpus);
+       if (tmp_cpus > 0)
+               return tmp_cpus;
 
        fd = open(fcpu, O_RDONLY);
        if (fd < 0) {
@@ -5017,7 +5030,7 @@ int libbpf_num_possible_cpus(void)
        }
        buf[len] = '\0';
 
-       for (ir = 0, cpus = 0; ir <= len; ir++) {
+       for (ir = 0, tmp_cpus = 0; ir <= len; ir++) {
                /* Each sub string separated by ',' has format \d+-\d+ or \d+ */
                if (buf[ir] == ',' || buf[ir] == '\0') {
                        buf[ir] = '\0';
@@ -5029,13 +5042,15 @@ int libbpf_num_possible_cpus(void)
                        } else if (n == 1) {
                                end = start;
                        }
-                       cpus += end - start + 1;
+                       tmp_cpus += end - start + 1;
                        il = ir + 1;
                }
        }
-       if (cpus <= 0) {
-               pr_warning("Invalid #CPUs %d from %s\n", cpus, fcpu);
+       if (tmp_cpus <= 0) {
+               pr_warning("Invalid #CPUs %d from %s\n", tmp_cpus, fcpu);
                return -EINVAL;
        }
-       return cpus;
+
+       WRITE_ONCE(cpus, tmp_cpus);
+       return tmp_cpus;
 }
index 5007b5d4fd2c51186a554fb03893dcabd7bef381..680e63066cf39c7f3bd06cdf645b05065060728e 100644 (file)
@@ -317,17 +317,16 @@ static int xsk_load_xdp_prog(struct xsk_socket *xsk)
 
 static int xsk_get_max_queues(struct xsk_socket *xsk)
 {
-       struct ethtool_channels channels;
-       struct ifreq ifr;
+       struct ethtool_channels channels = { .cmd = ETHTOOL_GCHANNELS };
+       struct ifreq ifr = {};
        int fd, err, ret;
 
        fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (fd < 0)
                return -errno;
 
-       channels.cmd = ETHTOOL_GCHANNELS;
        ifr.ifr_data = (void *)&channels;
-       strncpy(ifr.ifr_name, xsk->ifname, IFNAMSIZ - 1);
+       memcpy(ifr.ifr_name, xsk->ifname, IFNAMSIZ - 1);
        ifr.ifr_name[IFNAMSIZ - 1] = '\0';
        err = ioctl(fd, SIOCETHTOOL, &ifr);
        if (err && errno != EOPNOTSUPP) {
@@ -335,7 +334,7 @@ static int xsk_get_max_queues(struct xsk_socket *xsk)
                goto out;
        }
 
-       if (channels.max_combined == 0 || errno == EOPNOTSUPP)
+       if (err || channels.max_combined == 0)
                /* If the device says it has no channels, then all traffic
                 * is sent to a single stream, so max queues = 1.
                 */
@@ -517,7 +516,7 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
                err = -errno;
                goto out_socket;
        }
-       strncpy(xsk->ifname, ifname, IFNAMSIZ - 1);
+       memcpy(xsk->ifname, ifname, IFNAMSIZ - 1);
        xsk->ifname[IFNAMSIZ - 1] = '\0';
 
        err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
index 5f26620f13f56fdb2aec4668e0495a569f0bd049..176f2f084060955d3c979dd14ad36f3bd276f8ec 100644 (file)
@@ -1946,6 +1946,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
        struct alternative *alt;
        struct instruction *insn, *next_insn;
        struct section *sec;
+       u8 visited;
        int ret;
 
        insn = first;
@@ -1972,12 +1973,12 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
                        return 1;
                }
 
+               visited = 1 << state.uaccess;
                if (insn->visited) {
                        if (!insn->hint && !insn_state_match(insn, &state))
                                return 1;
 
-                       /* If we were here with AC=0, but now have AC=1, go again */
-                       if (insn->state.uaccess || !state.uaccess)
+                       if (insn->visited & visited)
                                return 0;
                }
 
@@ -2024,7 +2025,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
                } else
                        insn->state = state;
 
-               insn->visited = true;
+               insn->visited |= visited;
 
                if (!insn->ignore_alts) {
                        bool skip_orig = false;
index b881fafcf55d6011438287d172abb4429dd79b11..6d875ca6fce007358e6caf8069fb476ea04ed259 100644 (file)
@@ -33,8 +33,9 @@ struct instruction {
        unsigned int len;
        enum insn_type type;
        unsigned long immediate;
-       bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts;
+       bool alt_group, dead_end, ignore, hint, save, restore, ignore_alts;
        bool retpoline_safe;
+       u8 visited;
        struct symbol *call_dest;
        struct instruction *jump_dest;
        struct instruction *first_jump_src;
index 6d148a40551ceda23b590184e92cf632dc705f01..adc5a7e44b98223e6350908a417862541ef57513 100644 (file)
@@ -242,7 +242,7 @@ $(OUTPUT)doc.dep : $(wildcard *.txt) build-docdep.perl
        $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
        mv $@+ $@
 
--include $(OUPTUT)doc.dep
+-include $(OUTPUT)doc.dep
 
 _cmds_txt = cmds-ancillaryinterrogators.txt \
        cmds-ancillarymanipulators.txt \
index d4e2e18a5881be70729dcab035d3eeafcfbe0f8e..caaab28f8400fe3ddb57661abfc08ec2bd8cbb93 100644 (file)
@@ -228,11 +228,11 @@ OPTIONS
 
        With the metric option perf script can compute metrics for
        sampling periods, similar to perf stat. This requires
-       specifying a group with multiple metrics with the :S option
+       specifying a group with multiple events defining metrics with the :S option
        for perf record. perf will sample on the first event, and
-       compute metrics for all the events in the group. Please note
+       print computed metrics for all the events in the group. Please note
        that the metric computed is averaged over the whole sampling
-       period, not just for the sample point.
+       period (since the last sample), not just for the sample point.
 
        For sample events it's possible to display misc field with -F +misc option,
        following letters are displayed for each bit:
@@ -384,7 +384,7 @@ include::itrace.txt[]
        perf script --time 0%-10%,30%-40%
 
 --max-blocks::
-       Set the maximum number of program blocks to print with brstackasm for
+       Set the maximum number of program blocks to print with brstackinsn for
        each sample.
 
 --reltime::
index 5f54feb199777e7855b6fa571447d453d421b0cf..d030c87ed9f57d0589faa99615b59f49761da895 100644 (file)
@@ -126,7 +126,7 @@ vendor,family,model,stepping. For example: GenuineIntel,6,69,1
 
        HEADER_TOTAL_MEM = 10,
 
-An uint64_t with the total memory in bytes.
+An uint64_t with the total memory in kilobytes.
 
        HEADER_CMDLINE = 11,
 
index a19690a17291ebb52a9f0bccf97a356f4af6ade0..c8c86a0c9b793d6f5173d9bc2fa7bb60f7d23f6e 100644 (file)
@@ -6,8 +6,9 @@
 #include "machine.h"
 #include "api/fs/fs.h"
 #include "debug.h"
+#include "symbol.h"
 
-int arch__fix_module_text_start(u64 *start, const char *name)
+int arch__fix_module_text_start(u64 *start, u64 *size, const char *name)
 {
        u64 m_start = *start;
        char path[PATH_MAX];
@@ -17,7 +18,35 @@ int arch__fix_module_text_start(u64 *start, const char *name)
        if (sysfs__read_ull(path, (unsigned long long *)start) < 0) {
                pr_debug2("Using module %s start:%#lx\n", path, m_start);
                *start = m_start;
+       } else {
+               /* Successful read of the modules segment text start address.
+                * Calculate difference between module start address
+                * in memory and module text segment start address.
+                * For example module load address is 0x3ff8011b000
+                * (from /proc/modules) and module text segment start
+                * address is 0x3ff8011b870 (from file above).
+                *
+                * Adjust the module size and subtract the GOT table
+                * size located at the beginning of the module.
+                */
+               *size -= (*start - m_start);
        }
 
        return 0;
 }
+
+/* On s390 kernel text segment start is located at very low memory addresses,
+ * for example 0x10000. Modules are located at very high memory addresses,
+ * for example 0x3ff xxxx xxxx. The gap between end of kernel text segment
+ * and beginning of first module's text segment is very big.
+ * Therefore do not fill this gap and do not assign it to the kernel dso map.
+ */
+void arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+{
+       if (strchr(p->name, '[') == NULL && strchr(c->name, '['))
+               /* Last kernel symbol mapped to end of page */
+               p->end = roundup(p->end, page_size);
+       else
+               p->end = c->start;
+       pr_debug4("%s sym:%s end:%#lx\n", __func__, p->name, p->end);
+}
index b4e6f9e6204aa874f03337adc47f9bba0297f707..c29976eca4a8a86bdd2fc062b3e521afc0338301 100644 (file)
 431    common  fsconfig                __x64_sys_fsconfig
 432    common  fsmount                 __x64_sys_fsmount
 433    common  fspick                  __x64_sys_fspick
+434    common  pidfd_open              __x64_sys_pidfd_open
+435    common  clone3                  __x64_sys_clone3/ptregs
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
index a640ca7aaadaf5c170703a711d91a3fc072e01e5..513cb2f2fa32e08e3d4b531b4709d53b28c4b07a 100644 (file)
@@ -379,8 +379,10 @@ static u8 *alloc_data(ssize_t bytes0, int map_flags,
 
        /* Allocate and initialize all memory on CPU#0: */
        if (init_cpu0) {
-               orig_mask = bind_to_node(0);
-               bind_to_memnode(0);
+               int node = numa_node_of_cpu(0);
+
+               orig_mask = bind_to_node(node);
+               bind_to_memnode(node);
        }
 
        bytes = bytes0 + HPSIZE;
index 66d5a6658daf542489d5eed878b9ed0e1035498a..01931281040563358793d74151233c8989df1082 100644 (file)
@@ -173,7 +173,7 @@ static int set_tracing_cpumask(struct cpu_map *cpumap)
        int last_cpu;
 
        last_cpu = cpu_map__cpu(cpumap, cpumap->nr - 1);
-       mask_size = (last_cpu + 3) / 4 + 1;
+       mask_size = last_cpu / 4 + 2; /* one more byte for EOS */
        mask_size += last_cpu / 32; /* ',' is needed for every 32th cpus */
 
        cpumask = malloc(mask_size);
index 6418782951a4091f3f691feef9912d049ce9f1d2..3d0ffd41fb55777c2a0dec7cb9489aaffc794681 100644 (file)
@@ -698,6 +698,16 @@ __cmd_probe(int argc, const char **argv)
 
                ret = perf_add_probe_events(params.events, params.nevents);
                if (ret < 0) {
+
+                       /*
+                        * When perf_add_probe_events() fails it calls
+                        * cleanup_perf_probe_events(pevs, npevs), i.e.
+                        * cleanup_perf_probe_events(params.events, params.nevents), which
+                        * will call clear_perf_probe_event(), so set nevents to zero
+                        * to avoid cleanup_params() to call clear_perf_probe_event() again
+                        * on the same pevs.
+                        */
+                       params.nevents = 0;
                        pr_err_with_code("  Error: Failed to add events.", ret);
                        return ret;
                }
index 8f24865596af2fd5a6334f9c5fa10b726bc22956..0140ddb8dd0bd34883d0e6d848d9012dd8fe1c2b 100644 (file)
@@ -1059,7 +1059,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
 
                        printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
                        if (ip == end) {
-                               printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp,
+                               printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, ++insn, fp,
                                                            &total_cycles);
                                if (PRINT_FIELD(SRCCODE))
                                        printed += print_srccode(thread, x.cpumode, ip);
index b55a534b4de0be8ec98a8624526d4ced72971ae2..352cf39d7c2feb569914bacde2e66b01b5d51e42 100644 (file)
@@ -607,7 +607,13 @@ try_again:
         * group leaders.
         */
        read_counters(&(struct timespec) { .tv_nsec = t1-t0 });
-       perf_evlist__close(evsel_list);
+
+       /*
+        * We need to keep evsel_list alive, because it's processed
+        * later the evsel_list will be closed after.
+        */
+       if (!STAT_RECORD)
+               perf_evlist__close(evsel_list);
 
        return WEXITSTATUS(status);
 }
@@ -1997,6 +2003,7 @@ int cmd_stat(int argc, const char **argv)
                        perf_session__write_header(perf_stat.session, evsel_list, fd, true);
                }
 
+               perf_evlist__close(evsel_list);
                perf_session__delete(perf_stat.session);
        }
 
index 1a91a197cafb02124b9ca20cda355b7195c51fcd..d413761621b09673e5063a308e544e07c799da67 100644 (file)
@@ -453,6 +453,7 @@ static struct fixed {
        { "inst_retired.any_p", "event=0xc0" },
        { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03" },
        { "cpu_clk_unhalted.thread", "event=0x3c" },
+       { "cpu_clk_unhalted.core", "event=0x3c" },
        { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1" },
        { NULL, NULL},
 };
index 930b80f422e83b933d5688bab64862c45cdee987..aa597ae53747074a4f831acde0a0bc5b07c0cc46 100755 (executable)
@@ -3,10 +3,13 @@
 
 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
 
+# also as:
+# #define USBDEVFS_CONNINFO_EX(len)  _IOC(_IOC_READ, 'U', 32, len)
+
 printf "static const char *usbdevfs_ioctl_cmds[] = {\n"
-regex="^#[[:space:]]*define[[:space:]]+USBDEVFS_(\w+)[[:space:]]+_IO[WR]{0,2}\([[:space:]]*'U'[[:space:]]*,[[:space:]]*([[:digit:]]+).*"
-egrep $regex ${header_dir}/usbdevice_fs.h | egrep -v 'USBDEVFS_\w+32[[:space:]]' | \
-       sed -r "s/$regex/\2 \1/g"       | \
+regex="^#[[:space:]]*define[[:space:]]+USBDEVFS_(\w+)(\(\w+\))?[[:space:]]+_IO[CWR]{0,2}\([[:space:]]*(_IOC_\w+,[[:space:]]*)?'U'[[:space:]]*,[[:space:]]*([[:digit:]]+).*"
+egrep "$regex" ${header_dir}/usbdevice_fs.h | egrep -v 'USBDEVFS_\w+32[[:space:]]' | \
+       sed -r "s/$regex/\4 \1/g"       | \
        sort | xargs printf "\t[%s] = \"%s\",\n"
 printf "};\n\n"
 printf "#if 0\n"
index f80c51d5356555a7789f952a1d99985a9f552ac3..d227d74b28f812040159fa6b99148abf9d821480 100644 (file)
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
-#include "../string2.h"
-#include "../config.h"
-#include "../../perf.h"
+#include "../util/util.h"
+#include "../util/string2.h"
+#include "../util/config.h"
+#include "../perf.h"
 #include "libslang.h"
 #include "ui.h"
 #include "util.h"
@@ -14,7 +15,7 @@
 #include "browser.h"
 #include "helpline.h"
 #include "keysyms.h"
-#include "../color.h"
+#include "../util/color.h"
 #include <linux/ctype.h>
 #include <linux/zalloc.h>
 
index bc134b82829d64a55c61663bbfeadac09e14d6df..5a24dd3ce4db9bd13b5637481574cf0bd9b00f87 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/kernel.h>
-#include "../cache.h"
+#include "../../util/cache.h"
 #include "../progress.h"
 #include "../libslang.h"
 #include "../ui.h"
index ac9ad2330f930d78fe499d38bdc80937d71bdd3c..163536720149baf525f8d1ce1a978868574f281b 100644 (file)
@@ -1122,7 +1122,7 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)
                goto out;
 
        (*rawp)[0] = tmp;
-       *rawp = skip_spaces(*rawp);
+       *rawp = strim(*rawp);
 
        return 0;
 
index 3acfbe34ebafb53ea806a108e825a7c621164a7d..39cce66b4ebcca3aa071ba59ec43b2830ab83d79 100644 (file)
@@ -751,7 +751,10 @@ size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size)
        unsigned char *bitmap;
        int last_cpu = cpu_map__cpu(map, map->nr - 1);
 
-       bitmap = zalloc((last_cpu + 7) / 8);
+       if (buf == NULL)
+               return 0;
+
+       bitmap = zalloc(last_cpu / 8 + 1);
        if (bitmap == NULL) {
                buf[0] = '\0';
                return 0;
index ebb46da4dfe5abc6056f9054db2bbeba63cf1c6a..52459dd5ad0cfc8fbfe7ee7966b09cfb39ec7ced 100644 (file)
@@ -1291,6 +1291,7 @@ static void perf_evsel__free_id(struct perf_evsel *evsel)
        xyarray__delete(evsel->sample_id);
        evsel->sample_id = NULL;
        zfree(&evsel->id);
+       evsel->ids = 0;
 }
 
 static void perf_evsel__free_config_terms(struct perf_evsel *evsel)
@@ -2077,6 +2078,7 @@ void perf_evsel__close(struct perf_evsel *evsel)
 
        perf_evsel__close_fd(evsel);
        perf_evsel__free_fd(evsel);
+       perf_evsel__free_id(evsel);
 }
 
 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
index c24db7f4909c75b7d24e72c25d5885db315b7b71..1903d7ec9797609ee0a56a7f5a0a5505790992b1 100644 (file)
@@ -3559,6 +3559,13 @@ int perf_session__read_header(struct perf_session *session)
                           data->file.path);
        }
 
+       if (f_header.attr_size == 0) {
+               pr_err("ERROR: The %s file's attr size field is 0 which is unexpected.\n"
+                      "Was the 'perf record' command properly terminated?\n",
+                      data->file.path);
+               return -EINVAL;
+       }
+
        nr_attrs = f_header.attrs.size / f_header.attr_size;
        lseek(fd, f_header.attrs.offset, SEEK_SET);
 
@@ -3639,7 +3646,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
        size += sizeof(struct perf_event_header);
        size += ids * sizeof(u64);
 
-       ev = malloc(size);
+       ev = zalloc(size);
 
        if (ev == NULL)
                return -ENOMEM;
@@ -3747,7 +3754,7 @@ int perf_event__process_feature(struct perf_session *session,
                return 0;
 
        ff.buf  = (void *)fe->data;
-       ff.size = event->header.size - sizeof(event->header);
+       ff.size = event->header.size - sizeof(*fe);
        ff.ph = &session->header;
 
        if (feat_ops[feat].process(&ff, NULL))
index cf826eca3aafd7e65379c8caa001bf43e685881b..83b2fbbeeb900e713e733e054392a1eb45efac61 100644 (file)
@@ -1378,6 +1378,7 @@ static int machine__set_modules_path(struct machine *machine)
        return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0);
 }
 int __weak arch__fix_module_text_start(u64 *start __maybe_unused,
+                               u64 *size __maybe_unused,
                                const char *name __maybe_unused)
 {
        return 0;
@@ -1389,7 +1390,7 @@ static int machine__create_module(void *arg, const char *name, u64 start,
        struct machine *machine = arg;
        struct map *map;
 
-       if (arch__fix_module_text_start(&start, name) < 0)
+       if (arch__fix_module_text_start(&start, &size, name) < 0)
                return -1;
 
        map = machine__findnew_module_map(machine, start, name);
index f70ab98a7bde5d3c4422db17ba082d54e7ffb556..7aa38da26427008eb7dc7a46c7ed16c9932c631c 100644 (file)
@@ -222,7 +222,7 @@ struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
 
 struct map *machine__findnew_module_map(struct machine *machine, u64 start,
                                        const char *filename);
-int arch__fix_module_text_start(u64 *start, const char *name);
+int arch__fix_module_text_start(u64 *start, u64 *size, const char *name);
 
 int machine__load_kallsyms(struct machine *machine, const char *filename);
 
index cd1eb73cfe8316c3dd9c7462f787ce1c0f540d7a..8394d48f8b32e4e82c8c3f4f2ffb8aa9039cfeef 100644 (file)
@@ -2230,6 +2230,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
                        field = next;
                }
        }
+       pev->nargs = 0;
        zfree(&pev->args);
 }
 
index d0fd6c614e682c7ce688d48afac6036598a196da..37efa1f43d8bcf52c5e333d51cba04a79e3069b5 100644 (file)
@@ -36,10 +36,16 @@ static int perf_session__process_compressed_event(struct perf_session *session,
        void *src;
        size_t decomp_size, src_size;
        u64 decomp_last_rem = 0;
-       size_t decomp_len = session->header.env.comp_mmap_len;
+       size_t mmap_len, decomp_len = session->header.env.comp_mmap_len;
        struct decomp *decomp, *decomp_last = session->decomp_last;
 
-       decomp = mmap(NULL, sizeof(struct decomp) + decomp_len, PROT_READ|PROT_WRITE,
+       if (decomp_last) {
+               decomp_last_rem = decomp_last->size - decomp_last->head;
+               decomp_len += decomp_last_rem;
+       }
+
+       mmap_len = sizeof(struct decomp) + decomp_len;
+       decomp = mmap(NULL, mmap_len, PROT_READ|PROT_WRITE,
                      MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
        if (decomp == MAP_FAILED) {
                pr_err("Couldn't allocate memory for decompression\n");
@@ -47,10 +53,10 @@ static int perf_session__process_compressed_event(struct perf_session *session,
        }
 
        decomp->file_pos = file_offset;
+       decomp->mmap_len = mmap_len;
        decomp->head = 0;
 
-       if (decomp_last) {
-               decomp_last_rem = decomp_last->size - decomp_last->head;
+       if (decomp_last_rem) {
                memcpy(decomp->data, &(decomp_last->data[decomp_last->head]), decomp_last_rem);
                decomp->size = decomp_last_rem;
        }
@@ -61,7 +67,7 @@ static int perf_session__process_compressed_event(struct perf_session *session,
        decomp_size = zstd_decompress_stream(&(session->zstd_data), src, src_size,
                                &(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem);
        if (!decomp_size) {
-               munmap(decomp, sizeof(struct decomp) + decomp_len);
+               munmap(decomp, mmap_len);
                pr_err("Couldn't decompress data\n");
                return -1;
        }
@@ -255,15 +261,15 @@ static void perf_session__delete_threads(struct perf_session *session)
 static void perf_session__release_decomp_events(struct perf_session *session)
 {
        struct decomp *next, *decomp;
-       size_t decomp_len;
+       size_t mmap_len;
        next = session->decomp;
-       decomp_len = session->header.env.comp_mmap_len;
        do {
                decomp = next;
                if (decomp == NULL)
                        break;
                next = decomp->next;
-               munmap(decomp, decomp_len + sizeof(struct decomp));
+               mmap_len = decomp->mmap_len;
+               munmap(decomp, mmap_len);
        } while (1);
 }
 
index dd8920b745bce0d1625cc35d1f5f031b788145ac..863dbad878496413f8e2a9fbd0d515c9b9076bae 100644 (file)
@@ -46,6 +46,7 @@ struct perf_session {
 struct decomp {
        struct decomp *next;
        u64 file_pos;
+       size_t mmap_len;
        u64 head;
        size_t size;
        char data[];
index 656065af497129509e0b8f980ac2e0fac6a050bb..accb1bf1cfd84408aa94c763244a8e60d4addcda 100644 (file)
@@ -819,7 +819,8 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                        "stalled cycles per insn",
                                        ratio);
                } else if (have_frontend_stalled) {
-                       print_metric(config, ctxp, NULL, NULL,
+                       out->new_line(config, ctxp);
+                       print_metric(config, ctxp, NULL, "%7.2f ",
                                     "stalled cycles per insn", 0);
                }
        } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
index 173f3378aaa0696a8497881a0b6b98928c1f10a2..4efde7879474cc63e32c4cbbd180495f7da72b5b 100644 (file)
@@ -92,6 +92,11 @@ static int prefix_underscores_count(const char *str)
        return tail - str;
 }
 
+void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+{
+       p->end = c->start;
+}
+
 const char * __weak arch__normalize_symbol_name(const char *name)
 {
        return name;
@@ -218,7 +223,7 @@ void symbols__fixup_end(struct rb_root_cached *symbols)
                curr = rb_entry(nd, struct symbol, rb_node);
 
                if (prev->end == prev->start && prev->end != curr->start)
-                       prev->end = curr->start;
+                       arch__symbols__fixup_end(prev, curr);
        }
 
        /* Last entry */
index 12755b42ea93c86f6069ccfc93df581803d6ac60..183f630cb5f1b47b1fc7aaaf105814d6df0cb01c 100644 (file)
@@ -288,6 +288,7 @@ const char *arch__normalize_symbol_name(const char *name);
 #define SYMBOL_A 0
 #define SYMBOL_B 1
 
+void arch__symbols__fixup_end(struct symbol *p, struct symbol *c);
 int arch__compare_symbol_names(const char *namea, const char *nameb);
 int arch__compare_symbol_names_n(const char *namea, const char *nameb,
                                 unsigned int n);
index 873ab505ca8071fdf38e2eb8b091e19553f165fc..590793cc51424c163b99e5e35f58b2609f206d70 100644 (file)
@@ -214,14 +214,24 @@ struct comm *thread__comm(const struct thread *thread)
 
 struct comm *thread__exec_comm(const struct thread *thread)
 {
-       struct comm *comm, *last = NULL;
+       struct comm *comm, *last = NULL, *second_last = NULL;
 
        list_for_each_entry(comm, &thread->comm_list, list) {
                if (comm->exec)
                        return comm;
+               second_last = last;
                last = comm;
        }
 
+       /*
+        * 'last' with no start time might be the parent's comm of a synthesized
+        * thread (created by processing a synthesized fork event). For a main
+        * thread, that is very probably wrong. Prefer a later comm to avoid
+        * that case.
+        */
+       if (second_last && !last->start && thread->pid_ == thread->tid)
+               return second_last;
+
        return last;
 }
 
index 23bdb9884576087c5879e4af13f68d8cb83ab9bc..d2202392ffdbb328b9d08c4995c96faaa1a082fa 100644 (file)
@@ -99,8 +99,8 @@ size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size
        while (input.pos < input.size) {
                ret = ZSTD_decompressStream(data->dstream, &output, &input);
                if (ZSTD_isError(ret)) {
-                       pr_err("failed to decompress (B): %ld -> %ld : %s\n",
-                              src_size, output.size, ZSTD_getErrorName(ret));
+                       pr_err("failed to decompress (B): %ld -> %ld, dst_size %ld : %s\n",
+                              src_size, output.size, dst_size, ZSTD_getErrorName(ret));
                        break;
                }
                output.dst  = dst + output.pos;
index 045f5f7d68ab5d9836a3abe5170ab14ad172b379..13f1e8b9ac525ddf44793541551acde4f8432e1c 100644 (file)
@@ -9,9 +9,10 @@ ifeq ("$(origin O)", "command line")
 endif
 
 turbostat : turbostat.c
-override CFLAGS +=     -Wall -I../../../include
+override CFLAGS +=     -O2 -Wall -I../../../include
 override CFLAGS +=     -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
 override CFLAGS +=     -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"'
+override CFLAGS +=     -D_FORTIFY_SOURCE=2
 
 %: %.c
        @mkdir -p $(BUILD_OUTPUT)
index 75fc4fb9901cd20ec71c61537441565c08d6b1c3..b2a86438f074ac25ec14f7cb57ff3d4f45f416aa 100644 (file)
@@ -39,7 +39,6 @@ FILE *outf;
 int *fd_percpu;
 struct timeval interval_tv = {5, 0};
 struct timespec interval_ts = {5, 0};
-struct timespec one_msec = {0, 1000000};
 unsigned int num_iterations;
 unsigned int debug;
 unsigned int quiet;
@@ -60,6 +59,7 @@ unsigned int do_irtl_hsw;
 unsigned int units = 1000000;  /* MHz etc */
 unsigned int genuine_intel;
 unsigned int authentic_amd;
+unsigned int hygon_genuine;
 unsigned int max_level, max_extended_level;
 unsigned int has_invariant_tsc;
 unsigned int do_nhm_platform_info;
@@ -100,6 +100,7 @@ unsigned int has_hwp_epp;           /* IA32_HWP_REQUEST[bits 31:24] */
 unsigned int has_hwp_pkg;              /* IA32_HWP_REQUEST_PKG */
 unsigned int has_misc_feature_control;
 unsigned int first_counter_read = 1;
+int ignore_stdin;
 
 #define RAPL_PKG               (1 << 0)
                                        /* 0x610 MSR_PKG_POWER_LIMIT */
@@ -166,6 +167,7 @@ size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
 struct thread_data {
        struct timeval tv_begin;
        struct timeval tv_end;
+       struct timeval tv_delta;
        unsigned long long tsc;
        unsigned long long aperf;
        unsigned long long mperf;
@@ -506,6 +508,7 @@ unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAU
 unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
 
 #define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
+#define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME)
 #define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
 #define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
 #define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
@@ -849,7 +852,6 @@ int dump_counters(struct thread_data *t, struct core_data *c,
                outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
                outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
                outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
-               outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
                outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);
                outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);
                outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg);
@@ -911,7 +913,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
        if (DO_BIC(BIC_TOD))
                outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);
 
-       interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
+       interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec/1000000.0;
 
        tsc = t->tsc * tsc_tweak;
 
@@ -1287,6 +1289,14 @@ delta_core(struct core_data *new, struct core_data *old)
        }
 }
 
+int soft_c1_residency_display(int bic)
+{
+       if (!DO_BIC(BIC_CPU_c1) || use_c1_residency_msr)
+               return 0;
+
+       return DO_BIC_READ(bic);
+}
+
 /*
  * old = new - old
  */
@@ -1309,6 +1319,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
         * over-write old w/ new so we can print end of interval values
         */
 
+       timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);
        old->tv_begin = new->tv_begin;
        old->tv_end = new->tv_end;
 
@@ -1322,7 +1333,8 @@ delta_thread(struct thread_data *new, struct thread_data *old,
 
        old->c1 = new->c1 - old->c1;
 
-       if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) {
+       if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
+           soft_c1_residency_display(BIC_Avg_MHz)) {
                if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
                        old->aperf = new->aperf - old->aperf;
                        old->mperf = new->mperf - old->mperf;
@@ -1404,6 +1416,8 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
        t->tv_begin.tv_usec = 0;
        t->tv_end.tv_sec = 0;
        t->tv_end.tv_usec = 0;
+       t->tv_delta.tv_sec = 0;
+       t->tv_delta.tv_usec = 0;
 
        t->tsc = 0;
        t->aperf = 0;
@@ -1573,6 +1587,9 @@ void compute_average(struct thread_data *t, struct core_data *c,
 
        for_all_cpus(sum_counters, t, c, p);
 
+       /* Use the global time delta for the average. */
+       average.threads.tv_delta = tv_delta;
+
        average.threads.tsc /= topo.num_cpus;
        average.threads.aperf /= topo.num_cpus;
        average.threads.mperf /= topo.num_cpus;
@@ -1714,7 +1731,7 @@ void get_apic_id(struct thread_data *t)
        if (!DO_BIC(BIC_X2APIC))
                return;
 
-       if (authentic_amd) {
+       if (authentic_amd || hygon_genuine) {
                unsigned int topology_extensions;
 
                if (max_extended_level < 0x8000001e)
@@ -1762,19 +1779,20 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
        struct msr_counter *mp;
        int i;
 
-       gettimeofday(&t->tv_begin, (struct timezone *)NULL);
-
        if (cpu_migrate(cpu)) {
                fprintf(outf, "Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
+       gettimeofday(&t->tv_begin, (struct timezone *)NULL);
+
        if (first_counter_read)
                get_apic_id(t);
 retry:
        t->tsc = rdtsc();       /* we are running on local CPU of interest */
 
-       if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz)) {
+       if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
+           soft_c1_residency_display(BIC_Avg_MHz)) {
                unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
 
                /*
@@ -1851,20 +1869,20 @@ retry:
        if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
                goto done;
 
-       if (DO_BIC(BIC_CPU_c3)) {
+       if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) {
                if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
                        return -6;
        }
 
-       if (DO_BIC(BIC_CPU_c6) && !do_knl_cstates) {
+       if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) {
                if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
                        return -7;
-       } else if (do_knl_cstates) {
+       } else if (do_knl_cstates || soft_c1_residency_display(BIC_CPU_c6)) {
                if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6))
                        return -7;
        }
 
-       if (DO_BIC(BIC_CPU_c7))
+       if (DO_BIC(BIC_CPU_c7) || soft_c1_residency_display(BIC_CPU_c7))
                if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
                        return -8;
 
@@ -2912,6 +2930,7 @@ int snapshot_cpu_lpi_us(void)
        if (retval != 1) {
                fprintf(stderr, "Disabling Low Power Idle CPU output\n");
                BIC_NOT_PRESENT(BIC_CPU_LPI);
+               fclose(fp);
                return -1;
        }
 
@@ -2938,6 +2957,7 @@ int snapshot_sys_lpi_us(void)
        if (retval != 1) {
                fprintf(stderr, "Disabling Low Power Idle System output\n");
                BIC_NOT_PRESENT(BIC_SYS_LPI);
+               fclose(fp);
                return -1;
        }
        fclose(fp);
@@ -2985,8 +3005,6 @@ static void signal_handler (int signal)
                        fprintf(stderr, "SIGUSR1\n");
                break;
        }
-       /* make sure this manually-invoked interval is at least 1ms long */
-       nanosleep(&one_msec, NULL);
 }
 
 void setup_signal_handler(void)
@@ -3005,29 +3023,38 @@ void setup_signal_handler(void)
 
 void do_sleep(void)
 {
-       struct timeval select_timeout;
+       struct timeval tout;
+       struct timespec rest;
        fd_set readfds;
        int retval;
 
        FD_ZERO(&readfds);
        FD_SET(0, &readfds);
 
-       if (!isatty(fileno(stdin))) {
+       if (ignore_stdin) {
                nanosleep(&interval_ts, NULL);
                return;
        }
 
-       select_timeout = interval_tv;
-       retval = select(1, &readfds, NULL, NULL, &select_timeout);
+       tout = interval_tv;
+       retval = select(1, &readfds, NULL, NULL, &tout);
 
        if (retval == 1) {
                switch (getc(stdin)) {
                case 'q':
                        exit_requested = 1;
                        break;
+               case EOF:
+                       /*
+                        * 'stdin' is a pipe closed on the other end. There
+                        * won't be any further input.
+                        */
+                       ignore_stdin = 1;
+                       /* Sleep the rest of the time */
+                       rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000);
+                       rest.tv_nsec = (tout.tv_usec % 1000000) * 1000;
+                       nanosleep(&rest, NULL);
                }
-               /* make sure this manually-invoked interval is at least 1ms long */
-               nanosleep(&one_msec, NULL);
        }
 }
 
@@ -3209,6 +3236,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
                break;
        case INTEL_FAM6_HASWELL_CORE:   /* HSW */
        case INTEL_FAM6_HASWELL_X:      /* HSX */
+       case INTEL_FAM6_HASWELL_ULT:    /* HSW */
        case INTEL_FAM6_HASWELL_GT3E:   /* HSW */
        case INTEL_FAM6_BROADWELL_CORE: /* BDW */
        case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
@@ -3405,6 +3433,7 @@ int has_config_tdp(unsigned int family, unsigned int model)
        case INTEL_FAM6_IVYBRIDGE:      /* IVB */
        case INTEL_FAM6_HASWELL_CORE:   /* HSW */
        case INTEL_FAM6_HASWELL_X:      /* HSX */
+       case INTEL_FAM6_HASWELL_ULT:    /* HSW */
        case INTEL_FAM6_HASWELL_GT3E:   /* HSW */
        case INTEL_FAM6_BROADWELL_CORE: /* BDW */
        case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
@@ -3803,6 +3832,7 @@ double get_tdp_amd(unsigned int family)
 {
        switch (family) {
        case 0x17:
+       case 0x18:
        default:
                /* This is the max stock TDP of HEDT/Server Fam17h chips */
                return 250.0;
@@ -3841,6 +3871,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
        case INTEL_FAM6_SANDYBRIDGE:
        case INTEL_FAM6_IVYBRIDGE:
        case INTEL_FAM6_HASWELL_CORE:   /* HSW */
+       case INTEL_FAM6_HASWELL_ULT:    /* HSW */
        case INTEL_FAM6_HASWELL_GT3E:   /* HSW */
        case INTEL_FAM6_BROADWELL_CORE: /* BDW */
        case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
@@ -3982,6 +4013,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model)
 
        switch (family) {
        case 0x17: /* Zen, Zen+ */
+       case 0x18: /* Hygon Dhyana */
                do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
                if (rapl_joules) {
                        BIC_PRESENT(BIC_Pkg_J);
@@ -4002,7 +4034,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model)
        rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f));
        rapl_power_units = ldexp(1.0, -(msr & 0xf));
 
-       tdp = get_tdp_amd(model);
+       tdp = get_tdp_amd(family);
 
        rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
        if (!quiet)
@@ -4018,7 +4050,7 @@ void rapl_probe(unsigned int family, unsigned int model)
 {
        if (genuine_intel)
                rapl_probe_intel(family, model);
-       if (authentic_amd)
+       if (authentic_amd || hygon_genuine)
                rapl_probe_amd(family, model);
 }
 
@@ -4032,6 +4064,7 @@ void perf_limit_reasons_probe(unsigned int family, unsigned int model)
 
        switch (model) {
        case INTEL_FAM6_HASWELL_CORE:   /* HSW */
+       case INTEL_FAM6_HASWELL_ULT:    /* HSW */
        case INTEL_FAM6_HASWELL_GT3E:   /* HSW */
                do_gfx_perf_limit_reasons = 1;
        case INTEL_FAM6_HASWELL_X:      /* HSX */
@@ -4251,6 +4284,7 @@ int has_snb_msrs(unsigned int family, unsigned int model)
        case INTEL_FAM6_IVYBRIDGE_X:    /* IVB Xeon */
        case INTEL_FAM6_HASWELL_CORE:   /* HSW */
        case INTEL_FAM6_HASWELL_X:      /* HSW */
+       case INTEL_FAM6_HASWELL_ULT:    /* HSW */
        case INTEL_FAM6_HASWELL_GT3E:   /* HSW */
        case INTEL_FAM6_BROADWELL_CORE: /* BDW */
        case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
@@ -4267,7 +4301,7 @@ int has_snb_msrs(unsigned int family, unsigned int model)
 }
 
 /*
- * HSW adds support for additional MSRs:
+ * HSW ULT added support for C8/C9/C10 MSRs:
  *
  * MSR_PKG_C8_RESIDENCY                0x00000630
  * MSR_PKG_C9_RESIDENCY                0x00000631
@@ -4278,13 +4312,13 @@ int has_snb_msrs(unsigned int family, unsigned int model)
  * MSR_PKGC10_IRTL             0x00000635
  *
  */
-int has_hsw_msrs(unsigned int family, unsigned int model)
+int has_c8910_msrs(unsigned int family, unsigned int model)
 {
        if (!genuine_intel)
                return 0;
 
        switch (model) {
-       case INTEL_FAM6_HASWELL_CORE:
+       case INTEL_FAM6_HASWELL_ULT:    /* HSW */
        case INTEL_FAM6_BROADWELL_CORE: /* BDW */
        case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
        case INTEL_FAM6_CANNONLAKE_MOBILE:      /* CNL */
@@ -4568,9 +4602,6 @@ unsigned int intel_model_duplicates(unsigned int model)
        case INTEL_FAM6_XEON_PHI_KNM:
                return INTEL_FAM6_XEON_PHI_KNL;
 
-       case INTEL_FAM6_HASWELL_ULT:
-               return INTEL_FAM6_HASWELL_CORE;
-
        case INTEL_FAM6_BROADWELL_X:
        case INTEL_FAM6_BROADWELL_XEON_D:       /* BDX-DE */
                return INTEL_FAM6_BROADWELL_X;
@@ -4582,7 +4613,11 @@ unsigned int intel_model_duplicates(unsigned int model)
                return INTEL_FAM6_SKYLAKE_MOBILE;
 
        case INTEL_FAM6_ICELAKE_MOBILE:
+       case INTEL_FAM6_ICELAKE_NNPI:
                return INTEL_FAM6_CANNONLAKE_MOBILE;
+
+       case INTEL_FAM6_ATOM_TREMONT_X:
+               return INTEL_FAM6_ATOM_GOLDMONT_X;
        }
        return model;
 }
@@ -4600,6 +4635,8 @@ void process_cpuid()
                genuine_intel = 1;
        else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
                authentic_amd = 1;
+       else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e)
+               hygon_genuine = 1;
 
        if (!quiet)
                fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
@@ -4820,12 +4857,12 @@ void process_cpuid()
                BIC_NOT_PRESENT(BIC_CPU_c7);
                BIC_NOT_PRESENT(BIC_Pkgpc7);
        }
-       if (has_hsw_msrs(family, model)) {
+       if (has_c8910_msrs(family, model)) {
                BIC_PRESENT(BIC_Pkgpc8);
                BIC_PRESENT(BIC_Pkgpc9);
                BIC_PRESENT(BIC_Pkgpc10);
        }
-       do_irtl_hsw = has_hsw_msrs(family, model);
+       do_irtl_hsw = has_c8910_msrs(family, model);
        if (has_skl_msrs(family, model)) {
                BIC_PRESENT(BIC_Totl_c0);
                BIC_PRESENT(BIC_Any_c0);
@@ -5123,7 +5160,7 @@ int initialize_counters(int cpu_id)
 
 void allocate_output_buffer()
 {
-       output_buffer = calloc(1, (1 + topo.num_cpus) * 1024);
+       output_buffer = calloc(1, (1 + topo.num_cpus) * 2048);
        outp = output_buffer;
        if (outp == NULL)
                err(-1, "calloc output buffer");
@@ -5269,7 +5306,7 @@ int get_and_dump_counters(void)
 }
 
 void print_version() {
-       fprintf(outf, "turbostat version 19.03.20"
+       fprintf(outf, "turbostat version 19.08.31"
                " - Len Brown <lenb@kernel.org>\n");
 }
 
index 1fdeef864e7c1b43a97ad5b3d8a47523f98a5027..666b325a62a2299aba039fcbdd3ffae6ba26dbfc 100644 (file)
@@ -9,8 +9,9 @@ ifeq ("$(origin O)", "command line")
 endif
 
 x86_energy_perf_policy : x86_energy_perf_policy.c
-override CFLAGS +=     -Wall -I../../../include
+override CFLAGS +=     -O2 -Wall -I../../../include
 override CFLAGS +=     -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
+override CFLAGS +=     -D_FORTIFY_SOURCE=2
 
 %: %.c
        @mkdir -p $(BUILD_OUTPUT)
index 17db1c3af4d0bb3901482bbfed9e2cff8bc8cb6f..78c6361898b189a57414d3e10f05de23e1da6f81 100644 (file)
@@ -40,7 +40,7 @@ in the same processor package.
 Hardware P-States (HWP) are effectively an expansion of hardware
 P-state control from the opportunistic turbo-mode P-state range
 to include the entire range of available P-states.
-On Broadwell Xeon, the initial HWP implementation, EBP influenced HWP.
+On Broadwell Xeon, the initial HWP implementation, EPB influenced HWP.
 That influence was removed in subsequent generations,
 where it was moved to the
 Energy_Performance_Preference (EPP) field in
index 34a796b303fe2bfecd731d5b1f513e257637e663..3fe1eed900d414169fb99d00787e1be710c7270b 100644 (file)
@@ -545,7 +545,7 @@ void cmdline(int argc, char **argv)
 
        progname = argv[0];
 
-       while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw",
+       while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw:",
                                long_options, &option_index)) != -1) {
                switch (opt) {
                case 'a':
@@ -1259,6 +1259,15 @@ void probe_dev_msr(void)
                if (system("/sbin/modprobe msr > /dev/null 2>&1"))
                        err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
 }
+
+static void get_cpuid_or_exit(unsigned int leaf,
+                            unsigned int *eax, unsigned int *ebx,
+                            unsigned int *ecx, unsigned int *edx)
+{
+       if (!__get_cpuid(leaf, eax, ebx, ecx, edx))
+               errx(1, "Processor not supported\n");
+}
+
 /*
  * early_cpuid()
  * initialize turbo_is_enabled, has_hwp, has_epb
@@ -1266,15 +1275,10 @@ void probe_dev_msr(void)
  */
 void early_cpuid(void)
 {
-       unsigned int eax, ebx, ecx, edx, max_level;
+       unsigned int eax, ebx, ecx, edx;
        unsigned int fms, family, model;
 
-       __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
-
-       if (max_level < 6)
-               errx(1, "Processor not supported\n");
-
-       __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+       get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
        family = (fms >> 8) & 0xf;
        model = (fms >> 4) & 0xf;
        if (family == 6 || family == 0xf)
@@ -1288,7 +1292,7 @@ void early_cpuid(void)
                bdx_highest_ratio = msr & 0xFF;
        }
 
-       __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+       get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
        turbo_is_enabled = (eax >> 1) & 1;
        has_hwp = (eax >> 7) & 1;
        has_epb = (ecx >> 3) & 1;
@@ -1306,7 +1310,7 @@ void parse_cpuid(void)
 
        eax = ebx = ecx = edx = 0;
 
-       __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
+       get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx);
 
        if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
                genuine_intel = 1;
@@ -1315,7 +1319,7 @@ void parse_cpuid(void)
                fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
                        (char *)&ebx, (char *)&edx, (char *)&ecx);
 
-       __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+       get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
        family = (fms >> 8) & 0xf;
        model = (fms >> 4) & 0xf;
        stepping = fms & 0xf;
@@ -1340,7 +1344,7 @@ void parse_cpuid(void)
                errx(1, "CPUID: no MSR");
 
 
-       __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+       get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
        /* turbo_is_enabled already set */
        /* has_hwp already set */
        has_hwp_notify = eax & (1 << 8);
index 495066bafbe3130364c76e9f73cee0dbfaa1db0f..ded7a950dc4042899b3a61bab51652048dc1fd05 100644 (file)
@@ -32,7 +32,6 @@ EXTRA_WARNINGS += -Wno-system-headers
 EXTRA_WARNINGS += -Wold-style-definition
 EXTRA_WARNINGS += -Wpacked
 EXTRA_WARNINGS += -Wredundant-decls
-EXTRA_WARNINGS += -Wshadow
 EXTRA_WARNINGS += -Wstrict-prototypes
 EXTRA_WARNINGS += -Wswitch-default
 EXTRA_WARNINGS += -Wswitch-enum
@@ -69,8 +68,16 @@ endif
 # will do for now and keep the above -Wstrict-aliasing=3 in place
 # in newer systems.
 # Needed for the __raw_cmpxchg in tools/arch/x86/include/asm/cmpxchg.h
+#
+# See https://lkml.org/lkml/2006/11/28/253 and https://gcc.gnu.org/gcc-4.8/changes.html,
+# that takes into account Linus's comments (search for Wshadow) for the reasoning about
+# -Wshadow not being interesting before gcc 4.8.
+
 ifneq ($(filter 3.%,$(MAKE_VERSION)),)  # make-3
 EXTRA_WARNINGS += -fno-strict-aliasing
+EXTRA_WARNINGS += -Wno-shadow
+else
+EXTRA_WARNINGS += -Wshadow
 endif
 
 ifneq ($(findstring $(MAKEFLAGS), w),w)
index 72525426654bf00e5d31f9ae27f5ca5c41c495c9..6fd864935319599bce65fe1770299e9b7eb74c4f 100755 (executable)
@@ -663,7 +663,7 @@ while ($#ARGV >= 0) {
     }
 
     else {
-       die "Unknow option $opt\n";
+       die "Unknown option $opt\n";
     }
 }
 
@@ -732,7 +732,7 @@ if ($start) {
        }
     }
     run_command "cp $good_start $good" or die "failed to copy to $good\n";
-    run_command "cp $bad_start $bad" or die "faield to copy to $bad\n";
+    run_command "cp $bad_start $bad" or die "failed to copy to $bad\n";
 } else {
     if ( ! -f $good ) {
        die "Can not find file $good\n";
index 11c9c62c33620790f6ff72cba3369721f13fdc4e..96752ebd938fa7b941d167009c8d92d48f769df1 100644 (file)
@@ -34,6 +34,9 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test
 BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c)))
 TEST_GEN_FILES = $(BPF_OBJ_FILES)
 
+BTF_C_FILES = $(wildcard progs/btf_dump_test_case_*.c)
+TEST_FILES = $(BTF_C_FILES)
+
 # Also test sub-register code-gen if LLVM has eBPF v3 processor support which
 # contains both ALU32 and JMP32 instructions.
 SUBREG_CODEGEN := $(shell echo "int cal(int a) { return a > 0; }" | \
@@ -57,7 +60,8 @@ TEST_PROGS := test_kmod.sh \
        test_lirc_mode2.sh \
        test_skb_cgroup_id.sh \
        test_flow_dissector.sh \
-       test_xdp_vlan.sh \
+       test_xdp_vlan_mode_generic.sh \
+       test_xdp_vlan_mode_native.sh \
        test_lwt_ip_encap.sh \
        test_tcp_check_syncookie.sh \
        test_tc_tunnel.sh \
@@ -67,7 +71,8 @@ TEST_PROGS := test_kmod.sh \
 TEST_PROGS_EXTENDED := with_addr.sh \
        with_tunnels.sh \
        tcp_client.py \
-       tcp_server.py
+       tcp_server.py \
+       test_xdp_vlan.sh
 
 # Compile but not part of 'make run_tests'
 TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user \
index f7a0744db31e1bb3211e0b17ca73b7e57941e5b7..5dc109f4c0970fb492b955ec3a1edebbcc6d0932 100644 (file)
@@ -34,3 +34,4 @@ CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
 CONFIG_MPLS_IPTUNNEL=m
 CONFIG_IPV6_SIT=m
+CONFIG_BPF_JIT=y
index 5aeaa284fc47493decf0fc55b31de7c8a734ac6d..a680628204108b41d0c046a5371cec9f2cfedc0b 100644 (file)
@@ -41,8 +41,7 @@ int sendmsg_v6_prog(struct bpf_sock_addr *ctx)
        }
 
        /* Rewrite destination. */
-       if ((ctx->user_ip6[0] & 0xFFFF) == bpf_htons(0xFACE) &&
-            ctx->user_ip6[0] >> 16 == bpf_htons(0xB00C)) {
+       if (ctx->user_ip6[0] == bpf_htonl(0xFACEB00C)) {
                ctx->user_ip6[0] = bpf_htonl(DST_REWRITE_IP6_0);
                ctx->user_ip6[1] = bpf_htonl(DST_REWRITE_IP6_1);
                ctx->user_ip6[2] = bpf_htonl(DST_REWRITE_IP6_2);
index 8f850823d35f8362d0c6245724e059517618d2a5..6e75dd3cb14f97f033ff253e9a5f41af5f2c6d1c 100644 (file)
@@ -97,6 +97,13 @@ int test_btf_dump_case(int n, struct btf_dump_test_case *test_case)
        }
 
        snprintf(test_file, sizeof(test_file), "progs/%s.c", test_case->name);
+       if (access(test_file, R_OK) == -1)
+               /*
+                * When the test is run with O=, kselftest copies TEST_FILES
+                * without preserving the directory structure.
+                */
+               snprintf(test_file, sizeof(test_file), "%s.c",
+                       test_case->name);
        /*
         * Diff test output and expected test output, contained between
         * START-EXPECTED-OUTPUT and END-EXPECTED-OUTPUT lines in test case.
index 2fc4625c1a1502b5926614874253fd86715242c7..65572900439118dc17522ae971f5daf91a84db6b 100644 (file)
@@ -20,9 +20,9 @@ int main(int argc, char **argv)
                BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */
                BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
                             BPF_FUNC_get_local_storage),
-               BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0),
+               BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0),
                BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 0x1),
-               BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_3, 0),
+               BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0),
 
                BPF_LD_MAP_FD(BPF_REG_1, 0), /* map fd */
                BPF_MOV64_IMM(BPF_REG_2, 0), /* flags, not used */
@@ -30,7 +30,7 @@ int main(int argc, char **argv)
                             BPF_FUNC_get_local_storage),
                BPF_MOV64_IMM(BPF_REG_1, 1),
                BPF_STX_XADD(BPF_DW, BPF_REG_0, BPF_REG_1, 0),
-               BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
+               BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
                BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0x1),
                BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
                BPF_EXIT_INSN(),
index fb679ac3d4b07a4a68822369f9476ab0d06f7fd2..0e6652733462377cfe7bdc0fa57b5548c39f2e0f 100644 (file)
@@ -13,6 +13,7 @@
 #include <bpf/bpf.h>
 
 #include "cgroup_helpers.h"
+#include "bpf_endian.h"
 #include "bpf_rlimit.h"
 #include "bpf_util.h"
 
@@ -232,7 +233,8 @@ static struct sock_test tests[] = {
                        /* if (ip == expected && port == expected) */
                        BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
                                    offsetof(struct bpf_sock, src_ip6[3])),
-                       BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x01000000, 4),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_7,
+                                   __bpf_constant_ntohl(0x00000001), 4),
                        BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
                                    offsetof(struct bpf_sock, src_port)),
                        BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x2001, 2),
@@ -261,7 +263,8 @@ static struct sock_test tests[] = {
                        /* if (ip == expected && port == expected) */
                        BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
                                    offsetof(struct bpf_sock, src_ip4)),
-                       BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x0100007F, 4),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_7,
+                                   __bpf_constant_ntohl(0x7F000001), 4),
                        BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
                                    offsetof(struct bpf_sock, src_port)),
                        BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0x1002, 2),
index 51a3a31d1aac47b0e95e27b9ce3cc28d29b94d09..bb8b0da91686f0e14105b7c22bb40a7e762f937f 100755 (executable)
@@ -1,6 +1,14 @@
 #!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Author: Jesper Dangaard Brouer <hawk@kernel.org>
 
-TESTNAME=xdp_vlan
+# Allow wrapper scripts to name test
+if [ -z "$TESTNAME" ]; then
+    TESTNAME=xdp_vlan
+fi
+
+# Default XDP mode
+XDP_MODE=xdpgeneric
 
 usage() {
   echo "Testing XDP + TC eBPF VLAN manipulations: $TESTNAME"
@@ -9,9 +17,23 @@ usage() {
   echo "  -v | --verbose : Verbose"
   echo "  --flush        : Flush before starting (e.g. after --interactive)"
   echo "  --interactive  : Keep netns setup running after test-run"
+  echo "  --mode=XXX     : Choose XDP mode (xdp | xdpgeneric | xdpdrv)"
   echo ""
 }
 
+valid_xdp_mode()
+{
+       local mode=$1
+
+       case "$mode" in
+               xdpgeneric | xdpdrv | xdp)
+                       return 0
+                       ;;
+               *)
+                       return 1
+       esac
+}
+
 cleanup()
 {
        local status=$?
@@ -37,7 +59,7 @@ cleanup()
 
 # Using external program "getopt" to get --long-options
 OPTIONS=$(getopt -o hvfi: \
-    --long verbose,flush,help,interactive,debug -- "$@")
+    --long verbose,flush,help,interactive,debug,mode: -- "$@")
 if (( $? != 0 )); then
     usage
     echo "selftests: $TESTNAME [FAILED] Error calling getopt, unknown option?"
@@ -60,6 +82,11 @@ while true; do
                cleanup
                shift
                ;;
+           --mode )
+               shift
+               XDP_MODE=$1
+               shift
+               ;;
            -- )
                shift
                break
@@ -81,8 +108,14 @@ if [ "$EUID" -ne 0 ]; then
        exit 1
 fi
 
-ip link set dev lo xdp off 2>/dev/null > /dev/null
-if [ $? -ne 0 ];then
+valid_xdp_mode $XDP_MODE
+if [ $? -ne 0 ]; then
+       echo "selftests: $TESTNAME [FAILED] unknown XDP mode ($XDP_MODE)"
+       exit 1
+fi
+
+ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null
+if [ $? -ne 0 ]; then
        echo "selftests: $TESTNAME [SKIP] need ip xdp support"
        exit 0
 fi
@@ -155,7 +188,7 @@ ip netns exec ns2 ip link set lo up
 # At this point, the hosts cannot reach each-other,
 # because ns2 are using VLAN tags on the packets.
 
-ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Okay ping fails"'
+ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Success: First ping must fail"'
 
 
 # Now we can use the test_xdp_vlan.c program to pop/push these VLAN tags
@@ -166,7 +199,7 @@ export FILE=test_xdp_vlan.o
 
 # First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change"
 export XDP_PROG=xdp_vlan_change
-ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
 
 # In ns1: egress use TC to add back VLAN tag 4011
 #  (del cmd)
@@ -177,8 +210,8 @@ ip netns exec ns1 tc filter add dev $DEVNS1 egress \
   prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push
 
 # Now the namespaces can reach each-other, test with ping:
-ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
-ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
+ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1
+ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2
 
 # Second test: Replace xdp prog, that fully remove vlan header
 #
@@ -187,9 +220,9 @@ ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
 # ETH_P_8021Q indication, and this cause overwriting of our changes.
 #
 export XDP_PROG=xdp_vlan_remove_outer2
-ip netns exec ns1 ip link set $DEVNS1 xdp off
-ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE off
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
 
 # Now the namespaces should still be able reach each-other, test with ping:
-ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
-ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
+ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1
+ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh b/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh
new file mode 100755 (executable)
index 0000000..c515326
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Exit on failure
+set -e
+
+# Wrapper script to test generic-XDP
+export TESTNAME=xdp_vlan_mode_generic
+./test_xdp_vlan.sh --mode=xdpgeneric
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh b/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh
new file mode 100755 (executable)
index 0000000..5cf7ce1
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Exit on failure
+set -e
+
+# Wrapper script to test native-XDP
+export TESTNAME=xdp_vlan_mode_native
+./test_xdp_vlan.sh --mode=xdpdrv
index b0fda2877119c4af08277bd0f329f238c193313c..d438193804b212ffa80c94be47e8c1aca392181e 100644 (file)
        .result = ACCEPT,
        .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
 },
+{
+       "read gso_segs from CGROUP_SKB",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
+                   offsetof(struct __sk_buff, gso_segs)),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+},
 {
        "write gso_segs from CGROUP_SKB",
        .insns = {
index 5e980a5ab69deb857291889abb616d92507c852c..1fc4e61e9f9f0ba84b5d3329d1168446162d3cf1 100644 (file)
        .errstr = "loop detected",
        .prog_type = BPF_PROG_TYPE_TRACEPOINT,
 },
+{
+       "not-taken loop with back jump to 1st insn",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 123),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 4, -2),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .retval = 123,
+},
+{
+       "taken loop with back jump to 1st insn",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_1, 10),
+       BPF_MOV64_IMM(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, -3),
+       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .retval = 55,
+},
index 4c223266299aa7c90c1288bcbed7fd891f802f3d..bdb69599c4bdc2526943cf9a690e1ef0697872dd 100644 (file)
@@ -191,8 +191,7 @@ int cg_find_unified_root(char *root, size_t len)
                strtok(NULL, delim);
                strtok(NULL, delim);
 
-               if (strcmp(fs, "cgroup") == 0 &&
-                   strcmp(type, "cgroup2") == 0) {
+               if (strcmp(type, "cgroup2") == 0) {
                        strncpy(root, mount, len);
                        return 0;
                }
index 8219a30853d283fa65baa1be4f16036d7cf542a8..0fc1b6d4b0f9c4db9084158fd22b755e7b53482f 100644 (file)
@@ -447,6 +447,59 @@ cleanup:
        return ret;
 }
 
+/*
+ * The test creates a cgroups and freezes it. Then it creates a child cgroup
+ * and populates it with a task. After that it checks that the child cgroup
+ * is frozen and the parent cgroup remains frozen too.
+ */
+static int test_cgfreezer_mkdir(const char *root)
+{
+       int ret = KSFT_FAIL;
+       char *parent, *child = NULL;
+       int pid;
+
+       parent = cg_name(root, "cg_test_mkdir_A");
+       if (!parent)
+               goto cleanup;
+
+       child = cg_name(parent, "cg_test_mkdir_B");
+       if (!child)
+               goto cleanup;
+
+       if (cg_create(parent))
+               goto cleanup;
+
+       if (cg_freeze_wait(parent, true))
+               goto cleanup;
+
+       if (cg_create(child))
+               goto cleanup;
+
+       pid = cg_run_nowait(child, child_fn, NULL);
+       if (pid < 0)
+               goto cleanup;
+
+       if (cg_wait_for_proc_count(child, 1))
+               goto cleanup;
+
+       if (cg_check_frozen(child, true))
+               goto cleanup;
+
+       if (cg_check_frozen(parent, true))
+               goto cleanup;
+
+       ret = KSFT_PASS;
+
+cleanup:
+       if (child)
+               cg_destroy(child);
+       free(child);
+       if (parent)
+               cg_destroy(parent);
+       free(parent);
+       return ret;
+}
+
 /*
  * The test creates two nested cgroups, freezes the parent
  * and removes the child. Then it checks that the parent cgroup
@@ -815,6 +868,7 @@ struct cgfreezer_test {
        T(test_cgfreezer_simple),
        T(test_cgfreezer_tree),
        T(test_cgfreezer_forkbomb),
+       T(test_cgfreezer_mkdir),
        T(test_cgfreezer_rmdir),
        T(test_cgfreezer_migrate),
        T(test_cgfreezer_ptrace),
index 71231ad2dbfb5d2d4c3082a6669578dab59fcaef..47315fe48d5af51aa0593b0e0546dfff142976ba 100755 (executable)
@@ -262,7 +262,7 @@ test_mc_aware()
 
        stop_traffic
 
-       log_test "UC performace under MC overload"
+       log_test "UC performance under MC overload"
 
        echo "UC-only throughput  $(humanize $ucth1)"
        echo "UC+MC throughput    $(humanize $ucth2)"
@@ -316,7 +316,7 @@ test_uc_aware()
 
        stop_traffic
 
-       log_test "MC performace under UC overload"
+       log_test "MC performance under UC overload"
        echo "    ingress UC throughput $(humanize ${uc_ir})"
        echo "    egress UC throughput  $(humanize ${uc_er})"
        echo "    sent $attempts BC ARPs, got $passes responses"
index 0a76314b441494fcc38844c322fcaf1114912021..8b944cf042f6c8a98c8a303e230c47b1f57c75d4 100755 (executable)
@@ -28,7 +28,7 @@
 # override by exporting to your environment prior running this script.
 # For instance this script assumes you do not have xfs loaded upon boot.
 # If this is false, export DEFAULT_KMOD_FS="ext4" prior to running this
-# script if the filesyste module you don't have loaded upon bootup
+# script if the filesystem module you don't have loaded upon bootup
 # is ext4 instead. Refer to allow_user_defaults() for a list of user
 # override variables possible.
 #
@@ -263,7 +263,7 @@ config_get_test_result()
 config_reset()
 {
        if ! echo -n "1" >"$DIR"/reset; then
-               echo "$0: reset shuld have worked" >&2
+               echo "$0: reset should have worked" >&2
                exit 1
        fi
 }
@@ -488,7 +488,7 @@ usage()
        echo Example uses:
        echo
        echo "${TEST_NAME}.sh           -- executes all tests"
-       echo "${TEST_NAME}.sh -t 0008   -- Executes test ID 0008 number of times is recomended"
+       echo "${TEST_NAME}.sh -t 0008   -- Executes test ID 0008 number of times is recommended"
        echo "${TEST_NAME}.sh -w 0008   -- Watch test ID 0008 run until an error occurs"
        echo "${TEST_NAME}.sh -s 0008   -- Run test ID 0008 once"
        echo "${TEST_NAME}.sh -c 0008 3 -- Run test ID 0008 three times"
index ec15c4f6af552d57a5584e18abb7cb9bb17cc90f..0ac49d91a26023c3eb10804f4cf77fc004b4d080 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef __KSELFTEST_H
 #define __KSELFTEST_H
 
+#include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdarg.h>
@@ -81,58 +82,68 @@ static inline void ksft_print_cnts(void)
 
 static inline void ksft_print_msg(const char *msg, ...)
 {
+       int saved_errno = errno;
        va_list args;
 
        va_start(args, msg);
        printf("# ");
+       errno = saved_errno;
        vprintf(msg, args);
        va_end(args);
 }
 
 static inline void ksft_test_result_pass(const char *msg, ...)
 {
+       int saved_errno = errno;
        va_list args;
 
        ksft_cnt.ksft_pass++;
 
        va_start(args, msg);
        printf("ok %d ", ksft_test_num());
+       errno = saved_errno;
        vprintf(msg, args);
        va_end(args);
 }
 
 static inline void ksft_test_result_fail(const char *msg, ...)
 {
+       int saved_errno = errno;
        va_list args;
 
        ksft_cnt.ksft_fail++;
 
        va_start(args, msg);
        printf("not ok %d ", ksft_test_num());
+       errno = saved_errno;
        vprintf(msg, args);
        va_end(args);
 }
 
 static inline void ksft_test_result_skip(const char *msg, ...)
 {
+       int saved_errno = errno;
        va_list args;
 
        ksft_cnt.ksft_xskip++;
 
        va_start(args, msg);
        printf("not ok %d # SKIP ", ksft_test_num());
+       errno = saved_errno;
        vprintf(msg, args);
        va_end(args);
 }
 
 static inline void ksft_test_result_error(const char *msg, ...)
 {
+       int saved_errno = errno;
        va_list args;
 
        ksft_cnt.ksft_error++;
 
        va_start(args, msg);
        printf("not ok %d # error ", ksft_test_num());
+       errno = saved_errno;
        vprintf(msg, args);
        va_end(args);
 }
@@ -152,10 +163,12 @@ static inline int ksft_exit_fail(void)
 
 static inline int ksft_exit_fail_msg(const char *msg, ...)
 {
+       int saved_errno = errno;
        va_list args;
 
        va_start(args, msg);
        printf("Bail out! ");
+       errno = saved_errno;
        vprintf(msg, args);
        va_end(args);
 
@@ -178,10 +191,12 @@ static inline int ksft_exit_xpass(void)
 static inline int ksft_exit_skip(const char *msg, ...)
 {
        if (msg) {
+               int saved_errno = errno;
                va_list args;
 
                va_start(args, msg);
                printf("not ok %d # SKIP ", 1 + ksft_test_num());
+               errno = saved_errno;
                vprintf(msg, args);
                va_end(args);
        } else {
index 41266af0d3dc8b37268ec0a2500ec88391ae82c1..b35da375530afb1a3d2166aeac07c49f4cff11a7 100644 (file)
@@ -1,7 +1,7 @@
+/s390x/sync_regs_test
 /x86_64/cr4_cpuid_sync_test
 /x86_64/evmcs_test
 /x86_64/hyperv_cpuid
-/x86_64/kvm_create_max_vcpus
 /x86_64/mmio_warning_test
 /x86_64/platform_info_test
 /x86_64/set_sregs_test
@@ -13,3 +13,4 @@
 /x86_64/vmx_tsc_adjust_test
 /clear_dirty_log_test
 /dirty_log_test
+/kvm_create_max_vcpus
diff --git a/tools/testing/selftests/kvm/config b/tools/testing/selftests/kvm/config
new file mode 100644 (file)
index 0000000..63ed533
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_KVM=y
+CONFIG_KVM_INTEL=y
+CONFIG_KVM_AMD=y
index 4059014d93ea12ab235fa5706e36a4eb16c8c85d..4912d23844bc693d6ea97be6367d4b3022586eb3 100644 (file)
@@ -220,6 +220,8 @@ struct hv_enlightened_vmcs {
 struct hv_enlightened_vmcs *current_evmcs;
 struct hv_vp_assist_page *current_vp_assist;
 
+int vcpu_enable_evmcs(struct kvm_vm *vm, int vcpu_id);
+
 static inline int enable_vp_assist(uint64_t vp_assist_pa, void *vp_assist)
 {
        u64 val = (vp_assist_pa & HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_MASK) |
index 6cb34a0fa20053f7c37d8603f921fb86c71a6dc5..0a5e487dbc502ecf0e3ef914e9ac6061b3bdbb1b 100644 (file)
@@ -1060,9 +1060,11 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
         TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XSAVE, r: %i",
                 r);
 
-       r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
-                r);
+       if (kvm_check_cap(KVM_CAP_XCRS)) {
+               r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
+               TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
+                           r);
+       }
 
        r = ioctl(vcpu->fd, KVM_GET_SREGS, &state->sregs);
         TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_SREGS, r: %i",
@@ -1103,9 +1105,11 @@ void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *s
         TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XSAVE, r: %i",
                 r);
 
-       r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
-                r);
+       if (kvm_check_cap(KVM_CAP_XCRS)) {
+               r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
+               TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
+                           r);
+       }
 
        r = ioctl(vcpu->fd, KVM_SET_SREGS, &state->sregs);
         TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_SREGS, r: %i",
index 204f847bd065a66b5569c3f209c4fb3725ae5064..9cef0455b819c39688bc57551d99f8fb76abf4be 100644 (file)
 
 bool enable_evmcs;
 
+int vcpu_enable_evmcs(struct kvm_vm *vm, int vcpu_id)
+{
+       uint16_t evmcs_ver;
+
+       struct kvm_enable_cap enable_evmcs_cap = {
+               .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
+                .args[0] = (unsigned long)&evmcs_ver
+       };
+
+       vcpu_ioctl(vm, vcpu_id, KVM_ENABLE_CAP, &enable_evmcs_cap);
+
+       /* KVM should return supported EVMCS version range */
+       TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
+                   (evmcs_ver & 0xff) > 0,
+                   "Incorrect EVMCS version range: %x:%x\n",
+                   evmcs_ver & 0xff, evmcs_ver >> 8);
+
+       return evmcs_ver;
+}
+
 /* Allocate memory regions for nested VMX tests.
  *
  * Input Args:
index f95c08343b487d4a4ec2698d18b08d191a612675..92915e6408e766ef8218f945545205b918286e42 100644 (file)
@@ -79,11 +79,6 @@ int main(int argc, char *argv[])
        struct kvm_x86_state *state;
        struct ucall uc;
        int stage;
-       uint16_t evmcs_ver;
-       struct kvm_enable_cap enable_evmcs_cap = {
-               .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
-                .args[0] = (unsigned long)&evmcs_ver
-       };
 
        /* Create VM */
        vm = vm_create_default(VCPU_ID, 0, guest_code);
@@ -96,13 +91,7 @@ int main(int argc, char *argv[])
                exit(KSFT_SKIP);
        }
 
-       vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
-
-       /* KVM should return supported EVMCS version range */
-       TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
-                   (evmcs_ver & 0xff) > 0,
-                   "Incorrect EVMCS version range: %x:%x\n",
-                   evmcs_ver & 0xff, evmcs_ver >> 8);
+       vcpu_enable_evmcs(vm, VCPU_ID);
 
        run = vcpu_state(vm, VCPU_ID);
 
@@ -146,7 +135,7 @@ int main(int argc, char *argv[])
                kvm_vm_restart(vm, O_RDWR);
                vm_vcpu_add(vm, VCPU_ID);
                vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
-               vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
+               vcpu_enable_evmcs(vm, VCPU_ID);
                vcpu_load_state(vm, VCPU_ID, state);
                run = vcpu_state(vm, VCPU_ID);
                free(state);
index f72b3043db0ebc99b8934fde19a61c5a60e42748..ee59831fbc98474777514a919bb9864c61f3c04a 100644 (file)
@@ -18,6 +18,7 @@
 #include "test_util.h"
 #include "kvm_util.h"
 #include "processor.h"
+#include "vmx.h"
 
 #define VCPU_ID 0
 
@@ -106,12 +107,7 @@ int main(int argc, char *argv[])
 {
        struct kvm_vm *vm;
        int rv;
-       uint16_t evmcs_ver;
        struct kvm_cpuid2 *hv_cpuid_entries;
-       struct kvm_enable_cap enable_evmcs_cap = {
-               .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
-                .args[0] = (unsigned long)&evmcs_ver
-       };
 
        /* Tell stdout not to buffer its content */
        setbuf(stdout, NULL);
@@ -136,14 +132,14 @@ int main(int argc, char *argv[])
 
        free(hv_cpuid_entries);
 
-       rv = _vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
-
-       if (rv) {
+       if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
                fprintf(stderr,
                        "Enlightened VMCS is unsupported, skip related test\n");
                goto vm_free;
        }
 
+       vcpu_enable_evmcs(vm, VCPU_ID);
+
        hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
        if (!hv_cpuid_entries)
                return 1;
index 40050e44ec0acd63cba5372f9a7737c2c428d62a..f9334bd3cce9f4a2fe425d8a949aa1f9e062b7ee 100644 (file)
@@ -99,8 +99,8 @@ int main(int argc, char *argv[])
        msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
        vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
                msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
-       test_msr_platform_info_disabled(vm);
        test_msr_platform_info_enabled(vm);
+       test_msr_platform_info_disabled(vm);
        vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
 
        kvm_vm_free(vm);
index ed7218d166da6c36754b115bad4767b76378c682..853e370e8a3942c559925f37d0387e68a81aeef0 100644 (file)
 #define VMCS12_REVISION 0x11e57ed0
 #define VCPU_ID 5
 
+bool have_evmcs;
+
 void test_nested_state(struct kvm_vm *vm, struct kvm_nested_state *state)
 {
-       volatile struct kvm_run *run;
-
        vcpu_nested_state_set(vm, VCPU_ID, state, false);
-       run = vcpu_state(vm, VCPU_ID);
-       vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
-               "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s),\n",
-               run->exit_reason,
-               exit_reason_str(run->exit_reason));
 }
 
 void test_nested_state_expect_errno(struct kvm_vm *vm,
                                    struct kvm_nested_state *state,
                                    int expected_errno)
 {
-       volatile struct kvm_run *run;
        int rv;
 
        rv = vcpu_nested_state_set(vm, VCPU_ID, state, true);
@@ -50,12 +43,6 @@ void test_nested_state_expect_errno(struct kvm_vm *vm,
                "Expected %s (%d) from vcpu_nested_state_set but got rv: %i errno: %s (%d)",
                strerror(expected_errno), expected_errno, rv, strerror(errno),
                errno);
-       run = vcpu_state(vm, VCPU_ID);
-       vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
-               "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s),\n",
-               run->exit_reason,
-               exit_reason_str(run->exit_reason));
 }
 
 void test_nested_state_expect_einval(struct kvm_vm *vm,
@@ -90,8 +77,9 @@ void set_default_vmx_state(struct kvm_nested_state *state, int size)
 {
        memset(state, 0, size);
        state->flags = KVM_STATE_NESTED_GUEST_MODE  |
-                       KVM_STATE_NESTED_RUN_PENDING |
-                       KVM_STATE_NESTED_EVMCS;
+                       KVM_STATE_NESTED_RUN_PENDING;
+       if (have_evmcs)
+               state->flags |= KVM_STATE_NESTED_EVMCS;
        state->format = 0;
        state->size = size;
        state->hdr.vmx.vmxon_pa = 0x1000;
@@ -141,13 +129,19 @@ void test_vmx_nested_state(struct kvm_vm *vm)
        /*
         * Setting vmxon_pa == -1ull and vmcs_pa == -1ull exits early without
         * setting the nested state but flags other than eVMCS must be clear.
+        * The eVMCS flag can be set if the enlightened VMCS capability has
+        * been enabled.
         */
        set_default_vmx_state(state, state_sz);
        state->hdr.vmx.vmxon_pa = -1ull;
        state->hdr.vmx.vmcs12_pa = -1ull;
        test_nested_state_expect_einval(vm, state);
 
-       state->flags = KVM_STATE_NESTED_EVMCS;
+       state->flags &= KVM_STATE_NESTED_EVMCS;
+       if (have_evmcs) {
+               test_nested_state_expect_einval(vm, state);
+               vcpu_enable_evmcs(vm, VCPU_ID);
+       }
        test_nested_state(vm, state);
 
        /* It is invalid to have vmxon_pa == -1ull and SMM flags non-zero. */
@@ -232,6 +226,8 @@ int main(int argc, char *argv[])
        struct kvm_nested_state state;
        struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
 
+       have_evmcs = kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS);
+
        if (!kvm_check_cap(KVM_CAP_NESTED_STATE)) {
                printf("KVM_CAP_NESTED_STATE not available, skipping test\n");
                exit(KSFT_SKIP);
index 30195449c63c92c92ffaa8de326d44ec5a152e49..79b0affd21fbddf6d6075a216b536592f6fc3305 100644 (file)
@@ -13,6 +13,14 @@ function log() {
        echo "$1" > /dev/kmsg
 }
 
+# skip(msg) - testing can't proceed
+#      msg - explanation
+function skip() {
+       log "SKIP: $1"
+       echo "SKIP: $1" >&2
+       exit 4
+}
+
 # die(msg) - game over, man
 #      msg - dying words
 function die() {
@@ -21,13 +29,27 @@ function die() {
        exit 1
 }
 
-# set_dynamic_debug() - setup kernel dynamic debug
-#      TODO - push and pop this config?
+function push_dynamic_debug() {
+        DYNAMIC_DEBUG=$(grep '^kernel/livepatch' /sys/kernel/debug/dynamic_debug/control | \
+                awk -F'[: ]' '{print "file " $1 " line " $2 " " $4}')
+}
+
+function pop_dynamic_debug() {
+       if [[ -n "$DYNAMIC_DEBUG" ]]; then
+               echo -n "$DYNAMIC_DEBUG" > /sys/kernel/debug/dynamic_debug/control
+       fi
+}
+
+# set_dynamic_debug() - save the current dynamic debug config and tweak
+#                      it for the self-tests.  Set a script exit trap
+#                      that restores the original config.
 function set_dynamic_debug() {
-       cat << EOF > /sys/kernel/debug/dynamic_debug/control
-file kernel/livepatch/* +p
-func klp_try_switch_task -p
-EOF
+        push_dynamic_debug
+        trap pop_dynamic_debug EXIT INT TERM HUP
+        cat <<-EOF > /sys/kernel/debug/dynamic_debug/control
+               file kernel/livepatch/* +p
+               func klp_try_switch_task -p
+               EOF
 }
 
 # loop_until(cmd) - loop a command until it is successful or $MAX_RETRIES,
@@ -43,6 +65,12 @@ function loop_until() {
        done
 }
 
+function assert_mod() {
+       local mod="$1"
+
+       modprobe --dry-run "$mod" &>/dev/null
+}
+
 function is_livepatch_mod() {
        local mod="$1"
 
@@ -75,6 +103,9 @@ function __load_mod() {
 function load_mod() {
        local mod="$1"; shift
 
+       assert_mod "$mod" ||
+               skip "unable to load module ${mod}, verify CONFIG_TEST_LIVEPATCH=m and run self-tests as root"
+
        is_livepatch_mod "$mod" &&
                die "use load_lp() to load the livepatch module $mod"
 
@@ -88,6 +119,9 @@ function load_mod() {
 function load_lp_nowait() {
        local mod="$1"; shift
 
+       assert_mod "$mod" ||
+               skip "unable to load module ${mod}, verify CONFIG_TEST_LIVEPATCH=m and run self-tests as root"
+
        is_livepatch_mod "$mod" ||
                die "module $mod is not a livepatch"
 
index 4ce0bc1612f5495444d72f678d6368d54e6a10c1..c7cced739c34bcada309cae1ce7607af04637887 100644 (file)
@@ -17,7 +17,7 @@ tcp_inq
 tls
 txring_overwrite
 ip_defrag
+ipv6_flowlabel
+ipv6_flowlabel_mgr
 so_txtime
-flowlabel
-flowlabel_mgr
 tcp_fastopen_backup_key
index c5c93d5fb3ade4fbd24d668d227281712ae9894b..f9ebeac1e6f20e8fcafba752a916c87d61dfb7ca 100755 (executable)
@@ -212,6 +212,8 @@ check_output()
                        printf "        ${out}\n"
                        printf "    Expected:\n"
                        printf "        ${expected}\n\n"
+               else
+                       echo "      WARNING: Unexpected route entry"
                fi
        fi
 
@@ -274,7 +276,7 @@ ipv6_fcnal()
 
        run_cmd "$IP nexthop get id 52"
        log_test $? 0 "Get nexthop by id"
-       check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1"
+       check_nexthop "id 52" "id 52 via 2001:db8:91::2 dev veth1 scope link"
 
        run_cmd "$IP nexthop del id 52"
        log_test $? 0 "Delete nexthop by id"
@@ -479,12 +481,12 @@ ipv6_fcnal_runtime()
        run_cmd "$IP -6 nexthop add id 85 dev veth1"
        run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 85"
        log_test $? 0 "IPv6 route with device only nexthop"
-       check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1"
+       check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 dev veth1 metric 1024 pref medium"
 
        run_cmd "$IP nexthop add id 123 group 81/85"
        run_cmd "$IP ro replace 2001:db8:101::1/128 nhid 123"
        log_test $? 0 "IPv6 multipath route with nexthop mix - dev only + gw"
-       check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 85 nexthop via 2001:db8:91::2 dev veth1 nexthop dev veth1"
+       check_route6 "2001:db8:101::1" "2001:db8:101::1 nhid 123 metric 1024 nexthop via 2001:db8:91::2 dev veth1 weight 1 nexthop dev veth1 weight 1 pref medium"
 
        #
        # IPv6 route with v4 nexthop - not allowed
@@ -538,7 +540,7 @@ ipv4_fcnal()
 
        run_cmd "$IP nexthop get id 12"
        log_test $? 0 "Get nexthop by id"
-       check_nexthop "id 12" "id 12 via 172.16.1.2 src 172.16.1.1 dev veth1 scope link"
+       check_nexthop "id 12" "id 12 via 172.16.1.2 dev veth1 scope link"
 
        run_cmd "$IP nexthop del id 12"
        log_test $? 0 "Delete nexthop by id"
@@ -685,7 +687,7 @@ ipv4_withv6_fcnal()
        set +e
        run_cmd "$IP ro add 172.16.101.1/32 nhid 11"
        log_test $? 0 "IPv6 nexthop with IPv4 route"
-       check_route "172.16.101.1" "172.16.101.1 nhid 11 via ${lladdr} dev veth1"
+       check_route "172.16.101.1" "172.16.101.1 nhid 11 via inet6 ${lladdr} dev veth1"
 
        set -e
        run_cmd "$IP nexthop add id 12 via 172.16.1.2 dev veth1"
@@ -694,11 +696,11 @@ ipv4_withv6_fcnal()
        run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
        log_test $? 0 "IPv6 nexthop with IPv4 route"
 
-       check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
+       check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
 
        run_cmd "$IP ro replace 172.16.101.1/32 via inet6 ${lladdr} dev veth1"
        log_test $? 0 "IPv4 route with IPv6 gateway"
-       check_route "172.16.101.1" "172.16.101.1 via ${lladdr} dev veth1"
+       check_route "172.16.101.1" "172.16.101.1 via inet6 ${lladdr} dev veth1"
 
        run_cmd "$IP ro replace 172.16.101.1/32 via inet6 2001:db8:50::1 dev veth1"
        log_test $? 2 "IPv4 route with invalid IPv6 gateway"
@@ -785,10 +787,10 @@ ipv4_fcnal_runtime()
        log_test $? 0 "IPv4 route with device only nexthop"
        check_route "172.16.101.1" "172.16.101.1 nhid 85 dev veth1"
 
-       run_cmd "$IP nexthop add id 122 group 21/85"
-       run_cmd "$IP ro replace 172.16.101.1/32 nhid 122"
+       run_cmd "$IP nexthop add id 123 group 21/85"
+       run_cmd "$IP ro replace 172.16.101.1/32 nhid 123"
        log_test $? 0 "IPv4 multipath route with nexthop mix - dev only + gw"
-       check_route "172.16.101.1" "172.16.101.1 nhid 85 nexthop via 172.16.1.2 dev veth1 nexthop dev veth1"
+       check_route "172.16.101.1" "172.16.101.1 nhid 123 nexthop via 172.16.1.2 dev veth1 weight 1 nexthop dev veth1 weight 1"
 
        #
        # IPv4 with IPv6
@@ -820,7 +822,7 @@ ipv4_fcnal_runtime()
        run_cmd "$IP ro replace 172.16.101.1/32 nhid 101"
        log_test $? 0 "IPv4 route with mixed v4-v6 multipath route"
 
-       check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
+       check_route "172.16.101.1" "172.16.101.1 nhid 101 nexthop via inet6 ${lladdr} dev veth1 weight 1 nexthop via 172.16.1.2 dev veth1 weight 1"
 
        run_cmd "ip netns exec me ping -c1 -w1 172.16.101.1"
        log_test $? 0 "IPv6 nexthop with IPv4 route"
index cca2baa03fb81b12f393a1df566dbe0494cabe27..a8d8e8b3dc819f3abc90060eaa0d312632c2145f 100755 (executable)
@@ -93,18 +93,10 @@ sw1_create()
        ip route add vrf v$ol1 192.0.2.16/28 \
           nexthop dev g1a \
           nexthop dev g1b
-
-       tc qdisc add dev $ul1 clsact
-       tc filter add dev $ul1 egress pref 111 prot ipv4 \
-          flower dst_ip 192.0.2.66 action pass
-       tc filter add dev $ul1 egress pref 222 prot ipv4 \
-          flower dst_ip 192.0.2.82 action pass
 }
 
 sw1_destroy()
 {
-       tc qdisc del dev $ul1 clsact
-
        ip route del vrf v$ol1 192.0.2.16/28
 
        ip route del vrf v$ol1 192.0.2.82/32 via 192.0.2.146
@@ -139,10 +131,18 @@ sw2_create()
        ip route add vrf v$ol2 192.0.2.0/28 \
           nexthop dev g2a \
           nexthop dev g2b
+
+       tc qdisc add dev $ul2 clsact
+       tc filter add dev $ul2 ingress pref 111 prot 802.1Q \
+          flower vlan_id 111 action pass
+       tc filter add dev $ul2 ingress pref 222 prot 802.1Q \
+          flower vlan_id 222 action pass
 }
 
 sw2_destroy()
 {
+       tc qdisc del dev $ul2 clsact
+
        ip route del vrf v$ol2 192.0.2.0/28
 
        ip route del vrf v$ol2 192.0.2.81/32 via 192.0.2.145
@@ -187,12 +187,16 @@ setup_prepare()
        sw1_create
        sw2_create
        h2_create
+
+       forwarding_enable
 }
 
 cleanup()
 {
        pre_cleanup
 
+       forwarding_restore
+
        h2_destroy
        sw2_destroy
        sw1_destroy
@@ -211,15 +215,15 @@ multipath4_test()
           nexthop dev g1a weight $weight1 \
           nexthop dev g1b weight $weight2
 
-       local t0_111=$(tc_rule_stats_get $ul1 111 egress)
-       local t0_222=$(tc_rule_stats_get $ul1 222 egress)
+       local t0_111=$(tc_rule_stats_get $ul2 111 ingress)
+       local t0_222=$(tc_rule_stats_get $ul2 222 ingress)
 
        ip vrf exec v$h1 \
           $MZ $h1 -q -p 64 -A 192.0.2.1 -B 192.0.2.18 \
               -d 1msec -t udp "sp=1024,dp=0-32768"
 
-       local t1_111=$(tc_rule_stats_get $ul1 111 egress)
-       local t1_222=$(tc_rule_stats_get $ul1 222 egress)
+       local t1_111=$(tc_rule_stats_get $ul2 111 ingress)
+       local t1_222=$(tc_rule_stats_get $ul2 222 ingress)
 
        local d111=$((t1_111 - t0_111))
        local d222=$((t1_222 - t0_222))
index 41476399e184f9cbb13f4541918e80fea4f18cbf..f6e65674b83cec86c215605048a81e63e0d7c20d 100755 (executable)
@@ -30,7 +30,7 @@ do_test() {
        ip netns exec "${NETNS}" ./tcp_fastopen_backup_key "$1"
        val=$(ip netns exec "${NETNS}" nstat -az | \
                grep TcpExtTCPFastOpenPassiveFail | awk '{print $2}')
-       if [ $val -ne 0 ]; then
+       if [ "$val" != 0 ]; then
                echo "FAIL: TcpExtTCPFastOpenPassiveFail non-zero"
                return 1
        fi
index 090fff9dbc48f11a28ccba2444e80a3ac806a683..4c285b6e1db8c1713b70e6be5092b780bb5e0d6a 100644 (file)
 #define TLS_PAYLOAD_MAX_LEN 16384
 #define SOL_TLS 282
 
+#ifndef ENOTSUPP
+#define ENOTSUPP 524
+#endif
+
+FIXTURE(tls_basic)
+{
+       int fd, cfd;
+       bool notls;
+};
+
+FIXTURE_SETUP(tls_basic)
+{
+       struct sockaddr_in addr;
+       socklen_t len;
+       int sfd, ret;
+
+       self->notls = false;
+       len = sizeof(addr);
+
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_ANY);
+       addr.sin_port = 0;
+
+       self->fd = socket(AF_INET, SOCK_STREAM, 0);
+       sfd = socket(AF_INET, SOCK_STREAM, 0);
+
+       ret = bind(sfd, &addr, sizeof(addr));
+       ASSERT_EQ(ret, 0);
+       ret = listen(sfd, 10);
+       ASSERT_EQ(ret, 0);
+
+       ret = getsockname(sfd, &addr, &len);
+       ASSERT_EQ(ret, 0);
+
+       ret = connect(self->fd, &addr, sizeof(addr));
+       ASSERT_EQ(ret, 0);
+
+       self->cfd = accept(sfd, &addr, &len);
+       ASSERT_GE(self->cfd, 0);
+
+       close(sfd);
+
+       ret = setsockopt(self->fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       if (ret != 0) {
+               ASSERT_EQ(errno, ENOENT);
+               self->notls = true;
+               printf("Failure setting TCP_ULP, testing without tls\n");
+               return;
+       }
+
+       ret = setsockopt(self->cfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       ASSERT_EQ(ret, 0);
+}
+
+FIXTURE_TEARDOWN(tls_basic)
+{
+       close(self->fd);
+       close(self->cfd);
+}
+
+/* Send some data through with ULP but no keys */
+TEST_F(tls_basic, base_base)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+       char buf[10];
+
+       ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+       EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+       EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+};
+
 FIXTURE(tls)
 {
        int fd, cfd;
@@ -165,6 +239,16 @@ TEST_F(tls, msg_more)
        EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
 }
 
+TEST_F(tls, msg_more_unsent)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+       char buf[10];
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, MSG_MORE), send_len);
+       EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_DONTWAIT), -1);
+}
+
 TEST_F(tls, sendmsg_single)
 {
        struct msghdr msg;
@@ -610,6 +694,42 @@ TEST_F(tls, recv_lowat)
        EXPECT_EQ(memcmp(send_mem, recv_mem + 10, 5), 0);
 }
 
+TEST_F(tls, bidir)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+       char buf[10];
+       int ret;
+
+       if (!self->notls) {
+               struct tls12_crypto_info_aes_gcm_128 tls12;
+
+               memset(&tls12, 0, sizeof(tls12));
+               tls12.info.version = TLS_1_3_VERSION;
+               tls12.info.cipher_type = TLS_CIPHER_AES_GCM_128;
+
+               ret = setsockopt(self->fd, SOL_TLS, TLS_RX, &tls12,
+                                sizeof(tls12));
+               ASSERT_EQ(ret, 0);
+
+               ret = setsockopt(self->cfd, SOL_TLS, TLS_TX, &tls12,
+                                sizeof(tls12));
+               ASSERT_EQ(ret, 0);
+       }
+
+       ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+       EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+       EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+
+       memset(buf, 0, sizeof(buf));
+
+       EXPECT_EQ(send(self->cfd, test_str, send_len, 0), send_len);
+       EXPECT_NE(recv(self->fd, buf, send_len, 0), -1);
+       EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+};
+
 TEST_F(tls, pollin)
 {
        char const *test_str = "test_poll";
@@ -837,6 +957,109 @@ TEST_F(tls, control_msg)
        EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
 }
 
+TEST_F(tls, shutdown)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+       char buf[10];
+
+       ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+       EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+       EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+
+       shutdown(self->fd, SHUT_RDWR);
+       shutdown(self->cfd, SHUT_RDWR);
+}
+
+TEST_F(tls, shutdown_unsent)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, MSG_MORE), send_len);
+
+       shutdown(self->fd, SHUT_RDWR);
+       shutdown(self->cfd, SHUT_RDWR);
+}
+
+TEST_F(tls, shutdown_reuse)
+{
+       struct sockaddr_in addr;
+       int ret;
+
+       shutdown(self->fd, SHUT_RDWR);
+       shutdown(self->cfd, SHUT_RDWR);
+       close(self->cfd);
+
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_ANY);
+       addr.sin_port = 0;
+
+       ret = bind(self->fd, &addr, sizeof(addr));
+       EXPECT_EQ(ret, 0);
+       ret = listen(self->fd, 10);
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, EINVAL);
+
+       ret = connect(self->fd, &addr, sizeof(addr));
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, EISCONN);
+}
+
+TEST(non_established) {
+       struct tls12_crypto_info_aes_gcm_256 tls12;
+       struct sockaddr_in addr;
+       int sfd, ret, fd;
+       socklen_t len;
+
+       len = sizeof(addr);
+
+       memset(&tls12, 0, sizeof(tls12));
+       tls12.info.version = TLS_1_2_VERSION;
+       tls12.info.cipher_type = TLS_CIPHER_AES_GCM_256;
+
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_ANY);
+       addr.sin_port = 0;
+
+       fd = socket(AF_INET, SOCK_STREAM, 0);
+       sfd = socket(AF_INET, SOCK_STREAM, 0);
+
+       ret = bind(sfd, &addr, sizeof(addr));
+       ASSERT_EQ(ret, 0);
+       ret = listen(sfd, 10);
+       ASSERT_EQ(ret, 0);
+
+       ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       EXPECT_EQ(ret, -1);
+       /* TLS ULP not supported */
+       if (errno == ENOENT)
+               return;
+       EXPECT_EQ(errno, ENOTSUPP);
+
+       ret = setsockopt(sfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, ENOTSUPP);
+
+       ret = getsockname(sfd, &addr, &len);
+       ASSERT_EQ(ret, 0);
+
+       ret = connect(fd, &addr, sizeof(addr));
+       ASSERT_EQ(ret, 0);
+
+       ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       ASSERT_EQ(ret, 0);
+
+       ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, EEXIST);
+
+       close(fd);
+       close(sfd);
+}
+
 TEST(keysizes) {
        struct tls12_crypto_info_aes_gcm_256 tls12;
        struct sockaddr_in addr;
index 5445943bf07f222acaba83a253668ec06db032e5..7a1bf94c5bd38bc9837b87911a082a1ef287eee8 100755 (executable)
@@ -106,6 +106,13 @@ do_overlap()
     #
     # 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23.
     ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block
+
+    # similar to above: add policies (with partially random address), with shrinking prefixes.
+    for p in 29 28 27;do
+      for k in $(seq 1 32); do
+       ip -net $ns xfrm policy add src 10.253.1.$((RANDOM%255))/$p dst 10.254.1.$((RANDOM%255))/$p dir fwd priority $((200+k)) action block 2>/dev/null
+      done
+    done
 }
 
 do_esp_policy_get_check() {
index fe52488a6f729b5a78eaf6dfa10230acb7abe957..16571ac1dab40267fc2141f924839aa671784d1d 100755 (executable)
@@ -321,4 +321,52 @@ else
        ip netns exec nsr1 nft list ruleset
 fi
 
+KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1)
+KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1)
+SPI1=$RANDOM
+SPI2=$RANDOM
+
+if [ $SPI1 -eq $SPI2 ]; then
+       SPI2=$((SPI2+1))
+fi
+
+do_esp() {
+    local ns=$1
+    local me=$2
+    local remote=$3
+    local lnet=$4
+    local rnet=$5
+    local spi_out=$6
+    local spi_in=$7
+
+    ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in  enc aes $KEY_AES  auth sha1 $KEY_SHA mode tunnel sel src $rnet dst $lnet
+    ip -net $ns xfrm state add src $me  dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet
+
+    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
+    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 1 action allow
+    # to fwd decrypted packets after esp processing:
+    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 1 action allow
+
+}
+
+do_esp nsr1 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2
+
+do_esp nsr2 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1
+
+ip netns exec nsr1 nft delete table ip nat
+
+# restore default routes
+ip -net ns2 route del 192.168.10.1 via 10.0.2.1
+ip -net ns2 route add default via 10.0.2.1
+ip -net ns2 route add default via dead:2::1
+
+test_tcp_forwarding ns1 ns2
+if [ $? -eq 0 ] ;then
+       echo "PASS: ipsec tunnel mode for ns1/ns2"
+else
+       echo "FAIL: ipsec tunnel mode for ns1/ns2"
+       ip netns exec nsr1 nft list ruleset 1>&2
+       ip netns exec nsr1 cat /proc/net/xfrm_stat 1>&2
+fi
+
 exit $ret
index 7eaa8a3de26277212aa8350bb90e9098c9118741..b632965e60eb0758a1197faedd44f0b3e7d5c829 100644 (file)
@@ -339,13 +339,9 @@ static int test_pidfd_send_signal_syscall_support(void)
 
        ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0);
        if (ret < 0) {
-               /*
-                * pidfd_send_signal() will currently return ENOSYS when
-                * CONFIG_PROC_FS is not set.
-                */
                if (errno == ENOSYS)
                        ksft_exit_skip(
-                               "%s test: pidfd_send_signal() syscall not supported (Ensure that CONFIG_PROC_FS=y is set)\n",
+                               "%s test: pidfd_send_signal() syscall not supported\n",
                                test_name);
 
                ksft_exit_fail_msg("%s test: Failed to send signal\n",
index affa7f2d96702c9e399caccc5d497f4cb144eca2..9539cffa9e5e3556c53f9aaf9f1b1e25ddd6c649 100644 (file)
@@ -64,7 +64,7 @@ class SubPlugin(TdcPlugin):
             cmdlist.insert(0, self.args.NAMES['NS'])
             cmdlist.insert(0, 'exec')
             cmdlist.insert(0, 'netns')
-            cmdlist.insert(0, 'ip')
+            cmdlist.insert(0, self.args.NAMES['IP'])
         else:
             pass
 
@@ -78,16 +78,16 @@ class SubPlugin(TdcPlugin):
         return command
 
     def _ports_create(self):
-        cmd = 'ip link add $DEV0 type veth peer name $DEV1'
+        cmd = '$IP link add $DEV0 type veth peer name $DEV1'
         self._exec_cmd('pre', cmd)
-        cmd = 'ip link set $DEV0 up'
+        cmd = '$IP link set $DEV0 up'
         self._exec_cmd('pre', cmd)
         if not self.args.namespace:
-            cmd = 'ip link set $DEV1 up'
+            cmd = '$IP link set $DEV1 up'
             self._exec_cmd('pre', cmd)
 
     def _ports_destroy(self):
-        cmd = 'ip link del $DEV0'
+        cmd = '$IP link del $DEV0'
         self._exec_cmd('post', cmd)
 
     def _ns_create(self):
@@ -97,16 +97,16 @@ class SubPlugin(TdcPlugin):
         '''
         self._ports_create()
         if self.args.namespace:
-            cmd = 'ip netns add {}'.format(self.args.NAMES['NS'])
+            cmd = '$IP netns add {}'.format(self.args.NAMES['NS'])
             self._exec_cmd('pre', cmd)
-            cmd = 'ip link set $DEV1 netns {}'.format(self.args.NAMES['NS'])
+            cmd = '$IP link set $DEV1 netns {}'.format(self.args.NAMES['NS'])
             self._exec_cmd('pre', cmd)
-            cmd = 'ip -n {} link set $DEV1 up'.format(self.args.NAMES['NS'])
+            cmd = '$IP -n {} link set $DEV1 up'.format(self.args.NAMES['NS'])
             self._exec_cmd('pre', cmd)
             if self.args.device:
-                cmd = 'ip link set $DEV2 netns {}'.format(self.args.NAMES['NS'])
+                cmd = '$IP link set $DEV2 netns {}'.format(self.args.NAMES['NS'])
                 self._exec_cmd('pre', cmd)
-                cmd = 'ip -n {} link set $DEV2 up'.format(self.args.NAMES['NS'])
+                cmd = '$IP -n {} link set $DEV2 up'.format(self.args.NAMES['NS'])
                 self._exec_cmd('pre', cmd)
 
     def _ns_destroy(self):
@@ -115,7 +115,7 @@ class SubPlugin(TdcPlugin):
         devices as well)
         '''
         if self.args.namespace:
-            cmd = 'ip netns delete {}'.format(self.args.NAMES['NS'])
+            cmd = '$IP netns delete {}'.format(self.args.NAMES['NS'])
             self._exec_cmd('post', cmd)
 
     def _exec_cmd(self, stage, command):
index bf5ebf59c2d4b9ce18f3f4900c42afcd0f7b7985..9cdd2e31ac2c5bff88be689b6b95ec822ef22e66 100644 (file)
         "teardown": [
             "$TC actions flush action skbedit"
         ]
+    },
+    {
+        "id": "630c",
+        "name": "Add batch of 32 skbedit actions with all parameters and cookie",
+        "category": [
+            "actions",
+            "skbedit"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action skbedit",
+                0,
+                1,
+                255
+            ]
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit queue_mapping 2 priority 10 mark 7/0xaabbccdd ptype host inheritdsfield index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action skbedit",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "32",
+        "teardown": [
+            "$TC actions flush action skbedit"
+        ]
+    },
+    {
+        "id": "706d",
+        "name": "Delete batch of 32 skbedit actions with all parameters",
+        "category": [
+            "actions",
+            "skbedit"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action skbedit",
+                0,
+                1,
+                255
+            ],
+            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit queue_mapping 2 priority 10 mark 7/0xaabbccdd ptype host inheritdsfield index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action skbedit",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "0",
+        "teardown": []
     }
 ]
index cc7c7d75800809115bc22d62dbcd4c646a7f35d3..6503b1ce091f824dabbc3f25ddef6059cc6bce1f 100644 (file)
         "teardown": [
             "$TC actions flush action vlan"
         ]
+    },
+    {
+        "id": "294e",
+        "name": "Add batch of 32 vlan push actions with cookie",
+        "category": [
+            "actions",
+            "vlan"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action vlan",
+                0,
+                1,
+                255
+            ]
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan push protocol 802.1q id 4094 priority 7 pipe index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action vlan",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "32",
+        "teardown": [
+            "$TC actions flush action vlan"
+        ]
+    },
+    {
+        "id": "56f7",
+        "name": "Delete batch of 32 vlan push actions",
+        "category": [
+            "actions",
+            "vlan"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action vlan",
+                0,
+                1,
+                255
+            ],
+            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan push protocol 802.1q id 4094 priority 7 pipe index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action vlan",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "0",
+        "teardown": []
+    },
+    {
+        "id": "759f",
+        "name": "Add batch of 32 vlan pop actions with cookie",
+        "category": [
+            "actions",
+            "vlan"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action vlan",
+                0,
+                1,
+                255
+            ]
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan pop continue index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action vlan",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "32",
+        "teardown": [
+            "$TC actions flush action vlan"
+        ]
+    },
+    {
+        "id": "c84a",
+        "name": "Delete batch of 32 vlan pop actions",
+        "category": [
+            "actions",
+            "vlan"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action vlan",
+                0,
+                1,
+                255
+            ],
+            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan pop index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action vlan",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "0",
+        "teardown": []
     }
 ]
index 4602326b8f5b9dbe7bd2f9965088030acd5c871d..a4f4d4cf22c3b47c40acf7ae4c6d25d335e3b313 100644 (file)
@@ -451,7 +451,7 @@ static int test_vsys_x(void)
                printf("[OK]\tExecuting the vsyscall page failed: #PF(0x%lx)\n",
                       segv_err);
        } else {
-               printf("[FAILT]\tExecution failed with the wrong error: #PF(0x%lx)\n",
+               printf("[FAIL]\tExecution failed with the wrong error: #PF(0x%lx)\n",
                       segv_err);
                return 1;
        }
index aa316d99e035f8d7964264e5f85747c5328d9eb4..1fb6abe29b2fdb2bacfef75449860e8ddfac7d9b 100644 (file)
@@ -101,10 +101,6 @@ ifeq ($(SRCARCH),riscv)
 header-test- += linux/bpf_perf_event.h
 endif
 
-ifeq ($(SRCARCH),s390)
-header-test- += asm/zcrypt.h
-endif
-
 ifeq ($(SRCARCH),sparc)
 header-test- += asm/stat.h
 header-test- += asm/uctx.h
index f645c0fbf7ecef90aa7007709b90acf05756e558..35a069815baf1a4f970e9707460d677cc0e11907 100644 (file)
@@ -144,11 +144,6 @@ out_fail_alloc:
        return ret;
 }
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return false;
-}
-
 int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
 {
        return 0;
@@ -323,6 +318,17 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 
 void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
 {
+       /*
+        * If we're about to block (most likely because we've just hit a
+        * WFI), we need to sync back the state of the GIC CPU interface
+        * so that we have the lastest PMR and group enables. This ensures
+        * that kvm_arch_vcpu_runnable has up-to-date data to decide
+        * whether we have pending interrupts.
+        */
+       preempt_disable();
+       kvm_vgic_vmcr_sync(vcpu);
+       preempt_enable();
+
        kvm_vgic_v4_enable_doorbell(vcpu);
 }
 
@@ -340,6 +346,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        /* Set up the timer */
        kvm_timer_vcpu_init(vcpu);
 
+       kvm_pmu_vcpu_init(vcpu);
+
        kvm_arm_reset_debug_ptr(vcpu);
 
        return kvm_vgic_vcpu_init(vcpu);
@@ -727,7 +735,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                 * Ensure we set mode to IN_GUEST_MODE after we disable
                 * interrupts and before the final VCPU requests check.
                 * See the comment in kvm_vcpu_exiting_guest_mode() and
-                * Documentation/virtual/kvm/vcpu-requests.rst
+                * Documentation/virt/kvm/vcpu-requests.rst
                 */
                smp_store_mb(vcpu->mode, IN_GUEST_MODE);
 
index 254c5f190a3d660507f22e10799b36eddd160b8b..ccf1fde9836c1e2a5ae041899a0e7675e8837cc2 100644 (file)
@@ -349,8 +349,10 @@ void __hyp_text __vgic_v3_save_aprs(struct kvm_vcpu *vcpu)
        case 7:
                cpu_if->vgic_ap0r[3] = __vgic_v3_read_ap0rn(3);
                cpu_if->vgic_ap0r[2] = __vgic_v3_read_ap0rn(2);
+               /* Fall through */
        case 6:
                cpu_if->vgic_ap0r[1] = __vgic_v3_read_ap0rn(1);
+               /* Fall through */
        default:
                cpu_if->vgic_ap0r[0] = __vgic_v3_read_ap0rn(0);
        }
@@ -359,8 +361,10 @@ void __hyp_text __vgic_v3_save_aprs(struct kvm_vcpu *vcpu)
        case 7:
                cpu_if->vgic_ap1r[3] = __vgic_v3_read_ap1rn(3);
                cpu_if->vgic_ap1r[2] = __vgic_v3_read_ap1rn(2);
+               /* Fall through */
        case 6:
                cpu_if->vgic_ap1r[1] = __vgic_v3_read_ap1rn(1);
+               /* Fall through */
        default:
                cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
        }
@@ -382,8 +386,10 @@ void __hyp_text __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu)
        case 7:
                __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[3], 3);
                __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[2], 2);
+               /* Fall through */
        case 6:
                __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[1], 1);
+               /* Fall through */
        default:
                __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[0], 0);
        }
@@ -392,8 +398,10 @@ void __hyp_text __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu)
        case 7:
                __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[3], 3);
                __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[2], 2);
+               /* Fall through */
        case 6:
                __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[1], 1);
+               /* Fall through */
        default:
                __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[0], 0);
        }
index a8a6a0c883f1ba4585610cad9d1e14bc535d4d33..6af5c91337f251fc4a722afb80f9c60d78a0f65e 100644 (file)
@@ -86,6 +86,12 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
        unsigned int len;
        int mask;
 
+       /* Detect an already handled MMIO return */
+       if (unlikely(!vcpu->mmio_needed))
+               return 0;
+
+       vcpu->mmio_needed = 0;
+
        if (!run->mmio.is_write) {
                len = run->mmio.len;
                if (len > sizeof(unsigned long))
@@ -188,6 +194,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
        run->mmio.is_write      = is_write;
        run->mmio.phys_addr     = fault_ipa;
        run->mmio.len           = len;
+       vcpu->mmio_needed       = 1;
 
        if (!ret) {
                /* We handled the access successfully in the kernel. */
index 3dd8238ed2462eeeb04e5c7cfa2735e3782d02bd..362a01886bab9ef64ca89b61de1ff93ddf26e1bb 100644 (file)
@@ -214,6 +214,20 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
        kvm_pmu_release_perf_event(pmc);
 }
 
+/**
+ * kvm_pmu_vcpu_init - assign pmu counter idx for cpu
+ * @vcpu: The vcpu pointer
+ *
+ */
+void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       int i;
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+
+       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++)
+               pmu->pmc[i].idx = i;
+}
+
 /**
  * kvm_pmu_vcpu_reset - reset pmu state for cpu
  * @vcpu: The vcpu pointer
@@ -224,10 +238,8 @@ void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
        int i;
        struct kvm_pmu *pmu = &vcpu->arch.pmu;
 
-       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
+       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++)
                kvm_pmu_stop_counter(vcpu, &pmu->pmc[i]);
-               pmu->pmc[i].idx = i;
-       }
 
        bitmap_zero(vcpu->arch.pmu.chained, ARMV8_PMU_MAX_COUNTER_PAIRS);
 }
index bdbc297d06fb4676559dab05137a03d916d58273..e621b5d45b278b6e1d03f997849422ad3a94fe97 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/cpu.h>
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
+#include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
@@ -164,12 +165,18 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu0;
                kref_init(&irq->refcount);
-               if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+               switch (dist->vgic_model) {
+               case KVM_DEV_TYPE_ARM_VGIC_V2:
                        irq->targets = 0;
                        irq->group = 0;
-               } else {
+                       break;
+               case KVM_DEV_TYPE_ARM_VGIC_V3:
                        irq->mpidr = 0;
                        irq->group = 1;
+                       break;
+               default:
+                       kfree(dist->spis);
+                       return -EINVAL;
                }
        }
        return 0;
@@ -209,7 +216,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                irq->intid = i;
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu;
-               irq->targets = 1U << vcpu->vcpu_id;
                kref_init(&irq->refcount);
                if (vgic_irq_is_sgi(i)) {
                        /* SGIs */
@@ -219,11 +225,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                        /* PPIs */
                        irq->config = VGIC_CONFIG_LEVEL;
                }
-
-               if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
-                       irq->group = 1;
-               else
-                       irq->group = 0;
        }
 
        if (!irqchip_in_kernel(vcpu->kvm))
@@ -286,10 +287,19 @@ int vgic_init(struct kvm *kvm)
 
                for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
                        struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
-                       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+                       switch (dist->vgic_model) {
+                       case KVM_DEV_TYPE_ARM_VGIC_V3:
                                irq->group = 1;
-                       else
+                               irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+                               break;
+                       case KVM_DEV_TYPE_ARM_VGIC_V2:
                                irq->group = 0;
+                               irq->targets = 1U << idx;
+                               break;
+                       default:
+                               ret = -EINVAL;
+                               goto out;
+                       }
                }
        }
 
index 936962abc38d234ac77f385f1c46cbf0b8509905..c45e2d7e942fb6f55e4e96ece540fffc89283540 100644 (file)
@@ -250,7 +250,7 @@ static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
         * pending state of interrupt is latched in pending_latch variable.
         * Userspace will save and restore pending state and line_level
         * separately.
-        * Refer to Documentation/virtual/kvm/devices/arm-vgic-v3.txt
+        * Refer to Documentation/virt/kvm/devices/arm-vgic-v3.txt
         * for handling of ISPENDR and ICPENDR.
         */
        for (i = 0; i < len * 8; i++) {
index 3ba7278fb533be5acdba3c339358039eb6b472e0..0d090482720d2f79ee0af937672f969de728a275 100644 (file)
@@ -113,6 +113,22 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
+               if (vgic_irq_is_mapped_level(irq)) {
+                       bool was_high = irq->line_level;
+
+                       /*
+                        * We need to update the state of the interrupt because
+                        * the guest might have changed the state of the device
+                        * while the interrupt was disabled at the VGIC level.
+                        */
+                       irq->line_level = vgic_get_phys_line_level(irq);
+                       /*
+                        * Deactivate the physical interrupt so the GIC will let
+                        * us know when it is asserted again.
+                        */
+                       if (!irq->active && was_high && !irq->line_level)
+                               vgic_irq_set_phys_active(irq, false);
+               }
                irq->enabled = true;
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
 
@@ -195,6 +211,12 @@ static void vgic_hw_irq_spending(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        vgic_irq_set_phys_active(irq, true);
 }
 
+static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
+{
+       return (vgic_irq_is_sgi(irq->intid) &&
+               vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2);
+}
+
 void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
                              gpa_t addr, unsigned int len,
                              unsigned long val)
@@ -207,6 +229,12 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
+               /* GICD_ISPENDR0 SGI bits are WI */
+               if (is_vgic_v2_sgi(vcpu, irq)) {
+                       vgic_put_irq(vcpu->kvm, irq);
+                       continue;
+               }
+
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq->hw)
                        vgic_hw_irq_spending(vcpu, irq, is_uaccess);
@@ -254,6 +282,12 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
+               /* GICD_ICPENDR0 SGI bits are WI */
+               if (is_vgic_v2_sgi(vcpu, irq)) {
+                       vgic_put_irq(vcpu->kvm, irq);
+                       continue;
+               }
+
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                if (irq->hw)
index 6dd5ad706c927190152eb979dc2498b75d03a809..b00aa304c260eb412210cf26aa2b011dc51dfa88 100644 (file)
@@ -184,7 +184,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                if (vgic_irq_is_sgi(irq->intid)) {
                        u32 src = ffs(irq->source);
 
-                       BUG_ON(!src);
+                       if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n",
+                                          irq->intid))
+                               return;
+
                        val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
                        irq->source &= ~(1 << (src - 1));
                        if (irq->source) {
@@ -484,10 +487,17 @@ void vgic_v2_load(struct kvm_vcpu *vcpu)
                       kvm_vgic_global_state.vctrl_base + GICH_APR);
 }
 
-void vgic_v2_put(struct kvm_vcpu *vcpu)
+void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu)
 {
        struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
 
        cpu_if->vgic_vmcr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VMCR);
+}
+
+void vgic_v2_put(struct kvm_vcpu *vcpu)
+{
+       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+
+       vgic_v2_vmcr_sync(vcpu);
        cpu_if->vgic_apr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_APR);
 }
index c2c9ce009f6381556cf71f520c680af78fae4525..a4ad431c92a912d2b3a9330db301059858ebc62b 100644 (file)
@@ -167,7 +167,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
                        u32 src = ffs(irq->source);
 
-                       BUG_ON(!src);
+                       if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n",
+                                          irq->intid))
+                               return;
+
                        val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
                        irq->source &= ~(1 << (src - 1));
                        if (irq->source) {
@@ -662,12 +665,17 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
                __vgic_v3_activate_traps(vcpu);
 }
 
-void vgic_v3_put(struct kvm_vcpu *vcpu)
+void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
 
        if (likely(cpu_if->vgic_sre))
                cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr);
+}
+
+void vgic_v3_put(struct kvm_vcpu *vcpu)
+{
+       vgic_v3_vmcr_sync(vcpu);
 
        kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
 
index 04786c8ec77ed8e4a48b085c029ba2d03a008d4a..e7bde65ba67c0802582883c195052b96cc427caf 100644 (file)
@@ -254,6 +254,13 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
        bool penda, pendb;
        int ret;
 
+       /*
+        * list_sort may call this function with the same element when
+        * the list is fairly long.
+        */
+       if (unlikely(irqa == irqb))
+               return 0;
+
        raw_spin_lock(&irqa->irq_lock);
        raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
 
@@ -919,6 +926,17 @@ void kvm_vgic_put(struct kvm_vcpu *vcpu)
                vgic_v3_put(vcpu);
 }
 
+void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu)
+{
+       if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
+               return;
+
+       if (kvm_vgic_global_state.type == VGIC_V2)
+               vgic_v2_vmcr_sync(vcpu);
+       else
+               vgic_v3_vmcr_sync(vcpu);
+}
+
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 {
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
index 57205beaa981a11366dec8cf2ac1553e7056c271..797e05004d807a1041b4711488913f78f98636bb 100644 (file)
@@ -42,7 +42,7 @@
                            VGIC_AFFINITY_LEVEL(val, 3))
 
 /*
- * As per Documentation/virtual/kvm/devices/arm-vgic-v3.txt,
+ * As per Documentation/virt/kvm/devices/arm-vgic-v3.txt,
  * below macros are defined for CPUREG encoding.
  */
 #define KVM_REG_ARM_VGIC_SYSREG_OP0_MASK   0x000000000000c000
@@ -63,7 +63,7 @@
                                      KVM_REG_ARM_VGIC_SYSREG_OP2_MASK)
 
 /*
- * As per Documentation/virtual/kvm/devices/arm-vgic-its.txt,
+ * As per Documentation/virt/kvm/devices/arm-vgic-its.txt,
  * below macros are defined for ITS table entry encoding.
  */
 #define KVM_ITS_CTE_VALID_SHIFT                63
@@ -193,6 +193,7 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 void vgic_v2_init_lrs(void);
 void vgic_v2_load(struct kvm_vcpu *vcpu);
 void vgic_v2_put(struct kvm_vcpu *vcpu);
+void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu);
 
 void vgic_v2_save_state(struct kvm_vcpu *vcpu);
 void vgic_v2_restore_state(struct kvm_vcpu *vcpu);
@@ -223,6 +224,7 @@ bool vgic_v3_check_base(struct kvm *kvm);
 
 void vgic_v3_load(struct kvm_vcpu *vcpu);
 void vgic_v3_put(struct kvm_vcpu *vcpu);
+void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu);
 
 bool vgic_has_its(struct kvm *kvm);
 int kvm_vgic_register_its_device(void);
index 887f3b0c2b602d4cd4f81ebf137b8c04e112077c..c6a91b044d8d62d00a259590927b83d58b853394 100644 (file)
@@ -1855,8 +1855,7 @@ void kvm_set_pfn_dirty(kvm_pfn_t pfn)
        if (!kvm_is_reserved_pfn(pfn)) {
                struct page *page = pfn_to_page(pfn);
 
-               if (!PageReserved(page))
-                       SetPageDirty(page);
+               SetPageDirty(page);
        }
 }
 EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
@@ -2477,6 +2476,29 @@ static bool kvm_vcpu_eligible_for_directed_yield(struct kvm_vcpu *vcpu)
 #endif
 }
 
+/*
+ * Unlike kvm_arch_vcpu_runnable, this function is called outside
+ * a vcpu_load/vcpu_put pair.  However, for most architectures
+ * kvm_arch_vcpu_runnable does not require vcpu_load.
+ */
+bool __weak kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+       return kvm_arch_vcpu_runnable(vcpu);
+}
+
+static bool vcpu_dy_runnable(struct kvm_vcpu *vcpu)
+{
+       if (kvm_arch_dy_runnable(vcpu))
+               return true;
+
+#ifdef CONFIG_KVM_ASYNC_PF
+       if (!list_empty_careful(&vcpu->async_pf.done))
+               return true;
+#endif
+
+       return false;
+}
+
 void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
 {
        struct kvm *kvm = me->kvm;
@@ -2506,9 +2528,10 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
                                continue;
                        if (vcpu == me)
                                continue;
-                       if (swait_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
+                       if (swait_active(&vcpu->wq) && !vcpu_dy_runnable(vcpu))
                                continue;
-                       if (yield_to_kernel_mode && !kvm_arch_vcpu_in_kernel(vcpu))
+                       if (READ_ONCE(vcpu->preempted) && yield_to_kernel_mode &&
+                               !kvm_arch_vcpu_in_kernel(vcpu))
                                continue;
                        if (!kvm_vcpu_eligible_for_directed_yield(vcpu))
                                continue;
@@ -2591,30 +2614,20 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu)
        return anon_inode_getfd(name, &kvm_vcpu_fops, vcpu, O_RDWR | O_CLOEXEC);
 }
 
-static int kvm_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
+static void kvm_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
 {
+#ifdef __KVM_HAVE_ARCH_VCPU_DEBUGFS
        char dir_name[ITOA_MAX_LEN * 2];
-       int ret;
-
-       if (!kvm_arch_has_vcpu_debugfs())
-               return 0;
 
        if (!debugfs_initialized())
-               return 0;
+               return;
 
        snprintf(dir_name, sizeof(dir_name), "vcpu%d", vcpu->vcpu_id);
        vcpu->debugfs_dentry = debugfs_create_dir(dir_name,
-                                                               vcpu->kvm->debugfs_dentry);
-       if (!vcpu->debugfs_dentry)
-               return -ENOMEM;
-
-       ret = kvm_arch_create_vcpu_debugfs(vcpu);
-       if (ret < 0) {
-               debugfs_remove_recursive(vcpu->debugfs_dentry);
-               return ret;
-       }
+                                                 vcpu->kvm->debugfs_dentry);
 
-       return 0;
+       kvm_arch_create_vcpu_debugfs(vcpu);
+#endif
 }
 
 /*
@@ -2649,9 +2662,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        if (r)
                goto vcpu_destroy;
 
-       r = kvm_create_vcpu_debugfs(vcpu);
-       if (r)
-               goto vcpu_destroy;
+       kvm_create_vcpu_debugfs(vcpu);
 
        mutex_lock(&kvm->lock);
        if (kvm_get_vcpu_by_id(kvm, id)) {
@@ -4205,7 +4216,7 @@ static void kvm_sched_in(struct preempt_notifier *pn, int cpu)
 {
        struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
 
-       vcpu->preempted = false;
+       WRITE_ONCE(vcpu->preempted, false);
        WRITE_ONCE(vcpu->ready, false);
 
        kvm_arch_sched_in(vcpu, cpu);
@@ -4219,7 +4230,7 @@ static void kvm_sched_out(struct preempt_notifier *pn,
        struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
 
        if (current->state == TASK_RUNNING) {
-               vcpu->preempted = true;
+               WRITE_ONCE(vcpu->preempted, true);
                WRITE_ONCE(vcpu->ready, true);
        }
        kvm_arch_vcpu_put(vcpu);